- 3.0.0-beta.7Latest
- 3.0.0-beta.6
- 3.0.0-beta.5
- 3.0.0-beta.4
- 3.0.0-beta.3
- 3.0.0-beta.2
- 3.0.0-beta.1
- 2.1.0
- 2.1.0-beta.3
- 2.1.0-beta.2
- 2.1.0-beta.1
- 1.0.0-beta.6
- 2.0.0
- 2.0.0-beta.3
- 2.0.0-beta.2
- 2.0.0-beta.1
- 1.2.0
- 1.2.0-beta.5
- 1.2.0-beta.4
- 1.2.0-beta.3
- 1.2.0-beta.2
- 1.2.0-beta.1
- 1.1.0
- 1.1.0-beta.1
- 1.0.0
- 1.0.0-beta.5
- 1.0.0-beta.4
- 1.0.0-beta.3
- 1.0.0-beta.2
- 1.0.0-beta.1
http-router
HTTP request router for standard Request
and Response
.
- Based on URL pattern API
- Tiny, lean
- Nested route
- Automatically
HEAD
request handler - Debug mode
Packages
The package supports multiple platforms.
- deno.land/x -
https://deno.land/x/http_router/mod.ts
- npm -
@httpland/http-router
HTTP router
Create HTTP request router with URL pattern and method handler map.
import { createRouter } from "https://deno.land/x/http_router@$VERSION/mod.ts";
import { serve } from "https://deno.land/std@$VERSION/http/mod.ts";
const router = createRouter({
"/api/students/:name": {
GET: (req, ctx) => {
const greeting = `Hello! ${ctx.params.name!}`;
return new Response(greeting);
},
},
"/api/status": () => new Response("OK"), // Any HTTP request method
});
await serve(router);
Route handler context
The route handler receives the following context.
Name | Description |
---|---|
params | { readonly [k in string]?: string } URL matched parameters. |
route | string Route pathname. |
pattern | URLPattern URL pattern. |
Nested route
Nested route is supported.
The nested root is a flat route syntax sugar. Nesting can be as deep as desired.
import { createRouter } from "https://deno.land/x/http_router@$VERSION/mod.ts";
createRouter({
"/api": {
"status": () => new Response("OK"),
"hello": {
GET: () => new Response("world!"),
},
},
});
This matches the following pattern:
- /api/status
- [GET] /api/hello
- [HEAD] /api/hello (if withHead is not
false
)
Joining path segment
Path segments are joined without overlapping slashes.
The result is the same with or without slashes between path segments.
import { createRouter } from "https://deno.land/x/http_router@$VERSION/mod.ts";
createRouter({
"/api": {
"status": () => new Response("OK"),
"/status": () => new Response("OK"),
},
"/api/status": () => new Response("OK"),
});
They all represent the same URL pattern.
Throwing error
Routers may throw an error during initialization.
If an error is detected in the user-defined routing table, an error is thrown.
Error in the routing table:
- Duplicate route
- Duplicate route and HTTP method pairs
These prevent you from writing multiple routing tables with the same meaning and protect you from unexpected bugs.
Throwing error patterns:
import { createRouter } from "https://deno.land/x/http_router@$VERSION/mod.ts";
createRouter({
"/api": {
"status": () => new Response("OK"),
"/status": () => new Response("OK"),
},
"/api/status": () => new Response("OK"),
}); // duplicate /api/status
createRouter({
"/api": {
"status": {
GET: () => new Response("OK"),
},
},
"/api/status": {
GET: () => new Response("OK"),
},
}); // duplicate [GET] /api/status
router detects as many errors as possible and throws errors. In this case, it
throws AggregateError
, which has RouterError
as a child.
URL match pattern
URL patterns can be defined using the URL pattern API.
- Literal strings which will be matched exactly.
- Wildcards (
/posts/*
) that match any character. - Named groups (
/books/:id
) which extract a part of the matched URL. - Non-capturing groups (
/books{/old}?
) which make parts of a pattern optional or be matched multiple times. - RegExp groups (
/books/(\\d+)
) which make arbitrarily complex regex matches with a few limitations.
HEAD request handler
By default, if a GET
request handler is defined, a HEAD
request handler is
automatically added.
This feature is based on RFC 9110, 9.1
All general-purpose servers MUST support the methods GET and HEAD.
import { createRouter } from "https://deno.land/x/http_router@$VERSION/mod.ts";
import { serve } from "https://deno.land/std@$VERSION/http/mod.ts";
import { assertEquals } from "https://deno.land/std@$VERSION/testing/asserts.ts";
const router = createRouter({
"/": {
GET: (req) => {
const body = `Hello! world`;
return new Response(body, {
headers: {
"content-length": new Blob([body]).size.toString(),
},
});
},
},
});
const req = new Request("http://localhost", { method: "HEAD" });
const res = await router(req);
assertEquals(res.body, null);
assertEquals(res.headers.get("content-length"), "12");
This can be disabled by setting withHead
to false
.
import { createRouter } from "https://deno.land/x/http_router@$VERSION/mod.ts";
createRouter({}, { withHead: false });
Handle base path
Change the router base path.
Just as you could use baseURL or base tags on the Web, you can change the
basePath
of your router.
import { createRouter } from "https://deno.land/x/http_router@$VERSION/mod.ts";
import { assertEquals } from "https://deno.land/std@$VERSION/testing/asserts.ts";
const api = createRouter({
"/hello": () => new Response("world"),
}, { basePath: "/api" });
const res = await api(new Request("http://localhost/api/hello"));
assertEquals(res.ok, true);
The basePath
and route path are merged without overlapping slashes.
Debug
If an error occurs internally, router always catch the error.
In this case, the response status code will automatically be 500, but no further information is provided.
Normally, details of unexpected errors should not be disclosed in production.
If you are in development and want to know what happened when an error occurs,
you can use the debug
flag.
import { createRouter } from "https://deno.land/x/http_router@$VERSION/mod.ts";
createRouter({
"*": () => Promise.reject(Error("Something wrong")),
}, { debug: true });
The response body contains a string serializing the errors caught.
Again, this should not be used in production.
Spec
In addition to user-defined responses, routers may return the following responses:
Status | Headers | Condition |
---|---|---|
404 | If not all route paths match. | |
405 | allow |
If no HTTP method handler is defined. |
500 | content-type (if debug is true ) |
If an internal error occurs. |
API
All APIs can be found in the deno doc.
Performance
version 1.2 or later
Caches URL matching results internally. This speeds up the response time for
requests that have already been matched by ^20X
.
Benchmark
Benchmark script with comparison to several popular routers is available.
deno task bench
Benchmark results can be found here.
License
Copyright © 2022-present httpland.
Released under the MIT license