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-Charsetheader. 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
为什么使用 @std/http? Jump to heading
非常适合使用 Web Fetch API 风格构建小型、快速的 HTTP 服务器和处理器。
示例 Jump to heading
一个极简服务器
import { serve } from "@std/http";
serve((_req) => new Response("Hello"), { port: 8000 });
条件 GET 与 ETag(304 未修改)
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 传回 false 说明标签匹配 -> 响应 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 },
});
});
内容协商(HTML 与 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" },
});
});
Cookie:设置、读取与删除
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") {
// 实际场景请先验证凭证
setCookie(headers, {
name: "sid",
value: crypto.randomUUID(),
httpOnly: true,
secure: true,
sameSite: "Lax",
path: "/",
maxAge: 60 * 60, // 1 小时
});
return new Response("ok", { headers });
}
if (url.pathname === "/me") {
const cookies = getCookies(req.headers);
const sid = cookies["sid"] ?? "(无)";
return Response.json({ sid });
}
if (url.pathname === "/logout") {
deleteCookie(headers, "sid", { path: "/" });
return new Response("bye", { headers });
}
return new Response("未找到", { status: 404 });
});
使用 serveDir 提供静态文件和跨域资源共享(CORS)
import { serve } from "@std/http";
import { serveDir } from "@std/http/file-server";
// 需要为你的公共目录授予 --allow-read 权限
serve((req) =>
serveDir(req, {
fsRoot: "public",
showDirListing: true,
enableCors: true, // 添加基本的 Access-Control-* 头
urlRoot: "/static",
})
);
使用服务端发送事件 (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) { // 发送 5 条消息后停止
clearInterval(timer);
sse.close();
}
}, 1000);
return new Response(readable, {
headers: {
"content-type": "text/event-stream",
"cache-control": "no-cache",
"connection": "keep-alive",
},
});
});
提供单个文件服务(支持 Range 请求)
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("未找到", { status: 404 });
});
小贴士 Jump to heading
- 处理器签名为
(req: Request) => Response | Promise<Response>。 - 与标准的
URL、Headers和Request结合使用,方便解析与响应。