From 7f7a7f1aeaec6b327ae0e5e7470a4f46174bf8ae Mon Sep 17 00:00:00 2001 From: Arsh <69170106+lilnasy@users.noreply.github.com> Date: Wed, 27 Dec 2023 17:56:10 +0000 Subject: [PATCH] qol(routing): warn when api route method doesn't match the casing of an export (#9497) * fix(routing): improve messaging for getting the case wrong * add changeset * lint: no shadowing * remove old APIRoute signature * Apply suggestions from code review Co-authored-by: Voxel --------- Co-authored-by: Voxel --- .changeset/tidy-dogs-remain.md | 5 ++ packages/astro/src/@types/astro.ts | 2 +- packages/astro/src/runtime/server/endpoint.ts | 46 ++++++------------- 3 files changed, 21 insertions(+), 32 deletions(-) create mode 100644 .changeset/tidy-dogs-remain.md diff --git a/.changeset/tidy-dogs-remain.md b/.changeset/tidy-dogs-remain.md new file mode 100644 index 000000000000..aef030c9d05c --- /dev/null +++ b/.changeset/tidy-dogs-remain.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Adds a helpful warning message for when an exported API Route is not uppercase. diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts index 2893a20eab23..6a255c5734b7 100644 --- a/packages/astro/src/@types/astro.ts +++ b/packages/astro/src/@types/astro.ts @@ -2237,7 +2237,7 @@ export type APIRoute = Record> = ) => Response | Promise; export interface EndpointHandler { - [method: string]: APIRoute | ((params: Params, request: Request) => Response); + [method: string]: APIRoute; } export type Props = Record; diff --git a/packages/astro/src/runtime/server/endpoint.ts b/packages/astro/src/runtime/server/endpoint.ts index f8fc1c071c78..c1448affade8 100644 --- a/packages/astro/src/runtime/server/endpoint.ts +++ b/packages/astro/src/runtime/server/endpoint.ts @@ -2,18 +2,6 @@ import { bold } from 'kleur/colors'; import type { APIContext, EndpointHandler, Params } from '../../@types/astro.js'; import type { Logger } from '../../core/logger/core.js'; -function getHandlerFromModule(mod: EndpointHandler, method: string) { - // If there was an exact match on `method`, return that function. - if (mod[method]) { - return mod[method]; - } - if (mod['ALL']) { - return mod['ALL']; - } - // Otherwise, no handler found. - return undefined; -} - /** Renders an endpoint request to completion, returning the body. */ export async function renderEndpoint( mod: EndpointHandler, @@ -23,38 +11,34 @@ export async function renderEndpoint( ) { const { request, url } = context; - const chosenMethod = request.method?.toUpperCase(); - const handler = getHandlerFromModule(mod, chosenMethod); - if (!ssr && ssr === false && chosenMethod && chosenMethod !== 'GET') { + const method = request.method.toUpperCase(); + // use the exact match on `method`, fallback to ALL + const handler = mod[method] ?? mod['ALL']; + if (!ssr && ssr === false && method !== 'GET') { logger.warn( - null, + "router", `${url.pathname} ${bold( - chosenMethod + method )} requests are not available for a static site. Update your config to \`output: 'server'\` or \`output: 'hybrid'\` to enable.` ); } - if (!handler || typeof handler !== 'function') { + if (typeof handler !== 'function') { + logger.warn( + 'router', + `No API Route handler exists for the method "${method}" for the route ${url.pathname}.\n` + + `Found handlers: ${Object.keys(mod).map(exp => JSON.stringify(exp)).join(', ')}\n` + + ('all' in mod ? `One of the exported handlers is "all" (lowercase), did you mean to export 'ALL'?\n` : '') + ); // No handler found, so this should be a 404. Using a custom header // to signal to the renderer that this is an internal 404 that should // be handled by a custom 404 route if possible. - let response = new Response(null, { + return new Response(null, { status: 404, headers: { 'X-Astro-Response': 'Not-Found', }, }); - return response; } - const proxy = new Proxy(context, { - get(target, prop) { - if (prop in target) { - return Reflect.get(target, prop); - } else { - return undefined; - } - }, - }) as APIContext & Params; - - return handler.call(mod, proxy, request); + return handler.call(mod, context); }