有用的参考文档:
示例应用说明
假设我们要创建一个 Web 服务器,它应该响应 /greet 处的 GET 请求,并允许一个 optional route parameter name 作为问候名称,所以路由看起来像这样:/greet/:name?。当该路由匹配时,服务器应该使用单独的中间件来:
- 记录
name路由参数的值(在服务器控制台中),然后
- 以纯文本问候消息进行响应。
上面描述的中间件函数可能如下所示:
./middleware.ts:
import { type RouterMiddleware } from "https://deno.land/x/oak@v10.6.0/mod.ts";
export const logName: RouterMiddleware<"/greet/:name?"> = (ctx, next) => {
const { name } = ctx.params;
console.log({ name });
return next();
};
export const sendGreeting: RouterMiddleware<"/greet/:name?"> = (ctx, next) => {
const name = ctx.params.name ?? "World";
const msg = `Hello ${name}!`;
ctx.response.body = msg;
ctx.response.type = "text/plain";
return next();
};
现在让我们创建一个将定义路由的模块。现在,我们将初始化一个路由器并将其导出,以便在继续设置时不会出现类型错误,但我们将回到这里探索两种组合方法:
./routes.ts:
import { Router } from "https://deno.land/x/oak@v10.6.0/mod.ts";
export const router = new Router();
我们还创建一个模块,用于初始化和导出应用程序(以及在服务器启动时将启动消息打印到控制台的函数):
./app.ts:
import { Application } from "https://deno.land/x/oak@v10.6.0/mod.ts";
import { router } from "./routes.ts";
// This is not necessary, but is potentially helpful to see in the console
function printStartupMessage({ hostname, port, secure }: {
hostname: string;
port: number;
secure?: boolean;
}): void {
const address = new URL(
`http${secure ? "s" : ""}://${
hostname === "0.0.0.0" ? "localhost" : hostname
}:${port}/`,
).href;
console.log(`Listening at ${address}`);
console.log("Use ctrl+c to stop");
}
export const app = new Application();
app.addEventListener("listen", printStartupMessage);
app.use(router.routes());
app.use(router.allowedMethods());
对于设置的最后一部分,我们将创建启动服务器的主应用程序入口点模块:
./main.ts:
import { app } from "./app.ts";
await app.listen({ port: 8000 });
现在,让我们回到./routes.ts来探索组合方法:
组合中间件函数
可以组合中间件的第一种方法是使用 Oak 导出的函数来实现此目的:composeMiddlware
我们的路由模块的修改版本如下所示:
./routes.ts:
import {
composeMiddleware,
Router,
} from "https://deno.land/x/oak@v10.6.0/mod.ts";
import { logName, sendGreeting } from "./middleware.ts";
export const router = new Router();
const greetMiddleware = composeMiddleware([logName, sendGreeting]);
router.get("/greet/:name?", greetMiddleware);
或者,更简单地说,每个中间件函数可以按顺序作为位置参数提供给路由器方法:
./routes.ts:
import { Router } from "https://deno.land/x/oak@v10.6.0/mod.ts";
import { logName, sendGreeting } from "./middleware.ts";
export const router = new Router();
router.get("/greet/:name?", logName, sendGreeting);
两者都产生相同的结果。
测试应用程序
使用适当的permissions 在终端控制台中启动应用程序以进行网络访问:
% deno run --allow-net=0.0.0.0:8000 main.ts
Listening at http://localhost:8000/
Use ctrl+c to stop
如果您在浏览器中导航到http://localhost:8000/greet,您应该会在视口中看到文本Hello World!,然后在终端控制台中返回带有{ name: undefined } 的行。
同样,如果您导航到http://localhost:8000/greet/visitor,您应该会在视口中看到文本Hello visitor!,然后在终端控制台中返回带有{ name: "visitor" } 的行。