Skip to content

Commit

Permalink
Implement support for abort signal in XHR Gateway
Browse files Browse the repository at this point in the history
  • Loading branch information
klippx committed Sep 11, 2024
1 parent e77e123 commit b5ce4bc
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 32 deletions.
40 changes: 36 additions & 4 deletions spec/integration/browser/integration.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ describe('integration', () => {
})
})

describe('CSRF', () => {
integrationTestsForGateway(Fetch, { host: '/proxy' }, (gateway, params) => {
csrfSpec(forge(createManifest(params.host), gateway))
})
})

describe('with raw binary', () => {
it('GET /api/binary.pdf', (done) => {
const Client = forge(createManifest(params.host), gateway)
Expand Down Expand Up @@ -100,11 +106,37 @@ describe('integration', () => {
})
})
})
})

describe('CSRF', () => {
integrationTestsForGateway(Fetch, { host: '/proxy' }, (gateway, params) => {
csrfSpec(forge(createManifest(params.host), gateway))
describe('aborting a request', () => {
it('aborts the request', (done) => {
const Client = forge(
{
host: params.host,
fetch,
resources: {
Timeout: {
get: { path: '/api/timeout.json' },
},
},
},
gateway
)
const abortController = new AbortController()
const request = Client.Timeout.get({ waitTime: 666, signal: abortController.signal })
// Fire the request, but abort after 1ms
setTimeout(() => {
abortController.abort()
}, 1)
request
.then((response) => {
done.fail(`Expected this request to fail: ${errorMessage(response)}`)
})
.catch((response) => {
expect(response.status()).toEqual(400)
expect(response.error()).toMatch(/The operation was aborted/i)
done()
})
})
})
})
})
75 changes: 47 additions & 28 deletions spec/integration/node/integration.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ describe('integration', () => {
})

it('should call the callbacks', (done) => {
const Client = forge(createManifest(params.host))
const Client = forge(createManifest(params.host), gateway)
Client.Book.all().then(() => {
expect(gatewayConfigs.onRequestWillStart).toHaveBeenCalledWith(jasmine.any(Object))
expect(gatewayConfigs.onRequestSocketAssigned).toHaveBeenCalledWith(jasmine.any(Object))
Expand Down Expand Up @@ -126,14 +126,17 @@ describe('integration', () => {

describe('with raw binary', () => {
it('GET /api/binary.pdf', (done) => {
const Client = forge({
host: params.host,
resources: {
Binary: {
get: { path: '/api/binary.pdf', binary: true },
const Client = forge(
{
host: params.host,
resources: {
Binary: {
get: { path: '/api/binary.pdf', binary: true },
},
},
},
})
gateway
)
Client.Binary.get()
.then((response) => {
expect(response.status()).toEqual(200)
Expand All @@ -149,14 +152,17 @@ describe('integration', () => {

describe('on network errors', () => {
it('returns the original error', (done) => {
const Client = forge({
host: INVALID_ADDRESS,
resources: {
PlainText: {
get: { path: '/api/plain-text' },
const Client = forge(
{
host: INVALID_ADDRESS,
resources: {
PlainText: {
get: { path: '/api/plain-text' },
},
},
},
})
gateway
)
Client.PlainText.get()
.then((response) => {
done.fail(`Expected this request to fail: ${errorMessage(response)}`)
Expand All @@ -171,17 +177,23 @@ describe('integration', () => {

describe('aborting a request', () => {
it('aborts the request', (done) => {
const Client = forge({
host: params.host,
resources: {
Timeout: {
get: { path: '/api/timeout.json' },
const Client = forge(
{
host: params.host,
resources: {
Timeout: {
get: { path: '/api/timeout.json' },
},
},
},
})
gateway
)
const abortController = new AbortController()
const request = Client.Timeout.get({ waitTime: 666, signal: abortController.signal })
abortController.abort()
// Fire the request, but abort after 1ms
setTimeout(() => {
abortController.abort()
}, 1)
request
.then((response) => {
done.fail(`Expected this request to fail: ${errorMessage(response)}`)
Expand All @@ -196,6 +208,7 @@ describe('integration', () => {
})

describe('Fetch', () => {
const gateway = Fetch
const params = { host: 'http://localhost:9090' }

beforeAll(() => {
Expand All @@ -204,18 +217,24 @@ describe('integration', () => {

describe('aborting a request', () => {
it('aborts the request', (done) => {
const Client = forge({
host: params.host,
fetch,
resources: {
Timeout: {
get: { path: '/api/timeout.json' },
const Client = forge(
{
host: params.host,
fetch,
resources: {
Timeout: {
get: { path: '/api/timeout.json' },
},
},
},
})
gateway
)
const abortController = new AbortController()
const request = Client.Timeout.get({ waitTime: 666, signal: abortController.signal })
abortController.abort()
// Fire the request, but abort after 1ms
setTimeout(() => {
abortController.abort()
}, 1)
request
.then((response) => {
done.fail(`Expected this request to fail: ${errorMessage(response)}`)
Expand Down
18 changes: 18 additions & 0 deletions src/gateway/xhr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export class XHR extends Gateway {
this.setHeaders(xmlHttpRequest, {})
this.configureTimeout(xmlHttpRequest)
this.configureBinary(xmlHttpRequest)
this.configureAbort(xmlHttpRequest)
xmlHttpRequest.send()
}

Expand All @@ -31,6 +32,7 @@ export class XHR extends Gateway {
this.setHeaders(xmlHttpRequest, {})
this.configureTimeout(xmlHttpRequest)
this.configureBinary(xmlHttpRequest)
this.configureAbort(xmlHttpRequest)
xmlHttpRequest.send()
}

Expand Down Expand Up @@ -80,6 +82,21 @@ export class XHR extends Gateway {
}
}

configureAbort(xmlHttpRequest: XMLHttpRequest) {
const signal = this.request.signal()
if (signal) {
signal.addEventListener('abort', () => {
xmlHttpRequest.abort()
})
xmlHttpRequest.addEventListener('abort', () => {
this.dispatchClientError(
'The operation was aborted',
new Error('The operation was aborted')
)
})
}
}

configureCallbacks(xmlHttpRequest: XMLHttpRequest) {
xmlHttpRequest.addEventListener('load', () => {
if (this.canceled) {
Expand Down Expand Up @@ -128,6 +145,7 @@ export class XHR extends Gateway {
this.setHeaders(xmlHttpRequest, customHeaders)
this.configureTimeout(xmlHttpRequest)
this.configureBinary(xmlHttpRequest)
this.configureAbort(xmlHttpRequest)

xmlHttpRequest.send(body)
}
Expand Down

0 comments on commit b5ce4bc

Please sign in to comment.