@helia/verified-fetch 4.1.1 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -40
- package/dist/index.min.js +73 -534
- package/dist/index.min.js.map +4 -4
- package/dist/src/constants.d.ts +2 -0
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/constants.js +2 -0
- package/dist/src/constants.js.map +1 -1
- package/dist/src/index.d.ts +162 -68
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +7 -40
- package/dist/src/index.js.map +1 -1
- package/dist/src/plugins/index.d.ts +0 -5
- package/dist/src/plugins/index.d.ts.map +1 -1
- package/dist/src/plugins/index.js +0 -4
- package/dist/src/plugins/index.js.map +1 -1
- package/dist/src/plugins/plugin-base.d.ts +8 -9
- package/dist/src/plugins/plugin-base.d.ts.map +1 -1
- package/dist/src/plugins/plugin-base.js +5 -6
- package/dist/src/plugins/plugin-base.js.map +1 -1
- package/dist/src/plugins/plugin-handle-car.d.ts +3 -3
- package/dist/src/plugins/plugin-handle-car.d.ts.map +1 -1
- package/dist/src/plugins/plugin-handle-car.js +38 -39
- package/dist/src/plugins/plugin-handle-car.js.map +1 -1
- package/dist/src/plugins/plugin-handle-ipld.d.ts +12 -0
- package/dist/src/plugins/plugin-handle-ipld.d.ts.map +1 -0
- package/dist/src/plugins/plugin-handle-ipld.js +83 -0
- package/dist/src/plugins/plugin-handle-ipld.js.map +1 -0
- package/dist/src/plugins/plugin-handle-ipns-record.d.ts +3 -3
- package/dist/src/plugins/plugin-handle-ipns-record.d.ts.map +1 -1
- package/dist/src/plugins/plugin-handle-ipns-record.js +25 -34
- package/dist/src/plugins/plugin-handle-ipns-record.js.map +1 -1
- package/dist/src/plugins/plugin-handle-tar.d.ts +3 -3
- package/dist/src/plugins/plugin-handle-tar.d.ts.map +1 -1
- package/dist/src/plugins/plugin-handle-tar.js +20 -22
- package/dist/src/plugins/plugin-handle-tar.js.map +1 -1
- package/dist/src/plugins/plugin-handle-unixfs.d.ts +14 -0
- package/dist/src/plugins/plugin-handle-unixfs.d.ts.map +1 -0
- package/dist/src/plugins/plugin-handle-unixfs.js +180 -0
- package/dist/src/plugins/plugin-handle-unixfs.js.map +1 -0
- package/dist/src/plugins/types.d.ts +1 -77
- package/dist/src/plugins/types.d.ts.map +1 -1
- package/dist/src/url-resolver.d.ts +29 -11
- package/dist/src/url-resolver.d.ts.map +1 -1
- package/dist/src/url-resolver.js +152 -74
- package/dist/src/url-resolver.js.map +1 -1
- package/dist/src/utils/content-type-parser.d.ts.map +1 -1
- package/dist/src/utils/content-type-parser.js +4 -3
- package/dist/src/utils/content-type-parser.js.map +1 -1
- package/dist/src/utils/content-types.d.ts +26 -0
- package/dist/src/utils/content-types.d.ts.map +1 -0
- package/dist/src/utils/content-types.js +137 -0
- package/dist/src/utils/content-types.js.map +1 -0
- package/dist/src/utils/convert-output.d.ts +17 -0
- package/dist/src/utils/convert-output.d.ts.map +1 -0
- package/dist/src/utils/convert-output.js +176 -0
- package/dist/src/utils/convert-output.js.map +1 -0
- package/dist/src/utils/error-to-response.d.ts +3 -0
- package/dist/src/utils/error-to-response.d.ts.map +1 -0
- package/dist/src/utils/error-to-response.js +40 -0
- package/dist/src/utils/error-to-response.js.map +1 -0
- package/dist/src/utils/get-content-disposition-filename.d.ts +1 -1
- package/dist/src/utils/get-content-disposition-filename.d.ts.map +1 -1
- package/dist/src/utils/get-content-disposition-filename.js +4 -0
- package/dist/src/utils/get-content-disposition-filename.js.map +1 -1
- package/dist/src/utils/get-e-tag.d.ts +20 -15
- package/dist/src/utils/get-e-tag.d.ts.map +1 -1
- package/dist/src/utils/get-e-tag.js +8 -22
- package/dist/src/utils/get-e-tag.js.map +1 -1
- package/dist/src/utils/get-offset-and-length.d.ts +12 -2
- package/dist/src/utils/get-offset-and-length.d.ts.map +1 -1
- package/dist/src/utils/get-offset-and-length.js +63 -21
- package/dist/src/utils/get-offset-and-length.js.map +1 -1
- package/dist/src/utils/get-range-header.d.ts +22 -0
- package/dist/src/utils/get-range-header.d.ts.map +1 -0
- package/dist/src/utils/get-range-header.js +69 -0
- package/dist/src/utils/get-range-header.js.map +1 -0
- package/dist/src/utils/parse-url-string.d.ts +2 -1
- package/dist/src/utils/parse-url-string.d.ts.map +1 -1
- package/dist/src/utils/parse-url-string.js +46 -71
- package/dist/src/utils/parse-url-string.js.map +1 -1
- package/dist/src/utils/resource-to-cache-key.d.ts +3 -3
- package/dist/src/utils/resource-to-cache-key.js +5 -5
- package/dist/src/utils/resource-to-cache-key.js.map +1 -1
- package/dist/src/utils/response-headers.d.ts +4 -14
- package/dist/src/utils/response-headers.d.ts.map +1 -1
- package/dist/src/utils/response-headers.js +36 -36
- package/dist/src/utils/response-headers.js.map +1 -1
- package/dist/src/utils/responses.d.ts +30 -11
- package/dist/src/utils/responses.d.ts.map +1 -1
- package/dist/src/utils/responses.js +146 -39
- package/dist/src/utils/responses.js.map +1 -1
- package/dist/src/verified-fetch.d.ts +16 -15
- package/dist/src/verified-fetch.d.ts.map +1 -1
- package/dist/src/verified-fetch.js +302 -238
- package/dist/src/verified-fetch.js.map +1 -1
- package/dist/typedoc-urls.json +64 -45
- package/package.json +4 -3
- package/src/constants.ts +3 -0
- package/src/index.ts +199 -68
- package/src/plugins/index.ts +0 -6
- package/src/plugins/plugin-base.ts +8 -10
- package/src/plugins/plugin-handle-car.ts +48 -46
- package/src/plugins/plugin-handle-ipld.ts +93 -0
- package/src/plugins/plugin-handle-ipns-record.ts +31 -41
- package/src/plugins/plugin-handle-tar.ts +25 -29
- package/src/plugins/plugin-handle-unixfs.ts +217 -0
- package/src/plugins/types.ts +0 -86
- package/src/url-resolver.ts +197 -83
- package/src/utils/content-type-parser.ts +4 -3
- package/src/utils/content-types.ts +159 -0
- package/src/utils/convert-output.ts +187 -0
- package/src/utils/error-to-response.ts +49 -0
- package/src/utils/get-content-disposition-filename.ts +7 -1
- package/src/utils/get-e-tag.ts +26 -35
- package/src/utils/get-offset-and-length.ts +75 -21
- package/src/utils/get-range-header.ts +107 -0
- package/src/utils/parse-url-string.ts +51 -80
- package/src/utils/resource-to-cache-key.ts +5 -5
- package/src/utils/response-headers.ts +40 -41
- package/src/utils/responses.ts +186 -45
- package/src/verified-fetch.ts +353 -270
- package/dist/src/plugins/plugin-handle-byte-range-context.d.ts +0 -14
- package/dist/src/plugins/plugin-handle-byte-range-context.d.ts.map +0 -1
- package/dist/src/plugins/plugin-handle-byte-range-context.js +0 -25
- package/dist/src/plugins/plugin-handle-byte-range-context.js.map +0 -1
- package/dist/src/plugins/plugin-handle-cbor.d.ts +0 -17
- package/dist/src/plugins/plugin-handle-cbor.d.ts.map +0 -1
- package/dist/src/plugins/plugin-handle-cbor.js +0 -94
- package/dist/src/plugins/plugin-handle-cbor.js.map +0 -1
- package/dist/src/plugins/plugin-handle-dag-cbor-html-preview.d.ts +0 -27
- package/dist/src/plugins/plugin-handle-dag-cbor-html-preview.d.ts.map +0 -1
- package/dist/src/plugins/plugin-handle-dag-cbor-html-preview.js +0 -279
- package/dist/src/plugins/plugin-handle-dag-cbor-html-preview.js.map +0 -1
- package/dist/src/plugins/plugin-handle-dag-cbor.d.ts +0 -17
- package/dist/src/plugins/plugin-handle-dag-cbor.d.ts.map +0 -1
- package/dist/src/plugins/plugin-handle-dag-cbor.js +0 -66
- package/dist/src/plugins/plugin-handle-dag-cbor.js.map +0 -1
- package/dist/src/plugins/plugin-handle-dag-pb.d.ts +0 -17
- package/dist/src/plugins/plugin-handle-dag-pb.d.ts.map +0 -1
- package/dist/src/plugins/plugin-handle-dag-pb.js +0 -209
- package/dist/src/plugins/plugin-handle-dag-pb.js.map +0 -1
- package/dist/src/plugins/plugin-handle-dag-walk.d.ts +0 -21
- package/dist/src/plugins/plugin-handle-dag-walk.d.ts.map +0 -1
- package/dist/src/plugins/plugin-handle-dag-walk.js +0 -95
- package/dist/src/plugins/plugin-handle-dag-walk.js.map +0 -1
- package/dist/src/plugins/plugin-handle-dir-index-html.d.ts +0 -10
- package/dist/src/plugins/plugin-handle-dir-index-html.d.ts.map +0 -1
- package/dist/src/plugins/plugin-handle-dir-index-html.js +0 -59
- package/dist/src/plugins/plugin-handle-dir-index-html.js.map +0 -1
- package/dist/src/plugins/plugin-handle-json.d.ts +0 -12
- package/dist/src/plugins/plugin-handle-json.d.ts.map +0 -1
- package/dist/src/plugins/plugin-handle-json.js +0 -73
- package/dist/src/plugins/plugin-handle-json.js.map +0 -1
- package/dist/src/plugins/plugin-handle-raw.d.ts +0 -9
- package/dist/src/plugins/plugin-handle-raw.d.ts.map +0 -1
- package/dist/src/plugins/plugin-handle-raw.js +0 -92
- package/dist/src/plugins/plugin-handle-raw.js.map +0 -1
- package/dist/src/plugins/plugins.d.ts +0 -6
- package/dist/src/plugins/plugins.d.ts.map +0 -1
- package/dist/src/plugins/plugins.js +0 -6
- package/dist/src/plugins/plugins.js.map +0 -1
- package/dist/src/utils/byte-range-context.d.ts +0 -103
- package/dist/src/utils/byte-range-context.d.ts.map +0 -1
- package/dist/src/utils/byte-range-context.js +0 -504
- package/dist/src/utils/byte-range-context.js.map +0 -1
- package/dist/src/utils/dag-cbor-to-safe-json.d.ts +0 -15
- package/dist/src/utils/dag-cbor-to-safe-json.d.ts.map +0 -1
- package/dist/src/utils/dag-cbor-to-safe-json.js +0 -54
- package/dist/src/utils/dag-cbor-to-safe-json.js.map +0 -1
- package/dist/src/utils/dir-index-html.d.ts +0 -19
- package/dist/src/utils/dir-index-html.d.ts.map +0 -1
- package/dist/src/utils/dir-index-html.js +0 -438
- package/dist/src/utils/dir-index-html.js.map +0 -1
- package/dist/src/utils/get-peer-id-from-string.d.ts +0 -3
- package/dist/src/utils/get-peer-id-from-string.d.ts.map +0 -1
- package/dist/src/utils/get-peer-id-from-string.js +0 -10
- package/dist/src/utils/get-peer-id-from-string.js.map +0 -1
- package/dist/src/utils/get-resolved-accept-header.d.ts +0 -9
- package/dist/src/utils/get-resolved-accept-header.d.ts.map +0 -1
- package/dist/src/utils/get-resolved-accept-header.js +0 -27
- package/dist/src/utils/get-resolved-accept-header.js.map +0 -1
- package/dist/src/utils/get-stream-from-async-iterable.d.ts +0 -9
- package/dist/src/utils/get-stream-from-async-iterable.d.ts.map +0 -1
- package/dist/src/utils/get-stream-from-async-iterable.js +0 -43
- package/dist/src/utils/get-stream-from-async-iterable.js.map +0 -1
- package/dist/src/utils/handle-redirects.d.ts +0 -16
- package/dist/src/utils/handle-redirects.d.ts.map +0 -1
- package/dist/src/utils/handle-redirects.js +0 -84
- package/dist/src/utils/handle-redirects.js.map +0 -1
- package/dist/src/utils/is-accept-explicit.d.ts +0 -15
- package/dist/src/utils/is-accept-explicit.d.ts.map +0 -1
- package/dist/src/utils/is-accept-explicit.js +0 -26
- package/dist/src/utils/is-accept-explicit.js.map +0 -1
- package/dist/src/utils/request-headers.d.ts +0 -13
- package/dist/src/utils/request-headers.d.ts.map +0 -1
- package/dist/src/utils/request-headers.js +0 -63
- package/dist/src/utils/request-headers.js.map +0 -1
- package/dist/src/utils/select-output-type.d.ts +0 -17
- package/dist/src/utils/select-output-type.d.ts.map +0 -1
- package/dist/src/utils/select-output-type.js +0 -153
- package/dist/src/utils/select-output-type.js.map +0 -1
- package/dist/src/utils/tlru.d.ts +0 -15
- package/dist/src/utils/tlru.d.ts.map +0 -1
- package/dist/src/utils/tlru.js +0 -34
- package/dist/src/utils/tlru.js.map +0 -1
- package/dist/src/utils/walk-path.d.ts +0 -27
- package/dist/src/utils/walk-path.d.ts.map +0 -1
- package/dist/src/utils/walk-path.js +0 -45
- package/dist/src/utils/walk-path.js.map +0 -1
- package/src/plugins/plugin-handle-byte-range-context.ts +0 -30
- package/src/plugins/plugin-handle-cbor.ts +0 -107
- package/src/plugins/plugin-handle-dag-cbor-html-preview.ts +0 -295
- package/src/plugins/plugin-handle-dag-cbor.ts +0 -83
- package/src/plugins/plugin-handle-dag-pb.ts +0 -248
- package/src/plugins/plugin-handle-dag-walk.ts +0 -110
- package/src/plugins/plugin-handle-dir-index-html.ts +0 -72
- package/src/plugins/plugin-handle-json.ts +0 -80
- package/src/plugins/plugin-handle-raw.ts +0 -110
- package/src/plugins/plugins.ts +0 -5
- package/src/utils/byte-range-context.ts +0 -597
- package/src/utils/dag-cbor-to-safe-json.ts +0 -63
- package/src/utils/dir-index-html.ts +0 -505
- package/src/utils/get-peer-id-from-string.ts +0 -12
- package/src/utils/get-resolved-accept-header.ts +0 -42
- package/src/utils/get-stream-from-async-iterable.ts +0 -49
- package/src/utils/handle-redirects.ts +0 -109
- package/src/utils/is-accept-explicit.ts +0 -38
- package/src/utils/request-headers.ts +0 -65
- package/src/utils/select-output-type.ts +0 -175
- package/src/utils/tlru.ts +0 -42
- package/src/utils/walk-path.ts +0 -69
package/src/utils/responses.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
1
|
+
import itToBrowserReadableStream from 'it-to-browser-readablestream'
|
|
2
|
+
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
|
3
|
+
import { rangeToOffsetAndLength } from './get-offset-and-length.ts'
|
|
4
|
+
import { getContentRangeHeader } from './response-headers.ts'
|
|
5
|
+
import type { SupportedBodyTypes, ContentType } from '../index.js'
|
|
6
|
+
import type { Range, RangeHeader } from './get-range-header.ts'
|
|
4
7
|
|
|
5
8
|
function setField (response: Response, name: string, value: string | boolean): void {
|
|
6
9
|
Object.defineProperty(response, name, {
|
|
@@ -12,17 +15,22 @@ function setField (response: Response, name: string, value: string | boolean): v
|
|
|
12
15
|
}
|
|
13
16
|
|
|
14
17
|
function setType (response: Response, value: 'basic' | 'cors' | 'error' | 'opaque' | 'opaqueredirect'): void {
|
|
15
|
-
|
|
18
|
+
if (response.type !== value) {
|
|
19
|
+
setField(response, 'type', value)
|
|
20
|
+
}
|
|
16
21
|
}
|
|
17
22
|
|
|
18
|
-
function setUrl (response: Response, value: string): void {
|
|
23
|
+
function setUrl (response: Response, value: string | URL): void {
|
|
24
|
+
value = value.toString()
|
|
19
25
|
const fragmentStart = value.indexOf('#')
|
|
20
26
|
|
|
21
27
|
if (fragmentStart > -1) {
|
|
22
28
|
value = value.substring(0, fragmentStart)
|
|
23
29
|
}
|
|
24
30
|
|
|
25
|
-
|
|
31
|
+
if (response.url !== value) {
|
|
32
|
+
setField(response, 'url', value)
|
|
33
|
+
}
|
|
26
34
|
}
|
|
27
35
|
|
|
28
36
|
function setRedirected (response: Response): void {
|
|
@@ -64,6 +72,26 @@ export function internalServerErrorResponse (url: string, body?: SupportedBodyTy
|
|
|
64
72
|
return response
|
|
65
73
|
}
|
|
66
74
|
|
|
75
|
+
/**
|
|
76
|
+
* A 504 Gateway Timeout for when a request made to an upstream server timed out
|
|
77
|
+
*/
|
|
78
|
+
export function gatewayTimeoutResponse (url: string, body?: SupportedBodyTypes, init?: ResponseInit): Response {
|
|
79
|
+
const response = new Response(body, {
|
|
80
|
+
...(init ?? {}),
|
|
81
|
+
status: 504,
|
|
82
|
+
statusText: 'Gateway Timeout'
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
setType(response, 'basic')
|
|
86
|
+
setUrl(response, url)
|
|
87
|
+
|
|
88
|
+
return response
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* A 502 Bad Gateway is for when an invalid response was received from an
|
|
93
|
+
* upstream server.
|
|
94
|
+
*/
|
|
67
95
|
export function badGatewayResponse (url: string, body?: SupportedBodyTypes, init?: ResponseInit): Response {
|
|
68
96
|
const response = new Response(body, {
|
|
69
97
|
...(init ?? {}),
|
|
@@ -91,11 +119,17 @@ export function notImplementedResponse (url: string, body?: SupportedBodyTypes,
|
|
|
91
119
|
return response
|
|
92
120
|
}
|
|
93
121
|
|
|
94
|
-
export function notAcceptableResponse (url: string,
|
|
95
|
-
const
|
|
122
|
+
export function notAcceptableResponse (url: string | URL, acceptable: ContentType[], init?: ResponseInit): Response {
|
|
123
|
+
const headers = new Headers(init?.headers)
|
|
124
|
+
headers.set('content-type', 'application/json')
|
|
125
|
+
|
|
126
|
+
const response = new Response(JSON.stringify({
|
|
127
|
+
acceptable: acceptable.map(contentType => contentType.mediaType)
|
|
128
|
+
}), {
|
|
96
129
|
...(init ?? {}),
|
|
97
130
|
status: 406,
|
|
98
|
-
statusText: 'Not Acceptable'
|
|
131
|
+
statusText: 'Not Acceptable',
|
|
132
|
+
headers
|
|
99
133
|
})
|
|
100
134
|
|
|
101
135
|
setType(response, 'basic')
|
|
@@ -125,6 +159,7 @@ export function badRequestResponse (url: string, errors: Error | Error[], init?:
|
|
|
125
159
|
// stacktrace of the single error, or the stacktrace of the last error in the array
|
|
126
160
|
let stack: string | undefined
|
|
127
161
|
let convertedErrors: Array<{ message: string, stack: string }> | undefined
|
|
162
|
+
|
|
128
163
|
if (isArrayOfErrors(errors)) {
|
|
129
164
|
stack = errors[errors.length - 1].stack
|
|
130
165
|
convertedErrors = errors.map(e => ({ message: e.message, stack: e.stack ?? '' }))
|
|
@@ -171,70 +206,176 @@ export function movedPermanentlyResponse (url: string, location: string, init?:
|
|
|
171
206
|
return response
|
|
172
207
|
}
|
|
173
208
|
|
|
174
|
-
interface
|
|
175
|
-
|
|
176
|
-
|
|
209
|
+
export interface PartialContent {
|
|
210
|
+
/**
|
|
211
|
+
* Yield data from the content starting at `start` (or 0) inclusive and ending
|
|
212
|
+
* at `end` exclusive
|
|
213
|
+
*/
|
|
214
|
+
(offset: number, length: number): AsyncGenerator<Uint8Array>
|
|
177
215
|
}
|
|
178
216
|
|
|
179
|
-
export function
|
|
180
|
-
|
|
181
|
-
|
|
217
|
+
export function partialContentResponse (url: string, getSlice: PartialContent, range: RangeHeader, documentSize: number | bigint, init?: ResponseOptions): Response {
|
|
218
|
+
let response: Response
|
|
219
|
+
|
|
220
|
+
if (range.ranges.length === 1) {
|
|
221
|
+
response = singleRangeResponse(url, getSlice, range.ranges[0], documentSize, init)
|
|
222
|
+
} else if (range.ranges.length > 1) {
|
|
223
|
+
response = multiRangeResponse(url, getSlice, range, documentSize, init)
|
|
224
|
+
} else {
|
|
225
|
+
return notSatisfiableResponse(url, documentSize)
|
|
182
226
|
}
|
|
183
227
|
|
|
184
|
-
if (
|
|
185
|
-
|
|
228
|
+
if (init?.redirected === true) {
|
|
229
|
+
setRedirected(response)
|
|
186
230
|
}
|
|
187
231
|
|
|
188
|
-
|
|
232
|
+
setType(response, 'basic')
|
|
233
|
+
setUrl(response, url)
|
|
234
|
+
|
|
235
|
+
return response
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function singleRangeResponse (url: string, getSlice: PartialContent, range: Range, documentSize: number | bigint, init?: ResponseOptions): Response {
|
|
189
239
|
try {
|
|
190
|
-
//
|
|
240
|
+
// create headers object with any initial headers from init
|
|
191
241
|
const headers = new Headers(init?.headers)
|
|
242
|
+
const { offset, length } = rangeToOffsetAndLength(documentSize, range.start, range.end)
|
|
192
243
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
if (byteRangeContext.isMultiRangeRequest) {
|
|
200
|
-
headers.set('content-type', 'multipart/byteranges')
|
|
201
|
-
} else {
|
|
202
|
-
headers.set('content-range', byteRangeContext.contentRangeHeaderValue)
|
|
203
|
-
}
|
|
204
|
-
}
|
|
244
|
+
headers.set('content-length', `${length}`)
|
|
245
|
+
|
|
246
|
+
// see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Range
|
|
247
|
+
headers.set('content-range', getContentRangeHeader(documentSize, range.start, range.end))
|
|
248
|
+
|
|
249
|
+
const stream = itToBrowserReadableStream(getSlice(offset, length))
|
|
205
250
|
|
|
206
|
-
|
|
251
|
+
return new Response(stream, {
|
|
207
252
|
...(init ?? {}),
|
|
208
253
|
status: 206,
|
|
209
254
|
statusText: 'Partial Content',
|
|
210
255
|
headers
|
|
211
256
|
})
|
|
212
|
-
} catch (
|
|
213
|
-
|
|
214
|
-
|
|
257
|
+
} catch (err: any) {
|
|
258
|
+
if (err.name === 'InvalidRangeError') {
|
|
259
|
+
return notSatisfiableResponse(url, documentSize, init)
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return internalServerErrorResponse(url, '', init)
|
|
215
263
|
}
|
|
264
|
+
}
|
|
216
265
|
|
|
217
|
-
|
|
218
|
-
|
|
266
|
+
/**
|
|
267
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Range_requests
|
|
268
|
+
*/
|
|
269
|
+
function multiRangeResponse (url: string, getSlice: PartialContent, range: RangeHeader, documentSize: number | bigint, init?: ResponseOptions): Response {
|
|
270
|
+
// create headers object with any initial headers from init
|
|
271
|
+
const headers = new Headers(init?.headers)
|
|
272
|
+
|
|
273
|
+
const contentType = headers.get('content-type')
|
|
274
|
+
|
|
275
|
+
if (contentType == null) {
|
|
276
|
+
throw new Error('Content-Type header must be set')
|
|
219
277
|
}
|
|
220
278
|
|
|
221
|
-
|
|
222
|
-
setUrl(response, url)
|
|
279
|
+
headers.delete('content-type')
|
|
223
280
|
|
|
224
|
-
|
|
281
|
+
let contentLength = 0n
|
|
282
|
+
|
|
283
|
+
// calculate content range based on range headers
|
|
284
|
+
const rangeHeaders = range.ranges.map(({ start, end }) => {
|
|
285
|
+
const header = uint8ArrayFromString([
|
|
286
|
+
`--${range.multipartBoundary}`,
|
|
287
|
+
|
|
288
|
+
// content-type of multipart part
|
|
289
|
+
`Content-Type: ${contentType}`,
|
|
290
|
+
|
|
291
|
+
// see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Range
|
|
292
|
+
`Content-Range: ${getContentRangeHeader(documentSize, start, end)}`,
|
|
293
|
+
'',
|
|
294
|
+
''
|
|
295
|
+
].join('\r\n'))
|
|
296
|
+
|
|
297
|
+
contentLength += BigInt(header.byteLength) + (BigInt(end ?? documentSize) - BigInt(start ?? 0))
|
|
298
|
+
|
|
299
|
+
return header
|
|
300
|
+
})
|
|
301
|
+
|
|
302
|
+
const trailer = uint8ArrayFromString([
|
|
303
|
+
`--${range.multipartBoundary}--`,
|
|
304
|
+
''
|
|
305
|
+
].join('\r\n'))
|
|
306
|
+
|
|
307
|
+
contentLength += BigInt(trailer.byteLength)
|
|
308
|
+
|
|
309
|
+
// content length is the expected length of all multipart parts
|
|
310
|
+
headers.set('content-length', `${contentLength}`)
|
|
311
|
+
|
|
312
|
+
// content type of response is multipart
|
|
313
|
+
headers.set('content-type', `multipart/byteranges; boundary=${range.multipartBoundary}`)
|
|
314
|
+
|
|
315
|
+
const stream = itToBrowserReadableStream(async function * () {
|
|
316
|
+
for (let i = 0; i < rangeHeaders.length; i++) {
|
|
317
|
+
yield rangeHeaders[i]
|
|
318
|
+
|
|
319
|
+
const { offset, length } = rangeToOffsetAndLength(documentSize, range.ranges[i].start, range.ranges[i].end)
|
|
320
|
+
yield * getSlice(offset, length)
|
|
321
|
+
|
|
322
|
+
yield uint8ArrayFromString('\r\n')
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
yield trailer
|
|
326
|
+
}())
|
|
327
|
+
|
|
328
|
+
return new Response(stream, {
|
|
329
|
+
...(init ?? {}),
|
|
330
|
+
status: 206,
|
|
331
|
+
statusText: 'Partial Content',
|
|
332
|
+
headers
|
|
333
|
+
})
|
|
225
334
|
}
|
|
226
335
|
|
|
227
336
|
/**
|
|
228
|
-
* We likely need to catch errors handled by upstream helia libraries if
|
|
337
|
+
* We likely need to catch errors handled by upstream helia libraries if
|
|
338
|
+
* range-request throws an error. Some examples:
|
|
339
|
+
*
|
|
229
340
|
* - The range is out of bounds
|
|
230
341
|
* - The range is invalid
|
|
231
342
|
* - The range is not supported for the given type
|
|
232
343
|
*/
|
|
233
|
-
export function
|
|
234
|
-
const
|
|
235
|
-
|
|
344
|
+
export function notSatisfiableResponse (url: string, documentSize?: number | bigint | string, init?: ResponseInit): Response {
|
|
345
|
+
const headers = new Headers(init?.headers)
|
|
346
|
+
|
|
347
|
+
if (documentSize != null) {
|
|
348
|
+
headers.set('content-range', `bytes */${documentSize}`)
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
const response = new Response('Range Not Satisfiable', {
|
|
352
|
+
...init,
|
|
353
|
+
headers,
|
|
236
354
|
status: 416,
|
|
237
|
-
statusText: '
|
|
355
|
+
statusText: 'Range Not Satisfiable'
|
|
356
|
+
})
|
|
357
|
+
|
|
358
|
+
setType(response, 'basic')
|
|
359
|
+
setUrl(response, url)
|
|
360
|
+
|
|
361
|
+
return response
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Error to indicate that request was formally correct, but Gateway is unable to
|
|
366
|
+
* return requested data under the additional (usually cache-related) conditions
|
|
367
|
+
* sent by the client.
|
|
368
|
+
*
|
|
369
|
+
* @see https://specs.ipfs.tech/http-gateways/path-gateway/#412-precondition-failed
|
|
370
|
+
*/
|
|
371
|
+
export function preconditionFailedResponse (url: string, init?: ResponseInit): Response {
|
|
372
|
+
const headers = new Headers(init?.headers)
|
|
373
|
+
|
|
374
|
+
const response = new Response('Precondition Failed', {
|
|
375
|
+
...init,
|
|
376
|
+
headers,
|
|
377
|
+
status: 412,
|
|
378
|
+
statusText: 'Precondition Failed'
|
|
238
379
|
})
|
|
239
380
|
|
|
240
381
|
setType(response, 'basic')
|