mirror of
https://github.com/withastro/astro.git
synced 2025-01-20 22:12:38 -05:00
fix: handle immutable response object (#12106)
* fix: handle immutable response object * changeset
This commit is contained in:
parent
fbe1bc51d8
commit
d3a74da196
4 changed files with 36 additions and 12 deletions
5
.changeset/poor-doors-listen.md
Normal file
5
.changeset/poor-doors-listen.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Handles case where an immutable Response object is returned from an endpoint
|
|
@ -50,7 +50,7 @@ export async function renderEndpoint(
|
|||
return new Response(null, { status: 500 });
|
||||
}
|
||||
|
||||
const response = await handler.call(mod, context);
|
||||
let response = await handler.call(mod, context);
|
||||
|
||||
if (!response || response instanceof Response === false) {
|
||||
throw new AstroError(EndpointDidNotReturnAResponse);
|
||||
|
@ -59,10 +59,20 @@ export async function renderEndpoint(
|
|||
// Endpoints explicitly returning 404 or 500 response status should
|
||||
// NOT be subject to rerouting to 404.astro or 500.astro.
|
||||
if (REROUTABLE_STATUS_CODES.includes(response.status)) {
|
||||
// Only `Response.redirect` headers are immutable, therefore a `try..catch` is not necessary.
|
||||
// Note: `Response.redirect` can only be called with HTTP status codes: 301, 302, 303, 307, 308.
|
||||
// Source: https://developer.mozilla.org/en-US/docs/Web/API/Response/redirect_static#parameters
|
||||
response.headers.set(REROUTE_DIRECTIVE_HEADER, 'no');
|
||||
try {
|
||||
response.headers.set(REROUTE_DIRECTIVE_HEADER, 'no');
|
||||
} catch (err) {
|
||||
// In some cases the response may have immutable headers
|
||||
// This is the case if, for example, the user directly returns a `fetch` response
|
||||
// There's no clean way to check if the headers are immutable, so we just catch the error
|
||||
// Note that response.clone() still has immutable headers!
|
||||
if((err as Error).message?.includes('immutable')) {
|
||||
response = new Response(response.body, response);
|
||||
response.headers.set(REROUTE_DIRECTIVE_HEADER, 'no');
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
|
|
3
packages/astro/test/fixtures/ssr-api-route/src/pages/fail.js
vendored
Normal file
3
packages/astro/test/fixtures/ssr-api-route/src/pages/fail.js
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
export async function GET({ request }) {
|
||||
return fetch("https://http.im/status/500", request)
|
||||
}
|
|
@ -137,23 +137,29 @@ describe('API routes in SSR', () => {
|
|||
assert.equal(count, 2, 'Found two separate set-cookie response headers');
|
||||
});
|
||||
|
||||
it('can return an immutable response object', async () => {
|
||||
const response = await fixture.fetch('/fail');
|
||||
const text = await response.text();
|
||||
assert.equal(response.status, 500);
|
||||
assert.equal(text, '');
|
||||
});
|
||||
|
||||
it('Has valid api context', async () => {
|
||||
const response = await fixture.fetch('/context/any');
|
||||
assert.equal(response.status, 200);
|
||||
const data = await response.json();
|
||||
assert.equal(data.cookiesExist, true);
|
||||
assert.equal(data.requestExist, true);
|
||||
assert.equal(data.redirectExist, true);
|
||||
assert.equal(data.propsExist, true);
|
||||
assert.ok(data.cookiesExist);
|
||||
assert.ok(data.requestExist);
|
||||
assert.ok(data.redirectExist);
|
||||
assert.ok(data.propsExist);
|
||||
assert.deepEqual(data.params, { param: 'any' });
|
||||
assert.match(data.generator, /^Astro v/);
|
||||
assert.equal(
|
||||
assert.ok(
|
||||
['http://[::1]:4321/blog/context/any', 'http://127.0.0.1:4321/blog/context/any'].includes(
|
||||
data.url,
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(['::1', '127.0.0.1'].includes(data.clientAddress), true);
|
||||
assert.ok(['::1', '127.0.0.1'].includes(data.clientAddress));
|
||||
assert.equal(data.site, 'https://mysite.dev/subsite/');
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Reference in a new issue