mirror of
https://github.com/withastro/astro.git
synced 2025-03-10 23:01:26 -05:00
fix: default head requests for endpoints when no explicit head method… (#13210)
* fix: default head requests for endpoints when no explicit head method implemented * Update changeset for astro to minor * Update changeset for default HEAD requests * Update .changeset/afraid-turkeys-kneel.md Co-authored-by: Reuben Tier <64310361+TheOtterlord@users.noreply.github.com> --------- Co-authored-by: Matt Kane <m@mk.gg> Co-authored-by: Reuben Tier <64310361+TheOtterlord@users.noreply.github.com>
This commit is contained in:
parent
8d4e566f54
commit
344e9bc480
4 changed files with 61 additions and 2 deletions
7
.changeset/afraid-turkeys-kneel.md
Normal file
7
.changeset/afraid-turkeys-kneel.md
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
'astro': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Handle `HEAD` requests to an endpoint when a handler is not defined.
|
||||||
|
|
||||||
|
If an endpoint defines a handler for `GET`, but does not define a handler for `HEAD`, Astro will call the `GET` handler and return the headers and status but an empty body.
|
|
@ -19,8 +19,12 @@ export async function renderEndpoint(
|
||||||
|
|
||||||
const method = request.method.toUpperCase();
|
const method = request.method.toUpperCase();
|
||||||
// use the exact match on `method`, fallback to ALL
|
// use the exact match on `method`, fallback to ALL
|
||||||
const handler = mod[method] ?? mod['ALL'];
|
let handler = mod[method] ?? mod['ALL'];
|
||||||
if (isPrerendered && method !== 'GET') {
|
// use GET handler for HEAD requests
|
||||||
|
if (!handler && method === 'HEAD' && mod['GET']) {
|
||||||
|
handler = mod['GET'];
|
||||||
|
}
|
||||||
|
if (isPrerendered && !['GET', 'HEAD'].includes(method)) {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
'router',
|
'router',
|
||||||
`${url.pathname} ${bold(
|
`${url.pathname} ${bold(
|
||||||
|
@ -78,5 +82,10 @@ export async function renderEndpoint(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (method === 'HEAD') {
|
||||||
|
// make sure HEAD responses doesnt have body
|
||||||
|
return new Response(null, response);
|
||||||
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1135,6 +1135,16 @@ describe('astro:image', () => {
|
||||||
assert.equal(response.headers.get('content-type'), 'image/webp');
|
assert.equal(response.headers.get('content-type'), 'image/webp');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('returns HEAD method ok for /_image', async () => {
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
params.set('href', '/src/assets/penguin1.jpg?origWidth=207&origHeight=243&origFormat=jpg');
|
||||||
|
params.set('f', 'webp');
|
||||||
|
const response = await fixture.fetch('/some-base/_image?' + String(params), { method: 'HEAD' });
|
||||||
|
assert.equal(response.status, 200);
|
||||||
|
assert.equal(response.body, null);
|
||||||
|
assert.equal(response.headers.get('content-type'), 'image/webp');
|
||||||
|
});
|
||||||
|
|
||||||
it('does not interfere with query params', async () => {
|
it('does not interfere with query params', async () => {
|
||||||
let res = await fixture.fetch('/api?src=image.png');
|
let res = await fixture.fetch('/api?src=image.png');
|
||||||
const html = await res.text();
|
const html = await res.text();
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {
|
||||||
const root = new URL('../../fixtures/api-routes/', import.meta.url);
|
const root = new URL('../../fixtures/api-routes/', import.meta.url);
|
||||||
const fileSystem = {
|
const fileSystem = {
|
||||||
'/src/pages/incorrect.ts': `export const GET = _ => {}`,
|
'/src/pages/incorrect.ts': `export const GET = _ => {}`,
|
||||||
|
'/src/pages/headers.ts': `export const GET = () => { return new Response('content', { status: 201, headers: { Test: 'value' } }) }`,
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('endpoints', () => {
|
describe('endpoints', () => {
|
||||||
|
@ -44,4 +45,36 @@ describe('endpoints', () => {
|
||||||
await done;
|
await done;
|
||||||
assert.equal(res.statusCode, 500);
|
assert.equal(res.statusCode, 500);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should respond with 404 if GET is not implemented', async () => {
|
||||||
|
const { req, res, done } = createRequestAndResponse({
|
||||||
|
method: 'HEAD',
|
||||||
|
url: '/incorrect-route',
|
||||||
|
});
|
||||||
|
container.handle(req, res);
|
||||||
|
await done;
|
||||||
|
assert.equal(res.statusCode, 404);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should respond with same code as GET response', async () => {
|
||||||
|
const { req, res, done } = createRequestAndResponse({
|
||||||
|
method: 'HEAD',
|
||||||
|
url: '/incorrect',
|
||||||
|
});
|
||||||
|
container.handle(req, res);
|
||||||
|
await done;
|
||||||
|
assert.equal(res.statusCode, 500); // get not returns response
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should remove body and pass headers for HEAD requests', async () => {
|
||||||
|
const { req, res, done } = createRequestAndResponse({
|
||||||
|
method: 'HEAD',
|
||||||
|
url: '/headers',
|
||||||
|
});
|
||||||
|
container.handle(req, res);
|
||||||
|
await done;
|
||||||
|
assert.equal(res.statusCode, 201);
|
||||||
|
assert.equal(res.getHeaders().test, 'value');
|
||||||
|
assert.equal(res.body, undefined);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Reference in a new issue