中间件
中间件允许你拦截请求和响应,并在即将渲染页面或端点时动态注入行为。对于所有预渲染的页面,这种渲染发生在构建时,但对于按需渲染的页面,这种渲染发生在请求路由时,这时可以使用 额外的 SSR 功能如 cookie 和标头 (EN)。
这也允许你通过修改在所有 Astro 组件和 API 端点中可用的 locals
对象,设置和共享跨端点和页面的请求特定信息。即使在构建时运行这个中间件时,这个对象也是可用的。
基本用法
段落标题 基本用法-
创建
src/middleware.js|ts
(或者,你也可以创建src/middleware/index.js|ts
) -
在这个文件中,导出一个接收
context
对象 的onRequest()
函数。注意这里不能是默认导出。 -
在任何
.astro
文件中,使用Astro.locals
访问响应数据。
context
对象
段落标题 context 对象context
对象包含需要对其他中间件、API 路由和 .astro
路由在渲染过程中可用的信息。
它是一个传入 onRequest()
的可选参数,可能包含 locals
对象以及其他在渲染期间共享的任何属性。例如,context
对象可能包含用于认证的 cookies。
在 context.locals
中存储数据
段落标题 在 context.locals 中存储数据context.locals
是一个可以在中间件中操作、包含来自 Response
的数据的对象。
这个 locals
对象在请求处理过程中被传递,并作为 APIContext
和 AstroGlobal
的属性可用。这使得中间件,API 路由和 .astro
页面之间可以共享数据。这对于在渲染步骤中存储请求特定的数据(例如用户数据)很有用。
集成可能会在 locals
对象中设置属性和提供一些功能。如果你在使用一个集成,检查它的文档并确认你没有覆盖掉它的属性或者在做重复的工作。
你可以在 locals
中存储任何类型的数据:字符串,数字,甚至复杂的数据类型,如函数和映射。
然后你可以在任何 .astro
文件中通过 Astro.locals
使用这个信息。
locals
是一个在单个 Astro 路由中创建和销毁的对象;当你的路由页面渲染完后,locals
将不再存在,并会创建一个新的。需要在多个页面请求之间保持的信息必须存储在其他地方。
locals
的值不能在运行时被覆盖。这样做会有清除用户存储的所有信息的风险。在 dev
模式下 Astro 会进行检查,如果 locals
被覆盖将会抛出错误。
示例:删除敏感信息
段落标题 示例:删除敏感信息下面的示例使用中间件将”私人信息”替换为”已删除”,以便你在页面上渲染修改后的 HTML:
中间件类型
段落标题 中间件类型你可以导入并使用 defineMiddleware()
实用函数来提供类型安全:
或者,如果你使用 JsDoc 来提供类型安全,你可以使用 MiddlewareHandler
:
要给 Astro.locals
内的信息定义类型,也就是在 .astro
文件和中间件代码中能提供自动补全,在 env.d.ts
文件中声明一个全局命名空间:
然后,在中间件中,你就可以使用自动补全和类型安全了。
中间件链式调用
段落标题 中间件链式调用可以使用 sequence()
按指定顺序连接多个中间件:
控制台打印结果顺序如下:
重写
段落标题 重写
Added in:
astro@4.13.0
APIContext
中暴露了一个名为 rewrite()
的方法,它的工作方式与 Astro.rewrite 相同。
使用 context.rewrite()
在中间件中显示不同页面的内容,而不会将访问者 重定向 到新页面。这将触发一个新的渲染阶段,导致任何中间件被重新执行。
你也可以向 next()
函数传递一个可选的 URL 路径参数,以重写当前的 Request
而不重新触发新的渲染阶段。重写路径的位置可以作为字符串、URL 或 Request
提供:
next
函数接受与 Astro.rewrite()
函数 相同的参数。重写路径的位置可以作为字符串、URL 或 Request
提供。
当你有多个通过 sequence() 链接的中间件函数时,向 next()
提交一个路径将在原地重写 Request
,并且中间件不会再次执行。链中的下一个中间件函数将接收具有其更新的 context
的新 Request
:
使用此签名调用 next()
将使用旧的 ctx.request
来创建一个新的 Request
对象。这意味着无论是在此重写之前还是之后,只要尝试使用 Request.body
,都会引发运行时错误。使用 HTML 表单的 Astro Actions 经常会引发此错误。在这些情况下,我们建议使用 Astro.rewrite()
而不是使用中间件来处理 Astro 模板的重写。
错误页面
段落标题 错误页面即使找不到匹配的路由,中间件也会尝试为所有按需渲染的页面运行。这包括 Astro 的默认(空白)404 页面和任何自定义 404 页面。然而,是否运行该代码取决于适配器 (EN)。一些适配器可能会提供特定平台的错误页面。
在提供 500 错误页面之前,中间件也会尝试运行,包括自定义的 500 页面,除非服务器错误发生在中间件本身的执行中。如果你的中间件没有成功运行,那么你将无法访问 Astro.locals
来渲染你的 500 页面。