Skip to main content
Deno 2 is finally here 🎉️
Learn more

portal

Portal is a fast and simple routing framework powered by the URLPattern interface for Deno. The URLPattern interface matches URLs or parts of URLs against a pattern. The pattern can contain capturing groups that extract parts of the matched URL. The best way to learn and test the URL Pattern API is using our free URL Pattern User Interface.

Example

import { Portal, serveStatic } from "https://deno.land/x/portal/mod.ts";

const app = new Portal({ start: 0 });

app.use((ctx) => {
  const start = Date.now();
  ctx.state.start = start;
});

app.get(
  { pathname: "/greeting/:hello" },
  (ctx) =>
    new Response(`Hello ${ctx.urlPatternResult.pathname.groups["hello"]}`),
);

app.get(
  { pathname: "/(|index.html|cat.jpeg)" },
  serveStatic(new URL("./static", import.meta.url)),
);

app.use((ctx) => {
  const ms = Date.now() - ctx.state.start;
  ctx.response.headers.set("X-Response-Time", `${ms}ms`);
});

app.finally((ctx) => {
  const rt = ctx.response.headers.get("X-Response-Time");
  console.log(`${ctx.request.method} ${ctx.url.pathname} - ${String(rt)}`);
});

await app.listen({ port: 8080 });

API

Types

Context

The Context is accessible inside the Handlers as only argument.

Handlers

Receives a Context object and returns a Response object or undefined.

Class

Portal

Faciliates routing powered by the URLPattern interface.

add

Creates routing functions.

const getAndPost = app.add("GET", "POST");
getAndPost({ pathname: "/path/*" }, (ctx) => new Response("Hello"));
get, post, delete, connect…

Takes a URLPatternInput and one or multiple Handlers. It applies the Handlers to the named HTTP method and the specified route.

app.get({ pathname: "*" }, (ctx) => new Response("Hello"));
use

Adds one or multiple Handlers (middlewares) to all methods and routes.

app.use((ctx) => {
  const start = Date.now();
  ctx.state.start = start;
});
catch

The passed Handlers will be executed when an exception has been thrown which is not a Response object. As a consequence a thrown Response object can shortcut the execution order directly to the finally handlers.

app.catch((ctx) => new Response("Something went wrong", { status: 500 }));
finally

The passed Handlers will be executed after all other Handlers.

app.finally((ctx) => {
  const rt = ctx.response.headers.get("X-Response-Time");
  console.log(`${ctx.request.method} ${ctx.url.pathname} - ${String(rt)}`);
});
listen

Constructs a server, creates a listener on the given address, accepts incoming connections, upgrades them to TLS, and handles requests.

await app.listen({ port: 8080 });

Todo

  • Add some tests for the middlewares.
  • Create a UrlPattern Tester UI.
  • Add WebSocket support when WebSocketStream arrives.