Skip to main content
On this page

@std/http

Overview Jump to heading

Provides user-friendly serve on top of Deno's native HTTP server and other utilities for creating HTTP servers and clients.

File Server

A small program for serving local files over HTTP.

deno run --allow-net --allow-read jsr:@std/http/file-server
Listening on:
- Local: http://localhost:8000

When the --allow-sys=networkInterfaces permission is provided, the file server will also display the local area network addresses that can be used to access the server.

HTTP Status Code and Status Text

Helper for processing status code and status text.

HTTP errors

Provides error classes for each HTTP error status code as well as utility functions for handling HTTP errors in a structured way.

Methods

Provides helper functions and types to work with HTTP method strings safely.

Negotiation

A set of functions which can be used to negotiate content types, encodings and languages when responding to requests.

Note: some libraries include accept charset functionality by analyzing the Accept-Charset header. This is a legacy header that clients omit and servers should ignore therefore is not provided.

User agent handling

The UserAgent class provides user agent string parsing, allowing a user agent flag to be semantically understood.

For example to integrate the user agent provided in the header User-Agent in an http request would look like this:

import { UserAgent } from "@std/http/user-agent";

Deno.serve((req) => {
  const userAgent = new UserAgent(req.headers.get("user-agent") ?? "");
  return new Response(`Hello, ${userAgent.browser.name}
    on ${userAgent.os.name} ${userAgent.os.version}!`);
});

Routing

route provides an easy way to route requests to different handlers based on the request path and method.

import { route, type Route } from "@std/http/unstable-route";
import { serveDir } from "@std/http/file-server";

const routes: Route[] = [
  {
    pattern: new URLPattern({ pathname: "/about" }),
    handler: () => new Response("About page"),
  },
  {
    pattern: new URLPattern({ pathname: "/users/:id" }),
    handler: (_req, _info, params) => new Response(params?.pathname.groups.id),
  },
  {
    pattern: new URLPattern({ pathname: "/static/*" }),
    handler: (req: Request) => serveDir(req)
  },
  {
    method: ["GET", "HEAD"],
    pattern: new URLPattern({ pathname: "/api" }),
    handler: (req: Request) => new Response(req.method === 'HEAD' ? null : 'ok'),
  },
];

function defaultHandler(_req: Request) {
  return new Response("Not found", { status: 404 });
}

Deno.serve(route(routes, defaultHandler));

Add to your project Jump to heading

deno add jsr:@std/http

See all symbols in @std/http on

Why use @std/http? Jump to heading

Great for small, fast HTTP servers and handlers using the Web Fetch API style.

Examples Jump to heading

A minimal server

import { serve } from "@std/http";

serve((_req) => new Response("Hello"), { port: 8000 });

Conditional GET with ETag (304 Not Modified)

import { serve } from "@std/http";
import { eTag, ifNoneMatch } from "@std/http/etag";

const body = JSON.stringify({ message: "Hello, cached world" });
const etag = eTag(body);

serve((req) => {
  const inm = req.headers.get("if-none-match");
  // ifNoneMatch returns false when the tag matches -> respond 304
  if (!ifNoneMatch(inm, etag)) {
    return new Response(null, { status: 304, headers: { ETag: etag } });
  }
  return new Response(body, {
    headers: { "content-type": "application/json; charset=utf-8", ETag: etag },
  });
});

Content negotiation (HTML vs JSON)

import { serve } from "@std/http";
import { accepts } from "@std/http/negotiation";

serve((req) => {
  const preferred = accepts(req) ?? ["*/*"];
  if (preferred.includes("application/json") || preferred.includes("*/*")) {
    return Response.json({ ok: true });
  }
  return new Response("<h1>ok</h1>", {
    headers: { "content-type": "text/html; charset=utf-8" },
  });
});

Cookies: set, read, and delete

import { serve } from "@std/http";
import { deleteCookie, getCookies, setCookie } from "@std/http/cookie";

serve(async (req) => {
  const url = new URL(req.url);
  const headers = new Headers();

  if (url.pathname === "/login" && req.method === "POST") {
    // In practice, validate credentials first
    setCookie(headers, {
      name: "sid",
      value: crypto.randomUUID(),
      httpOnly: true,
      secure: true,
      sameSite: "Lax",
      path: "/",
      maxAge: 60 * 60, // 1 hour
    });
    return new Response("ok", { headers });
  }

  if (url.pathname === "/me") {
    const cookies = getCookies(req.headers);
    const sid = cookies["sid"] ?? "(none)";
    return Response.json({ sid });
  }

  if (url.pathname === "/logout") {
    deleteCookie(headers, "sid", { path: "/" });
    return new Response("bye", { headers });
  }

  return new Response("not found", { status: 404 });
});

Static files and CORS with serveDir

import { serve } from "@std/http";
import { serveDir } from "@std/http/file-server";

// Requires --allow-read for your public directory
serve((req) =>
  serveDir(req, {
    fsRoot: "public",
    showDirListing: true,
    enableCors: true, // Adds basic Access-Control-* headers
    urlRoot: "/static",
  })
);

Stream updates with Server-Sent Events (SSE)

import { serve } from "@std/http";
import { ServerSentEventStream } from "@std/http/server-sent-event-stream";

serve((_req) => {
  const { readable, writable } = new TransformStream();
  const sse = new ServerSentEventStream(writable);

  let i = 0;
  const timer = setInterval(() => {
    sse.dispatchMessage({
      event: "tick",
      id: String(i),
      data: new Date().toISOString(),
    });
    i++;
    if (i === 5) { // stop after 5 messages
      clearInterval(timer);
      sse.close();
    }
  }, 1000);

  return new Response(readable, {
    headers: {
      "content-type": "text/event-stream",
      "cache-control": "no-cache",
      "connection": "keep-alive",
    },
  });
});

Serve a single file (Range requests supported)

import { serve } from "@std/http";
import { serveFile } from "@std/http/file-server";

serve((req) => {
  const url = new URL(req.url);
  if (url.pathname === "/video") {
    return serveFile(req, "static/video.mp4");
  }
  return new Response("not found", { status: 404 });
});

Tips Jump to heading

  • Handlers are (req: Request) => Response | Promise<Response>.
  • Compose with standard URL, Headers, and Request for parsing and responses.

Did you find what you needed?

Privacy policy