-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: support redirects for UnixFS directories
Adds support for simulating redirects for UnixFS directories. We're somewhat in uncharted water here because window.fetch does this transparently unless you specify a `redirect` option, none of which actually allow you to follow a redirect. The states we can be in are: 1. URL: `ipfs://QmFoo/dir/` - Happy path - 200 response - `response.redirected = false` - `response.url = 'ipfs://QmFoo/dir'` 2: URL: `ipfs://QmFoo/dir`, `redirect: 'follow'` - The default value - Simulates automatically following a redirect - 200 response - `response.redirected = true` - `response.url = 'ipfs://QmFoo/dir/'` 3: URL: `ipfs://QmFoo/dir`, `redirect: 'error'` - Return an error if a redirect would take place - Throws `TypeError('Failed to Fetch')` same as `window.fetch` 4: URL: `ipfs://QmFoo/dir`, `redirect: 'manual'` - Allows a caller to take action on the redirect - 301 response - `response.redirected = false` - `response.url = 'ipfs://QmFoo/dir` - `response.headers.get('location') = 'ipfs://QmFoo/dir/'` Number 4 is the furthest from [the fetch spec](https://fetch.spec.whatwg.org/#concept-request-redirect-mode) but to follow the spec would make it impossible to actually follow a redirect.
- Loading branch information
1 parent
77d5e9e
commit 94fb322
Showing
3 changed files
with
190 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,29 +1,98 @@ | ||
export function okResponse (body?: BodyInit | null): Response { | ||
return new Response(body, { | ||
function setField (response: Response, name: string, value: string | boolean): void { | ||
Object.defineProperty(response, name, { | ||
enumerable: true, | ||
configurable: false, | ||
set: () => {}, | ||
get: () => value | ||
}) | ||
} | ||
|
||
function setType (response: Response, value: 'basic' | 'cors' | 'error' | 'opaque' | 'opaqueredirect'): void { | ||
setField(response, 'type', value) | ||
} | ||
|
||
function setUrl (response: Response, value: string): void { | ||
setField(response, 'url', value) | ||
} | ||
|
||
function setRedirected (response: Response): void { | ||
setField(response, 'redirected', true) | ||
} | ||
|
||
export interface ResponseOptions extends ResponseInit { | ||
redirected?: boolean | ||
} | ||
|
||
export function okResponse (url: string, body?: BodyInit | null, init?: ResponseOptions): Response { | ||
const response = new Response(body, { | ||
...(init ?? {}), | ||
status: 200, | ||
statusText: 'OK' | ||
}) | ||
|
||
if (init?.redirected === true) { | ||
setRedirected(response) | ||
} | ||
|
||
setType(response, 'basic') | ||
setUrl(response, url) | ||
|
||
return response | ||
} | ||
|
||
export function notSupportedResponse (body?: BodyInit | null): Response { | ||
export function notSupportedResponse (url: string, body?: BodyInit | null, init?: ResponseInit): Response { | ||
const response = new Response(body, { | ||
...(init ?? {}), | ||
status: 501, | ||
statusText: 'Not Implemented' | ||
}) | ||
response.headers.set('X-Content-Type-Options', 'nosniff') // see https://specs.ipfs.tech/http-gateways/path-gateway/#x-content-type-options-response-header | ||
|
||
setType(response, 'basic') | ||
setUrl(response, url) | ||
|
||
return response | ||
} | ||
|
||
export function notAcceptableResponse (body?: BodyInit | null): Response { | ||
return new Response(body, { | ||
export function notAcceptableResponse (url: string, body?: BodyInit | null, init?: ResponseInit): Response { | ||
const response = new Response(body, { | ||
...(init ?? {}), | ||
status: 406, | ||
statusText: 'Not Acceptable' | ||
}) | ||
|
||
setType(response, 'basic') | ||
setUrl(response, url) | ||
|
||
return response | ||
} | ||
|
||
export function badRequestResponse (body?: BodyInit | null): Response { | ||
return new Response(body, { | ||
export function badRequestResponse (url: string, body?: BodyInit | null, init?: ResponseInit): Response { | ||
const response = new Response(body, { | ||
...(init ?? {}), | ||
status: 400, | ||
statusText: 'Bad Request' | ||
}) | ||
|
||
setType(response, 'basic') | ||
setUrl(response, url) | ||
|
||
return response | ||
} | ||
|
||
export function movedPermanentlyResponse (url: string, location: string, init?: ResponseInit): Response { | ||
const response = new Response(null, { | ||
...(init ?? {}), | ||
status: 301, | ||
statusText: 'Moved Permanently', | ||
headers: { | ||
...(init?.headers ?? {}), | ||
location | ||
} | ||
}) | ||
|
||
setType(response, 'basic') | ||
setUrl(response, url) | ||
|
||
return response | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters