中间件
中间件允许你拦截请求和响应,并在每次页面或端点即将渲染时动态注入行为。此渲染在构建时发生在所有预渲染页面,但在请求按需渲染页面的路由时发生,从而使 其他 SSR 功能,如 cookie 和标头 可用。
¥Middleware allows you to intercept requests and responses and inject behaviors dynamically every time a page or endpoint is about to be rendered. This rendering occurs at build time for all prerendered pages, but occurs when the route is requested for pages rendered on demand, making additional SSR features like cookies and headers available.
中间件还允许你通过改变所有 Astro 组件和 API 端点中可用的 locals
对象来设置和共享端点和页面之间的请求特定信息。即使此中间件在构建时运行,此对象也可用。
¥Middleware also allows you to set and share request-specific information across endpoints and pages by mutating a locals
object that is available in all Astro components and API endpoints. This object is available even when this middleware runs at build time.
基本用法
标题部分 基本用法¥Basic Usage
-
Create
src/middleware.js|ts
(Alternatively, you can createsrc/middleware/index.js|ts
.) -
Inside this file, export an
onRequest()
function that can be passed acontext
object andnext()
function. This must not be a default export. -
Inside any
.astro
file, access response data usingAstro.locals
.
context
对象
标题部分 context 对象¥The context
object
context
对象包括渲染过程中可供其他中间件、API 路由和 .astro
路由使用的信息。
¥The context
object includes information to be made available to other middleware, API routes and .astro
routes during the rendering process.
这是传递给 onRequest()
的可选参数,它可能包含 locals
对象以及渲染期间要共享的任何其他属性。例如,context
对象可以包括用于身份验证的 cookie。
¥This is an optional argument passed to onRequest()
that may contain the locals
object as well as any additional properties to be shared during rendering. For example, the context
object may include cookies used in authentication.
将数据存储在 context.locals
中
标题部分 将数据存储在 context.locals 中¥Storing data in context.locals
context.locals
是一个可以在中间件内部操作的对象。
¥context.locals
is an object that can be manipulated inside the middleware.
此 locals
对象在请求处理过程中转发,并可作为 APIContext
和 AstroGlobal
的属性使用。这允许在中间件、API 路由和 .astro
页面之间共享数据。这对于在渲染步骤中存储特定于请求的数据(例如用户数据)非常有用。
¥This locals
object is forwarded across the request handling process and is available as a property to APIContext
and AstroGlobal
. This allows data to be shared between middlewares, API routes, and .astro
pages. This is useful for storing request-specific data, such as user data, across the rendering step.
你可以在 locals
中存储任何类型的数据:字符串、数字,甚至复杂的数据类型,例如函数和映射。
¥You can store any type of data inside locals
: strings, numbers, and even complex data types such as functions and maps.
然后你可以在任何带有 Astro.locals
的 .astro
文件中使用此信息。
¥Then you can use this information inside any .astro
file with Astro.locals
.
locals
是一个在单一 Astro 路由中生存和消亡的对象;当你的路由页面渲染时,locals
将不再存在,并且将创建一个新的。需要跨多个页面请求保留的信息必须存储在其他地方。
¥locals
is an object that lives and dies within a single Astro route; when your route page is rendered, locals
won’t exist anymore and a new one will be created. Information that needs to persist across multiple page requests must be stored elsewhere.
示例:编辑敏感信息
标题部分 示例:编辑敏感信息¥Example: redacting sensitive information
下面的示例使用中间件将 “私有信息” 替换为单词 “REDACTED”,以允许你在页面上渲染修改后的 HTML:
¥The example below uses middleware to replace “PRIVATE INFO” with the word “REDACTED” to allow you to render modified HTML on your page:
中间件类型
标题部分 中间件类型¥Middleware types
你可以导入并使用实用函数 defineMiddleware()
来利用类型安全:
¥You can import and use the utility function defineMiddleware()
to take advantage of type safety:
相反,如果你使用 JsDoc 来利用类型安全,则可以使用 MiddlewareHandler
:
¥Instead, if you’re using JsDoc to take advantage of type safety, you can use MiddlewareHandler
:
要在 Astro.locals
中键入信息(这会在 .astro
文件和中间件代码中提供自动补齐功能),请在 env.d.ts
文件中声明全局命名空间:
¥To type the information inside Astro.locals
, which gives you autocompletion inside .astro
files and middleware code, declare a global namespace in the env.d.ts
file:
然后,在中间件文件内,你可以利用自动补齐和类型安全。
¥Then, inside the middleware file, you can take advantage of autocompletion and type safety.
链接中间件
标题部分 链接中间件¥Chaining middleware
可以使用 sequence()
按指定顺序连接多个中间件:
¥Multiple middlewares can be joined in a specified order using sequence()
:
这将导致以下控制台命令:
¥This will result in the following console order:
重写
标题部分 重写¥Rewriting
Added in:
astro@4.13.0
APIContext
公开了一种名为 rewrite()
的方法,其工作方式与 Astro.rewrite 相同。
¥The APIContext
exposes a method called rewrite()
which works the same way as Astro.rewrite.
在中间件中使用 context.rewrite()
显示不同页面的内容,而无需将访问者引导到新页面。这将触发新的渲染阶段,导致任何中间件被重新执行。
¥Use context.rewrite()
inside middleware to display a different page’s content without redirecting your visitor to a new page. This will trigger a new rendering phase, causing any middleware to be re-executed.
你还可以向 next()
函数传递一个可选的 URL 路径参数来重写当前的 Request
,而无需重新触发新的渲染阶段。重写路径的位置可以作为字符串、URL 或 Request
提供:
¥You can also pass the next()
function an optional URL path parameter to rewrite the current Request
without retriggering a new rendering phase. The location of the rewrite path can be provided as a string, URL, or Request
:
next()
函数接受与 Astro.rewrite()
功能 相同的有效负载。重写路径的位置可以作为字符串、URL 或 Request
提供。
¥The next()
function accepts the same payload of the Astro.rewrite()
function. The location of the rewrite path can be provided as a string, URL, or Request
.
当你通过 sequence() 链接多个中间件函数时,向 next()
提交路径将在原地重写 Request
,中间件将不会再次执行。链中的下一个中间件函数将接收新的 Request
及其更新的 context
:
¥When you have multiple middleware functions chained via sequence(), submitting a path to next()
will rewrite the Request
in place and the middleware will not execute again. The next middleware function in the chain will receive the new Request
with its updated context
:
使用此签名调用 next()
将使用旧的 ctx.request
创建一个新的 Request
对象。这意味着尝试在重写之前或之后使用 Request.body
将引发运行时错误。此错误通常由 使用 HTML 表单的 Astro 操作 引发。在这些情况下,我们建议使用 Astro.rewrite()
而不是中间件来处理 Astro 模板的重写。
¥Calling next()
with this signature will create a new Request
object using the old ctx.request
. This means that trying to consume Request.body
, either before or after this rewrite, will throw a runtime error. This error is often raised with Astro Actions that use HTML forms. In these cases, we recommend handling rewrites from your Astro templates using Astro.rewrite()
instead of using middleware.
错误页面
标题部分 错误页面¥Error pages
即使找不到匹配的路由,中间件也会尝试运行所有按需渲染的页面。这包括 Astro 的默认(空白)404 页面和任何自定义 404 页面。但是,由 adapter 决定该代码是否运行。某些适配器可能会改为提供特定于平台的错误页面。
¥Middleware will attempt to run for all on-demand rendered pages, even when a matching route cannot be found. This includes Astro’s default (blank) 404 page and any custom 404 pages. However, it is up to the adapter to decide whether that code runs. Some adapters may serve a platform-specific error page instead.
除非服务器错误发生在中间件本身的执行过程中,否则中间件还会尝试在提供 500 错误页面(包括自定义 500 页面)之前运行。如果你的中间件无法成功运行,那么你将无法访问 Astro.locals
来渲染你的 500 页。
¥Middleware will also attempt to run before serving a 500 error page, including a custom 500 page, unless the server error occurred in the execution of the middleware itself. If your middleware does not run successfully, then you will not have access to Astro.locals
to render your 500 page.