Remix:在每个请求的加载器之前运行代码的中间件模式?

dav*_*wil 18 javascript remix.run

Remix 中是否有推荐的模式来在每个请求上运行通用代码,并可能向请求添加上下文数据?就像中间件一样?例如,这样做的一个用例可能是进行日志记录或身份验证。

\n

我见过的与此类似的一件事是通过API 的加载器上下文getLoadContext。这允许您填充一个context对象,该对象作为参数传递给所有路由加载器。

\n

它确实有效,最初似乎是这样做的方法,但它的文档说......

\n
\n

这是一种弥合适配器请求/响应 API 与 Remix 应用程序之间差距的方法

\n
\n
\n

此 API 是一个逃生舱口,\xe2\x80\x99 很少需要它

\n
\n

...这让我有不同的想法,因为

\n
    \n
  • 此 API 明确用于与服务器运行时的自定义集成。但中间件似乎并不应该特定于服务器运行时 - 它们应该只是作为 Remix 功能的“应用程序”级别的一部分。

    \n
  • \n
  • 运行中间件是Web 框架中非常常见的模式!

    \n
  • \n
\n

那么,Remix 对于在每个加载器之前运行的中间件有更好的模式吗?

\n

小智 16

您可以直接在加载器内部调用函数,而不是中间件,这也会更明确。如果你想提前从那些“中间件”返回响应,Remix 可以让你抛出响应对象。

例如,如果您想检查用户是否具有特定角色,您可以创建此函数:

async function verifyUserRole(request: Request, expectedRole: string) {
  let user = await getAuthenticatedUser(request); // somehow get the user
  if (user.role === expectedRole) return user;
  throw json({ message: "Forbidden" }, { status: 403 });
}
Run Code Online (Sandbox Code Playgroud)

在任何加载器中都这样称呼它:

let loader: LoaderFunction = async ({ request }) => {
  let user = await verifyUserRole(request, "admin");
  // code here will only run if user is an admin
  // and you'll also get the user object at the same time
};
Run Code Online (Sandbox Code Playgroud)

另一个例子可能是需要 HTTPS

function requireHTTPS(request: Request) {
  let url = new URL(request.url);
  if (url.protocol === "https:") return;
  url.protocol = "https:";
  throw redirect(url.toString());
}

let loader: LoaderFunction = async ({ request }) => {
  await requireHTTPS(request);
  // run your loader (or action) code here
};
Run Code Online (Sandbox Code Playgroud)

  • 恕我直言,但是中间件(以及基本上任何装饰器模式)的全部要点难道不是您不需要修改处理程序就可以工作吗?如果您可以修改处理程序,那么确保您不需要中间件...但是这个答案只是回避了 iso 回答的问题。我更喜欢 [Kaidjin](/users/2236690/kaidjin) 的[答案](/a/70187165/286685),它基本上只是告诉你,不,Remix 还不支持中间件。 (5认同)
  • 谢谢塞尔吉奥。是的,有趣的是,当我想到这一点时,这种模式实际上非常简单和明确。没有针对不同类型的行为和类型的深奥中间件签名,只是以最直接的方式工作 - 不需要全局/泛型或任何此类东西。 (2认同)

Kai*_*jin 6

Remix 中无法在加载器之前运行代码。

正如您所发现的,存在加载器上下文,但它甚至在重新混合开始执行其工作之前就运行(因此您不知道例如哪些路由模块是匹配的)。

您还可以在 JS 文件中传递重新混合请求之前运行任意代码,在该文件中您使用要部署到的平台的适配器(这取决于您使用的启动器。如果您选择了重新混合,则该文件不存在服务器作为您的服务器)

目前它应该适用于某些用例,但我同意这是目前 remix 中缺少的功能。