0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-01-06 22:10:10 -05:00

qol(endpoints): helpful error message when a response is not provided (#10455)

* qol(endpoints): helpful error message when a response is not provded

* add changeset

* add test
This commit is contained in:
Arsh 2024-03-18 20:06:46 +05:30 committed by GitHub
parent 7138aa4678
commit c12666166d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 84 additions and 0 deletions

View file

@ -0,0 +1,5 @@
---
"astro": patch
---
Adds a helpful error message that will be shown when an endpoint does not return a `Response`.

View file

@ -788,6 +788,29 @@ export const MiddlewareNotAResponse = {
message: 'Any data returned from middleware must be a valid `Response` object.',
} satisfies ErrorData;
/**
* @docs
* @description
* Thrown when an endpoint does not return anything or returns an object that is not a `Response` object.
*
* An endpoint must return either a `Response`, or a `Promise` that resolves with a `Response`. For example:
* ```ts
* import type { APIContext } from 'astro';
*
* export async function GET({ request, url, cookies }: APIContext): Promise<Response> {
* return Response.json({
* success: true,
* result: 'Data from Astro Endpoint!'
* })
* }
* ```
*/
export const EndpointDidNotReturnAResponse = {
name: 'EndpointDidNotReturnAResponse',
title: 'The endpoint did not return a `Response`.',
message: 'An endpoint must return either a `Response`, or a `Promise` that resolves with a `Response`.',
} satisfies ErrorData;
/**
* @docs
* @description

View file

@ -2,6 +2,8 @@ import { bold } from 'kleur/colors';
import type { APIContext, EndpointHandler } from '../../@types/astro.js';
import { REROUTABLE_STATUS_CODES, REROUTE_DIRECTIVE_HEADER } from '../../core/constants.js';
import type { Logger } from '../../core/logger/core.js';
import { AstroError } from '../../core/errors/errors.js';
import { EndpointDidNotReturnAResponse } from '../../core/errors/errors-data.js';
/** Renders an endpoint request to completion, returning the body. */
export async function renderEndpoint(
@ -49,6 +51,11 @@ export async function renderEndpoint(
}
const response = await handler.call(mod, context);
if (!response || response instanceof Response === false) {
throw new AstroError(EndpointDidNotReturnAResponse)
}
// 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)) {

View file

@ -0,0 +1,49 @@
import * as assert from 'node:assert/strict';
import { after, before, describe, it } from 'node:test';
import { fileURLToPath } from 'node:url';
import { createContainer } from '../../../dist/core/dev/container.js';
import testAdapter from '../../test-adapter.js';
import {
createBasicSettings,
createFs,
createRequestAndResponse,
defaultLogger,
} from '../test-utils.js';
const root = new URL('../../fixtures/api-routes/', import.meta.url);
const fileSystem = {
'/src/pages/incorrect.ts': `export const GET = _ => {}`,
};
describe('endpoints', () => {
let container;
let settings;
before(async () => {
const fs = createFs(fileSystem, root);
settings = await createBasicSettings({
root: fileURLToPath(root),
output: 'server',
adapter: testAdapter(),
});
container = await createContainer({
fs,
settings,
logger: defaultLogger,
});
});
after(async () => {
await container.close();
});
it('should respond with 500 for incorrect implementation', async () => {
const { req, res, done } = createRequestAndResponse({
method: 'GET',
url: '/incorrect',
});
container.handle(req, res);
await done;
assert.equal(res.statusCode, 500);
});
});