Skip to content

Commit 3f927b8

Browse files
authored
feat: add support for if-match on retry handler (#3144)
1 parent 77a7947 commit 3f927b8

File tree

2 files changed

+339
-14
lines changed

2 files changed

+339
-14
lines changed

lib/handler/retry-handler.js

+21-14
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@ const { isDisturbed, parseHeaders, parseRangeHeader } = require('../core/util')
77

88
function calculateRetryAfterHeader (retryAfter) {
99
const current = Date.now()
10-
const diff = new Date(retryAfter).getTime() - current
11-
12-
return diff
10+
return new Date(retryAfter).getTime() - current
1311
}
1412

1513
class RetryHandler {
@@ -116,11 +114,7 @@ class RetryHandler {
116114
const { counter } = state
117115

118116
// Any code that is not a Undici's originated and allowed to retry
119-
if (
120-
code &&
121-
code !== 'UND_ERR_REQ_RETRY' &&
122-
!errorCodes.includes(code)
123-
) {
117+
if (code && code !== 'UND_ERR_REQ_RETRY' && !errorCodes.includes(code)) {
124118
cb(err)
125119
return
126120
}
@@ -246,10 +240,7 @@ class RetryHandler {
246240
start != null && Number.isFinite(start),
247241
'content-range mismatch'
248242
)
249-
assert(
250-
end != null && Number.isFinite(end),
251-
'invalid content-length'
252-
)
243+
assert(end != null && Number.isFinite(end), 'invalid content-length')
253244

254245
this.start = start
255246
this.end = end
@@ -270,6 +261,13 @@ class RetryHandler {
270261
this.resume = resume
271262
this.etag = headers.etag != null ? headers.etag : null
272263

264+
// Weak etags are not useful for comparison nor cache
265+
// for instance not safe to assume if the response is byte-per-byte
266+
// equal
267+
if (this.etag != null && this.etag.startsWith('W/')) {
268+
this.etag = null
269+
}
270+
273271
return this.handler.onHeaders(
274272
statusCode,
275273
rawHeaders,
@@ -308,7 +306,9 @@ class RetryHandler {
308306
// and server error response
309307
if (this.retryCount - this.retryCountCheckpoint > 0) {
310308
// We count the difference between the last checkpoint and the current retry count
311-
this.retryCount = this.retryCountCheckpoint + (this.retryCount - this.retryCountCheckpoint)
309+
this.retryCount =
310+
this.retryCountCheckpoint +
311+
(this.retryCount - this.retryCountCheckpoint)
312312
} else {
313313
this.retryCount += 1
314314
}
@@ -328,11 +328,18 @@ class RetryHandler {
328328
}
329329

330330
if (this.start !== 0) {
331+
const headers = { range: `bytes=${this.start}-${this.end ?? ''}` }
332+
333+
// Weak etag check - weak etags will make comparison algorithms never match
334+
if (this.etag != null) {
335+
headers['if-match'] = this.etag
336+
}
337+
331338
this.opts = {
332339
...this.opts,
333340
headers: {
334341
...this.opts.headers,
335-
range: `bytes=${this.start}-${this.end ?? ''}`
342+
...headers
336343
}
337344
}
338345
}

0 commit comments

Comments
 (0)