0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2024-12-23 21:53:55 -05:00

refactor: remove endpoint handling infra (#9775)

* remove endpoint handling infra

* add changeset
This commit is contained in:
Arsh 2024-01-23 14:03:51 +00:00 committed by GitHub
parent 9aa7a5368c
commit 075706f26d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 31 additions and 91 deletions

View file

@ -0,0 +1,5 @@
---
"astro": patch
---
Simplifies internals that handle endpoints.

View file

@ -25,7 +25,7 @@ import {
createStylesheetElementSet,
} from '../render/ssr-element.js';
import { matchRoute } from '../routing/match.js';
import { EndpointNotFoundError, SSRRoutePipeline } from './ssrPipeline.js';
import { SSRRoutePipeline } from './ssrPipeline.js';
import type { RouteInfo } from './types.js';
export { deserializeManifest } from './common.js';
@ -272,28 +272,27 @@ export class App {
}
response = await this.#pipeline.renderRoute(renderContext, pageModule);
} catch (err: any) {
if (err instanceof EndpointNotFoundError) {
return this.#renderError(request, { status: 404, response: err.originalResponse });
} else {
this.#logger.error(null, err.stack || err.message || String(err));
return this.#renderError(request, { status: 500 });
}
this.#logger.error(null, err.stack || err.message || String(err));
return this.#renderError(request, { status: 500 });
}
// endpoints do not participate in implicit rerouting
if (routeData.type === 'page' || routeData.type === 'redirect') {
if (REROUTABLE_STATUS_CODES.has(response.status)) {
return this.#renderError(request, {
response,
status: response.status as 404 | 500,
});
}
if (REROUTABLE_STATUS_CODES.has(response.status) && response.headers.get("X-Astro-Reroute") !== "no") {
return this.#renderError(request, {
response,
status: response.status as 404 | 500,
});
}
if (response.headers.has("X-Astro-Reroute")) {
response.headers.delete("X-Astro-Reroute");
}
if (addCookieHeader) {
for (const setCookieHeaderValue of App.getSetCookieFromResponse(response)) {
response.headers.append('set-cookie', setCookieHeaderValue);
}
}
Reflect.set(response, responseSentSymbol, true);
return response;
}

View file

@ -1,28 +1,3 @@
import { Pipeline } from '../pipeline.js';
import type { Environment } from '../render/index.js';
/**
* Thrown when an endpoint contains a response with the header "X-Astro-Response" === 'Not-Found'
*/
export class EndpointNotFoundError extends Error {
originalResponse: Response;
constructor(originalResponse: Response) {
super();
this.originalResponse = originalResponse;
}
}
export class SSRRoutePipeline extends Pipeline {
constructor(env: Environment) {
super(env);
this.setEndpointHandler(this.#ssrEndpointHandler);
}
// This function is responsible for handling the result coming from an endpoint.
async #ssrEndpointHandler(request: Request, response: Response): Promise<Response> {
if (response.headers.get('X-Astro-Response') === 'Not-Found') {
throw new EndpointNotFoundError(response);
}
return response;
}
}
export class SSRRoutePipeline extends Pipeline {}

View file

@ -67,7 +67,6 @@ export class BuildPipeline extends Pipeline {
this.#internals = internals;
this.#staticBuildOptions = staticBuildOptions;
this.#manifest = manifest;
this.setEndpointHandler(this.#handleEndpointResult);
}
getInternals(): Readonly<BuildInternals> {
@ -193,8 +192,4 @@ export class BuildPipeline extends Pipeline {
return pages;
}
async #handleEndpointResult(_: Request, response: Response): Promise<Response> {
return response;
}
}

View file

@ -487,7 +487,8 @@ async function generatePath(
) {
const { mod, scripts: hoistedScripts, styles: _styles } = gopts;
const manifest = pipeline.getManifest();
pipeline.getEnvironment().logger.debug('build', `Generating: ${pathname}`);
const logger = pipeline.getLogger();
logger.debug('build', `Generating: ${pathname}`);
const links = new Set<never>();
const scripts = createModuleScriptsSet(

View file

@ -4,10 +4,6 @@ import { callMiddleware } from './middleware/callMiddleware.js';
import { renderPage } from './render/core.js';
import { type Environment, type RenderContext } from './render/index.js';
type EndpointResultHandler = (
originalRequest: Request,
result: Response
) => Promise<Response> | Response;
type PipelineHooks = {
before: PipelineHookFunction[];
@ -26,11 +22,6 @@ export class Pipeline {
#hooks: PipelineHooks = {
before: [],
};
/**
* The handler accepts the *original* `Request` and result returned by the endpoint.
* It must return a `Response`.
*/
#endpointHandler?: EndpointResultHandler;
/**
* When creating a pipeline, an environment is mandatory.
@ -42,15 +33,6 @@ export class Pipeline {
setEnvironment() {}
/**
* When rendering a route, an "endpoint" will a type that needs to be handled and transformed into a `Response`.
*
* Each consumer might have different needs; use this function to set up the handler.
*/
setEndpointHandler(handler: EndpointResultHandler) {
this.#endpointHandler = handler;
}
/**
* A middleware function that will be called before each request.
*/
@ -81,22 +63,12 @@ export class Pipeline {
for (const hook of this.#hooks.before) {
hook(renderContext, componentInstance);
}
const result = await this.#tryRenderRoute(
return await this.#tryRenderRoute(
renderContext,
this.env,
componentInstance,
this.#onRequest
);
if (renderContext.route.type === 'endpoint') {
if (!this.#endpointHandler) {
throw new Error(
'You created a pipeline that does not know how to handle the result coming from an endpoint.'
);
}
return this.#endpointHandler(renderContext.request, result);
} else {
return result;
}
}
/**

View file

@ -33,16 +33,14 @@ export async function renderEndpoint(
? `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.
return new Response(null, {
status: 404,
headers: {
'X-Astro-Response': 'Not-Found',
},
});
// No handler matching the verb found, so this should be a
// 404. Should be handled by 404.astro route if possible.
return new Response(null, { status: 404 });
}
return handler.call(mod, context);
const response = await handler.call(mod, context);
// Endpoints explicitly returning 404 or 500 response status should
// NOT be subject to rerouting to 404.astro or 500.astro.
response.headers.set("X-Astro-Reroute", "no");
return response;
}

View file

@ -35,7 +35,6 @@ export default class DevPipeline extends Pipeline {
this.#devLogger = logger;
this.#settings = settings;
this.#loader = loader;
this.setEndpointHandler(this.#handleEndpointResult);
}
clearRouteCache() {
@ -88,9 +87,5 @@ export default class DevPipeline extends Pipeline {
});
}
async #handleEndpointResult(_: Request, response: Response): Promise<Response> {
return response;
}
async handleFallback() {}
}