如何将多个中间件链接到一条路由上?



我想在deno oak中链接2个中间件函数,像这样:

const addProductPanier = async(req:any,res:any) => {...}
const showPanier = async(ctx:any) => {...}
router.post('/OBV/panier',addProductPanier).post('/OBV/panier',showPanier);

我已经尝试了很多方法,并在oak文档中寻找解决方案,但.post中的字符串路径不能相同,我需要有例如:

router.post('/OBV/panier',addProductPanier).post('/OBV/panier/one',showPanier);

我也试图合并在一个2中间件,它工作了几天前,但由于一些未知的原因,它不再工作回复我,response.render()不是一个函数。正如你所看到的,我把它们分开,让addProductPanier向我的数据库发送数据,让showPanier获取这些数据,并使用ctx.render()在我的html页面上显示它。

那么你知道如何将多个中间件链接到一条路由吗?

答案摘要

您可以使用Oak的中间件组合函数(composeMiddlware),或者您可以简单地将每个中间件函数作为路由器方法的位置参数提供。


指导解释因为在你的问题中没有一个最小的、可复制的例子,我将在下面以一个简单的问候应用的形式提供一个例子,并用它来解决你的问题,详细介绍在同一路由上组成中间件的两种方法。

有用的参考文档:

<<ul>
  • 橡树的路由器/gh>
  • Oak使用的路由参数库
  • 应用描述示例

    假设我们想要创建一个web服务器,它应该在/greet响应GET请求,并且还允许一个可选的路由参数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模块应该是这样的:

    ./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);
    

    或者,更简单地说,每个中间件函数都可以按顺序作为router方法的位置参数提供:

    ./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);
    

    两者产生相同的结果。

    测试应用

    在终端控制台中以适当的网络访问权限启动应用程序:

    % 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" }

    最新更新