Middleware (Промежуточная обработка)
Middleware позволяют добавлять обработку для запроса и ответа и динамически внедрять дополнительное поведение при каждом обращении к странице или эндпоинту.
В том числе, с помощью этого подхода можно устанавливать и использовать специфичную для запроса информацию (контекст) между различными эндпоинтами и страницами, мутируя locals объект, который доступен во всех Astro компонентах и API эндпоинтах.
В Astro middleware доступны как в SSG, так и в SSR подходе.
Использование
Раздел, озаглавленный Использование-
Создайте
src/middleware.js|ts(илиsrc/middleware/index.js|ts). -
Внутри этого модуля необходимо экспортировать
onRequest()функцию. Это не должен быть экспорт по умолчанию.src/middleware.js export function onRequest ({ locals, request }, next) {// доп. обработка ответа// опционально, изменить ответ, модифицируя `locals`locals.title = "Заголовок";// возвращает ответ или результат возможных следующих middleware в цепочкеreturn next();}; -
Внутри
.astroкомпонентов, можно получить доступ к данным черезAstro.locals.
---const data = Astro.locals;---<h1>{data.title}</h1><p>Данные из middleware - {data.property}.</p>Типы middleware
Раздел, озаглавленный Типы middlewareВы можете импортировать и использовать утилитную функцию defineMiddleware() для того, чтобы получить проверку типов:
import { defineMiddleware } from "astro/middleware";
// `context` и `next` уже типизированыexport const onRequest = defineMiddleware((context, next) => {
});Или, если вы используете JsDoc для проверки типов, вы можете использовать MiddlewareRequestHandler:
/** * @type {import("astro").MiddlewareResponseHandler} */// `context` и `next` уже типизированыexport const onRequest = (context, next) => {
};Для того чтобы типизировать данные внутри Astro.locals (это позволит использовать автодополнение IDE в .astro файлах и внутри middleware), определите глобальную область имён в env.d.ts файле:
/// <reference types="astro/client" />declare namespace App { interface Locals { user: { name: string }, welcomeTitle: () => string, orders: Map<string, object> }}Затем, внутри middleware файла, активируются инструменты автодополнения и проверки типов.
Вы можете хранить любые типы данных внутри Astro.locals: строки, числа и даже сложные структуры данных, такие как функции и Maps.
export function onRequest ({ locals, request }, next) { // доп. обработка ответа // опционально, изменить ответ, модифицируя `locals` locals.user.name = "John Wick"; locals.welcomeTitle = () => { return "Добро пожаловать, " + locals.user.name; };
// возвращает ответ или результат возможных следующих middleware в цепочке return next();};После этого вы можете использовать эту информацию внутри любых .astro файлов.
---const title = Astro.locals.welcomeTitle();const orders = Array.from(Astro.locals.orders.entries());---<h1>{title}</h1><ul> {orders.map(order => { return <li>{/* любые действия с объектом `order` */}</li>; })}</ul>Пример: цензурирование персональных данных
Раздел, озаглавленный Пример: цензурирование персональных данныхПример ниже использует middleware для того, чтобы заменить персональные данные на странице (“ПД”) словосочетанием “Совершенно секретно”:
export const onRequest = async (context, next) => { const response = await next(); const html = await response.text(); const redactedHtml = html.replaceAll("ПД", "Совершенно секретно");
return new Response(redactedHtml, { status: 200, headers: response.headers });};Цепочки middleware
Раздел, озаглавленный Цепочки middlewareНесколько middleware могут быть объединены в указанном порядке с помощью функции sequence():
import { sequence } from "astro/middleware";
async function validation(_, next) { console.log("validation request"); const response = await next(); console.log("validation response"); return response;}
async function auth(_, next) { console.log("auth request"); const response = await next(); console.log("auth response"); return response;}
async function greeting(_, next) { console.log("greeting request"); const response = await next(); console.log("greeting response"); return response;}
export const onRequest = sequence(validation, auth, greeting);Это приведет к такому порядку в консоли:
validation requestauth requestgreeting requestgreeting responseauth responsevalidation responseОписание API
Раздел, озаглавленный Описание APIonRequest()
Раздел, озаглавленный onRequest()Обязательный экспорт функции из src/middleware.js|ts, который будет вызван перед обработкой любой страницы или API роута. Эта функции принимает 2 необязательных аргумента: context и next(). onRequest() обязан вернуть объект типа Response: явно, или используя вызов next().
Объект, который включает всю информацию, которая доступна другим middleware, API роутам или компонентам .astro в процессе обработки запроса.
Это необязательный аргумент функции onRequest(), который может так же содержать объект locals как дополнительные атрибуты для общего доступа в процессе отрисовки. Например, объект context может содержать cookies, используемые для аутентификации.
Это тот же самый объект context, который используется в API роутах.
Это функция, которая добавляет обработку (чтение и запись) Response или вызывает next цепочки middleware и возвращает Response. Например, в ней может модифицироваться body HTML документа в ответе.
Это необязательный аргумент функции onRequest(), и может содержать обязательный Response, возвращаемый из middleware.
Объект, который содержит данные из Response. Ими можно манипулировать в middleware.
locals объект передаётся через процесс обработки запроса и доступен через свойства объектов APIContext и AstroGlobal. Это позволяет иметь общий доступ к данным как внутри middleware, так и в API роутах или .astro страницах. Это удобно, когда нужно сохранить специфичные для текущего запроса данные, например, инфо о пользователе.
locals - это объект, который живет в контексте запроса, т.е. когда страница отрисовалась, locals перестаёт существовать. Для последующего запроса будет создан новый locals. Данные, которые должны сохраняться между разными страницами и запросами должны быть сохранены в другом месте.
Значение объекта locals не может быть перезаписано в рантайме. Используя такой подход, есть риск стереть всю информацию, которая была сохранена пользователем. В dev режиме, Astro выполняет проверки и может выбросить исключение, если locals перезаписывается.
sequence()
Раздел, озаглавленный sequence()Функция, которая принимает набор middleware реализаций в качестве аргументов. В рантайме она будет выполнять их в порядке регистрации.
createContext
Раздел, озаглавленный createContextНизкоуровненый API для создания APIContext, который может использоваться внутри middleware Astro.
Эта функция может использоваться для интеграций/адаптеров для явного программного вызова middleware.
trySerializeLocals
Раздел, озаглавленный trySerializeLocalsНизкоуровневый API который принимает любое значение и пытается сериализовать его в строку. Если значение не может быть сериализовано, то функция выбросил исключение в рантайме.
Learn