HTTP 标头
本页内容

HTTP 标头



标头主要通过路由模块 headers 导出定义。您也可以在 entry.server.tsx 中设置标头。

从路由模块

import { Route } from "./+types/some-route";

export function headers(_: Route.HeadersArgs) {
  return {
    "Content-Security-Policy": "default-src 'self'",
    "X-Frame-Options": "DENY",
    "X-Content-Type-Options": "nosniff",
    "Cache-Control": "max-age=3600, s-maxage=86400",
  };
}

您可以返回一个 Headers 实例或 HeadersInit

从加载器和操作

当标头依赖于加载器数据时,加载器和操作也可以设置标头。

1. 将返回值包装在 data

import { data } from "react-router";

export async function loader({ params }: LoaderArgs) {
  let [page, ms] = await fakeTimeCall(
    await getPage(params.id),
  );

  return data(page, {
    headers: {
      "Server-Timing": `page;dur=${ms};desc="Page query"`,
    },
  });
}

2. 从 headers 导出返回

来自加载器和操作的标头不会自动发送。您必须从 headers 导出中明确返回它们。

function hasAnyHeaders(headers: Headers): boolean {
  return [...headers].length > 0;
}

export function headers({
  actionHeaders,
  loaderHeaders,
}: HeadersArgs) {
  return hasAnyHeaders(actionHeaders)
    ? actionHeaders
    : loaderHeaders;
}

一个显著的例外是 Set-Cookie 标头,它会自动从父路由的 headersloaderaction 中保留下来,即使子路由没有导出 headers

与父标头合并

考虑这些嵌套路由

route("pages", "pages-layout-with-nav.tsx", [
  route(":slug", "page.tsx"),
]);

如果两个路由模块都想设置标头,将发送最深层匹配路由的标头。

当您需要同时保留父标头和子标头时,您需要在子路由中合并它们。

追加

最简单的方法是直接追加到父标头。这样可以避免覆盖父级可能设置的标头,并且两者都很重要。

export function headers({ parentHeaders }: HeadersArgs) {
  parentHeaders.append(
    "Permissions-Policy: geolocation=()",
  );
  return parentHeaders;
}

设置

有时覆盖父标头很重要。使用 set 而不是 append 来实现

export function headers({ parentHeaders }: HeadersArgs) {
  parentHeaders.set(
    "Cache-Control",
    "max-age=3600, s-maxage=86400",
  );
  return parentHeaders;
}

您可以通过仅在“叶子路由”(索引路由和没有子路由的子路由)中定义标头,而不在父路由中定义,来避免合并标头的需要。

entry.server.tsx

handleRequest 导出接收来自路由模块的标头作为参数。您可以在这里追加全局标头。

export default async function handleRequest(
  request,
  responseStatusCode,
  responseHeaders,
  routerContext,
  loadContext,
) {
  // set, append global headers
  responseHeaders.set(
    "X-App-Version",
    routerContext.manifest.version,
  );

  return new Response(await getStream(), {
    headers: responseHeaders,
    status: responseStatusCode,
  });
}

如果您没有 entry.server.tsx,请运行 reveal 命令

react-router reveal
文档和示例 CC 4.0
编辑