A Router is a stateful container for an array of (Request, Response) tuples.
The following:
import { Router } from "request-router/router";
const router = new Router();
router.handle(
new Request("http://example.com/baz"),
() => new Response(null, { status: 200 })
);
router.match(new Request("http://example.com/baz"));Is identical to:
import { matchAll } from "request-router";
const router = [];
router.push([
new Request("http://example.com/baz"),
() => new Response(null, { status: 200 }),
]);
matchAll(router, new Request("http://example.com/baz"));import { Router } from "request-router/router";
const router = new Router();Routes are a tuple of Request and Response resolvers. The request is used for route matching. If requests match, then the Response resolver will be invoked. Response handlers MUST resolve Response or Promise<Response>.
// Static route matching
router.handle(
new Request("http://example.com/foo"),
(request) => new Response(null, { status: 200 })
);
router.handle(
new Request("http://example.com/bar", { method: "PUT" }),
(request) => new Response(null, { status: 301 })
);
// Dynamic route matching
router.handle(
(request) => new Request("http://example.com/baz"),
(request) => new Response(null, { status: 200 })
);
// This response handler will never be invoked
router.handle(
(request) => undefined,
(request) => new Response(null, { status: 500 })
);
// Wildcard, always match a route
router.handle(undefined, (request) => new Response(null, { status: 404 }));
// Wildcard is equivalent to, but faster than:
router.handle(
(request) => request,
() => new Response(null, { status: 404 })
);(request: Request, options?: RouterOptions) => (Response | Promise<Response>)[]Returns an array of Response or Promise<Response> where the Request portion of the tuple matches the argument to match. Matching is not greedy.
router.match(new Request("http://example.com/foo"));
// [{ status: 200, ... }, { status: 404, ... }]
router.match(new Request("http://example.com/apples"));
// [{ status: 404, ... }]
router.match(new Request("http://example.com/bar"));
// [{ status: 404, ... }]
router.match(new Request("http://example.com/bar", { method: "PUT" }));
// [{ status: 301, ... }, { status: 404, ...}]
router.match(new Request("http://example.com/bar"), { ignoreMethod: true });
// [{ status: 301, ... }, { status: 404, ...}]Internal API used to set default values on input options. See RouterOptions below.
(options?: RouterOptions) => { [key in keyof CacheQueryOptions]-?: CacheQueryOptions[key]; } & { excludeFragment: boolean }See the match method above for more examples. This API is useful if an array of routes is preferred to the Router interface.
(handlers: HandlerTuple[], queryRequest: Request, options?: RouterOptions) => (Response | Promise<Response>)[]Internal API used to compare two Requests given RouterOptions. See RouterOptions below for more explanation of options.
(queryRequest: Request, handlerRequest: Request, options?: RouterOptions) =>
boolean;A HandlerTuple represents a possible Request match and its associated Response resolver. A Router instance maintains an array of HandlerTuple on its handlers property.
type HandlerTuple = [RequestOrHandler, ResponseHandler];RequestOrHandler optionally provides Request instances for Router matching. It may be three possible values:
- RequestHandler - See
RequestHandlertype below - Request - Matching is always performed against the provided
Request - undefined - Indicates the
ResponseHandlerportion of this tuple is a wildcard to be invoked for every query match
type RequestOrHandler = RequestHandler | Request | undefined;The RequestHandler optionally returns a Request for router matching. Returning undefined instructs the router to skip the current (Request, Response) tuple. Its single parameter, request, is the Request object being routed.
type RequestHandler = (request: Request) => Request | undefined;ResponseHandler is invoked when the RequestOrHandler portion of the (Request, Response) tuple was matched. Its single parameter, request, is the Request object being routed. ResponseHandler MUST return a Response or Promise<Response>.
type ResponseHandler = (request: Request) => Response | Promise<Response>;Based on CacheQueryOptions. RouterOptions also exposes an implicit option from the Cache API, excludeFragment. Each flag is used to ignore a specific portion of a Request during matching.
type RouterOptions = {
/**
* The fragment (AKA hash) portion of a URL.
* When true, allows `new Request("example.com#foo")` to match `new Request("example.com")
*/
excludeFragment: boolean;
/**
* The search parameters (AKA query) portion of a URL
* When true, allows `new Request("example.com?foo=bar")` to match `new Request("example.com")
*/
ignoreSearch: boolean;
/**
* The HTTP method of the request
* When true, allows `new Request("example.com", { method: "PUT" })` to match `new Request("example.com")
*/
ignoreMethod: boolean;
/** This flag is currently unused and must always be `true` to earmark for future use. */
ignoreVary: true;
};handleExpression supports using itty-router style expressions for the path portion of a URL. The origin and all other request properties (in other words, every portion of a Request and URL except pathname) will be constructed from the RequestOrHandler passed in after the pathExpression.
Interface:
type HandleExpression = (
pathExpression: string,
requestOrHandler:
| ((
request: Request,
options: { params: { [key: string]: string } | undefined }
) => Request | undefined)
| Request,
responseOrHandler: (
request: Request,
options: { params: { [key: string]: string } | undefined }
) => Response | Promise<Response>
) => HandlerTuple;Example:
import { Router } from "request-router/router";
import { handleExpression } from "request-router/extras";
const router = new Router();
router.handlers.push(
handleExpression(
"/foo/:barId",
new Request("https://example.com"),
(request, { params } = {}) =>
new Response(`Hello, ${params?.barId ?? "friend"}`)
)
);