Skip to content

Commit bbcd1eb

Browse files
authored
fix: make timeouts stricter (#40)
1 parent 3bdfeea commit bbcd1eb

File tree

2 files changed

+32
-14
lines changed

2 files changed

+32
-14
lines changed

src/http.js

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,23 +30,29 @@ const timeout = (promise, ms, abortController) => {
3030
return promise
3131
}
3232

33-
return new Promise((resolve, reject) => {
34-
const timeoutID = setTimeout(() => {
35-
reject(new TimeoutError())
36-
37-
abortController.abort()
38-
}, ms)
33+
const start = Date.now()
3934

40-
promise
41-
.then((result) => {
35+
return new Promise((resolve, reject) => {
36+
const after = (next) => {
37+
return (res) => {
4238
clearTimeout(timeoutID)
39+
const time = Date.now() - start
4340

44-
resolve(result)
45-
}, (err) => {
46-
clearTimeout(timeoutID)
41+
if (time >= ms) {
42+
abortController.abort()
43+
reject(new TimeoutError())
44+
return
45+
}
4746

48-
reject(err)
49-
})
47+
if (next) {
48+
next(res)
49+
}
50+
}
51+
}
52+
const timeoutID = setTimeout(after(), ms)
53+
54+
promise
55+
.then(after(resolve), after(reject))
5056
})
5157
}
5258

@@ -138,7 +144,13 @@ class HTTP {
138144
opts.headers.set('content-type', 'application/json')
139145
}
140146

141-
const response = await timeout(fetch(url, opts), opts.timeout, this.abortController)
147+
const response = await timeout(fetch(url, {
148+
...opts,
149+
150+
// node-fetch implements it's own timeout in an addition to the spec so do not
151+
// pass the timeout value on, otherwise there are two sources of timeout errors
152+
timeout: undefined
153+
}), opts.timeout, this.abortController)
142154

143155
if (!response.ok && opts.throwHttpErrors) {
144156
if (opts.handleError) {

test/http.spec.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ describe('http', function () {
2424
expect(rsp).to.be.deep.eq({ test: 'one' })
2525
})
2626

27+
it('makes a GET request with a really short timeout', function () {
28+
return expect(HTTP.get(`${process.env.ECHO_SERVER}/redirect?to=${encodeURI(`${process.env.ECHO_SERVER}/echo/query?test=one`)}`, {
29+
timeout: 1
30+
})).to.eventually.be.rejectedWith().instanceOf(HTTP.TimeoutError)
31+
})
32+
2733
it('makes a JSON request', async () => {
2834
const req = await HTTP.post(`${process.env.ECHO_SERVER}/echo`, {
2935
json: {

0 commit comments

Comments
 (0)