2

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

我见过的一件事似乎与此类似,那就是通过API的加载程序上下文。getLoadContext这使您可以填充context作为 arg 传递给所有路由加载器的对象。

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

这是一种在适配器的请求/响应 API 与您的 Remix 应用程序之间架起桥梁的方法

这个 API 是一个逃生舱,很少需要它

...这让我不这么认为,因为

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

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

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

4

3 回答 3

6

代替中间件,您可以直接在加载器内部调用函数,这也将更加明确。如果您想尽早从那些“中间件”返回响应,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 });
}

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

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
};

另一个例子可能是要求 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
};
于 2021-12-01T16:37:15.503 回答
1

Remix 内部无法在加载程序之前运行代码。

正如您所发现的,有 loader 上下文,但它甚至在 remix 开始执行其工作之前就运行(例如,您将不知道匹配哪些路由模块)。

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

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

于 2021-12-01T15:43:58.457 回答
1

里面app/root.tsx

export let loader: LoaderFunction = ({ request }) => {

const url = new URL(request.url);
const hostname = url.hostname;
const proto = request.headers.get("X-Forwarded-Proto") ?? url.protocol;

url.host =
  request.headers.get("X-Forwarded-Host") ??
  request.headers.get("host") ??
  url.host;
  url.protocol = "https:";

if (proto === "http" && hostname !== "localhost") {
  return redirect(url.toString(), {
    headers: {
      "X-Forwarded-Proto": "https",
    },
  });
}
  return {};
};

来源:https ://github.com/remix-run/remix-jokes/blob/8f786d9d7fa7ea62203e87c1e0bdaa9bda3b28af/app/root.tsx#L25-L46

于 2021-12-27T15:20:54.573 回答