Home / File/ callMiddleware.ts — astro Source File

callMiddleware.ts — astro Source File

Architecture documentation for callMiddleware.ts, a typescript file in the astro codebase. 3 imports, 0 dependents.

File typescript CoreAstro CoreMiddleware 3 imports 1 functions

Entity Profile

Dependency Diagram

graph LR
  db77a309_a7b7_5c30_3a75_0733b8628466["callMiddleware.ts"]
  135a8084_d596_67c2_9209_cca6693604e6["../types/public/common.js"]
  db77a309_a7b7_5c30_3a75_0733b8628466 --> 135a8084_d596_67c2_9209_cca6693604e6
  28857b9f_4720_3f29_4abb_a7eec34dcca5["../types/public/context.js"]
  db77a309_a7b7_5c30_3a75_0733b8628466 --> 28857b9f_4720_3f29_4abb_a7eec34dcca5
  ef8a1e3f_e350_75a6_b92d_62a8566d8db9["../core/errors/index.js"]
  db77a309_a7b7_5c30_3a75_0733b8628466 --> ef8a1e3f_e350_75a6_b92d_62a8566d8db9
  style db77a309_a7b7_5c30_3a75_0733b8628466 fill:#6366f1,stroke:#818cf8,color:#fff

Relationship Graph

Source Code

import type {
	MiddlewareHandler,
	MiddlewareNext,
	RewritePayload,
} from '../../types/public/common.js';
import type { APIContext } from '../../types/public/context.js';
import { AstroError, AstroErrorData } from '../errors/index.js';

/**
 * Utility function that is in charge of calling the middleware.
 *
 * It accepts a `R` generic, which usually is the `Response` returned.
 * It is a generic because endpoints can return a different payload.
 *
 * When calling a middleware, we provide a `next` function, this function might or
 * might not be called.
 *
 * A middleware, to behave correctly, can:
 * - return a `Response`;
 * - call `next`;
 *
 * Failing doing so will result an error. A middleware can call `next` and do not return a
 * response. A middleware can not call `next` and return a new `Response` from scratch (maybe with a redirect).
 *
 * ```js
 * const onRequest = async (context, next) => {
 *   const response = await next(context);
 *   return response;
 * }
 * ```
 *
 * ```js
 * const onRequest = async (context, next) => {
 *   context.locals = "foo";
 *   next();
 * }
 * ```
 *
 * @param onRequest The function called which accepts a `context` and a `resolve` function
 * @param apiContext The API context
 * @param responseFunction A callback function that should return a promise with the response
 */
export async function callMiddleware(
	onRequest: MiddlewareHandler,
	apiContext: APIContext,
	responseFunction: (
		apiContext: APIContext,
		rewritePayload?: RewritePayload,
	) => Promise<Response> | Response,
): Promise<Response> {
	let nextCalled = false;
	let responseFunctionPromise: Promise<Response> | Response | undefined = undefined;
	const next: MiddlewareNext = async (payload) => {
		nextCalled = true;
		responseFunctionPromise = responseFunction(apiContext, payload);
		// We need to pass the APIContext pass to `callMiddleware` because it can be mutated across middleware functions
		return responseFunctionPromise;
	};

	const middlewarePromise = onRequest(apiContext, next);

	return await Promise.resolve(middlewarePromise).then(async (value) => {
		// first we check if `next` was called
		if (nextCalled) {
			/**
			 * Then we check if a value is returned. If so, we need to return the value returned by the
			 * middleware.
			 * e.g.
			 * ```js
			 * 	const response = await next();
			 * 	const new Response(null, { status: 500, headers: response.headers });
			 * ```
			 */
			if (typeof value !== 'undefined') {
				if (value instanceof Response === false) {
					throw new AstroError(AstroErrorData.MiddlewareNotAResponse);
				}
				return value;
			} else {
				/**
				 * Here we handle the case where `next` was called and returned nothing.
				 */
				if (responseFunctionPromise) {
					return responseFunctionPromise;
				} else {
					throw new AstroError(AstroErrorData.MiddlewareNotAResponse);
				}
			}
		} else if (typeof value === 'undefined') {
			/**
			 * There might be cases where `next` isn't called and the middleware **must** return
			 * something.
			 *
			 * If not thing is returned, then we raise an Astro error.
			 */
			throw new AstroError(AstroErrorData.MiddlewareNoDataOrNextCalled);
		} else if (value instanceof Response === false) {
			throw new AstroError(AstroErrorData.MiddlewareNotAResponse);
		} else {
			// Middleware did not call resolve and returned a value
			return value;
		}
	});
}

Domain

Subdomains

Functions

Dependencies

  • ../core/errors/index.js
  • ../types/public/common.js
  • ../types/public/context.js

Frequently Asked Questions

What does callMiddleware.ts do?
callMiddleware.ts is a source file in the astro codebase, written in typescript. It belongs to the CoreAstro domain, CoreMiddleware subdomain.
What functions are defined in callMiddleware.ts?
callMiddleware.ts defines 1 function(s): callMiddleware.
What does callMiddleware.ts depend on?
callMiddleware.ts imports 3 module(s): ../core/errors/index.js, ../types/public/common.js, ../types/public/context.js.
Where is callMiddleware.ts in the architecture?
callMiddleware.ts is located at packages/astro/src/core/middleware/callMiddleware.ts (domain: CoreAstro, subdomain: CoreMiddleware, directory: packages/astro/src/core/middleware).

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free