Middleware
Middleware allows you to run code before a request is completed. Then, based on the incoming request, you can modify the response by rewriting, redirecting, modifying the request or response headers, or responding directly.
Middleware runs before routes are matched.
Convention
Use the file middleware.ts
(or .js
) inside the src
folder of your project to define Middleware. Or inside src/middleware/index.ts
(or .js
).
Example
// middleware.ts
import { type RequestContext } from "brisa";
// This function can be without `async` if you are not using `await` inside
export default async function middleware({
i18n,
route,
headers,
}: RequestContext): Response | undefined {
const { locale } = i18n;
const isUserRoute = route?.name?.startsWith("/user/[username]");
if (isUserRoute && !(await isUserLogged(headers))) {
return new Response("", {
status: 302,
headers: {
Location: `/${locale}/login`,
},
});
}
}
// middleware.js
// This function can be without `async` if you are not using `await` inside
export default async function middleware({ i18n, route, headers }) {
const { locale } = i18n;
const isUserRoute = route?.name?.startsWith("/user/[username]");
if (isUserRout && !(await isUserLogged(headers))) {
return new Response("", {
status: 302,
headers: {
Location: `/${locale}/login`,
},
});
}
}
Only is possible to access to route
property inside api routes
and pages routes
. This is to support handling of dynamic routes, catch-all, etc in a simple way. In the case of assets
you can look it up through the request:
import { type RequestContext } from "brisa";
export default async function middleware(
request: RequestContext,
): Response | undefined {
const url = new URL(request.url);
if (url.pathname === "/favicon.svg") {
return new Response(
`
<svg>
<rect width="100" height="100" fill="red" />
</svg>
`,
{
headers: { "content-type": "image/svg+xml" },
},
);
}
}
export default async function middleware(request) {
const url = new URL(request.url);
if (url.pathname === "/favicon.svg") {
return new Response(
`
<svg>
<rect width="100" height="100" fill="red" />
</svg>
`,
{
headers: { "content-type": "image/svg+xml" },
},
);
}
}
However, this is not the best way to serve assets. You can put the static files directly inside the public
folder. More information here.
Cookies & Headers
On Request
Cookies are regular headers. On a Request
, they are stored in the Cookie
header.
import { type RequestContext } from "brisa";
export default async function middleware(request: RequestContext) {
const cookies = request.headers.get("cookie");
const headers = request.headers.get("x-example");
// ... do something with cookies and headers
}
export default async function middleware(request) {
const cookies = request.headers.get("cookie");
const headers = request.headers.get("x-example");
// ... do something with cookies and headers
}
On Response
The responseHeaders
function can be exported in the middleware
, in the same way that you can do it inside layout
and pages
.
All responseHeaders will be mixed in this order:
middleware
response headerslayout
response headers (can crush the middleware response headers)page
response headers (both middleware and layout response headers can be mixed).
import { type RequestContext } from "brisa";
export function responseHeaders(
request: RequestContext,
responseStatus: number,
) {
return {
"Cache-Control": "public, max-age=3600",
"X-Example": "This header is added from middleware",
};
}
export function responseHeaders(request, responseStatus) {
return {
"Cache-Control": "public, max-age=3600",
"X-Example": "This header is added from middleware",
};
}
Share data between middleware
โ layout
โ page
โ component
โ responseHeaders
You can share data between different parts of the application using the store
.
import { type RequestContext } from "brisa";
export default async function middleware(request: RequestContext) {
const data = await getData(request);
request.store.set("data", data);
}
import { type RequestContext } from "brisa";
type Props = {
name: string;
};
export default function SomeComponent(props: Props, request: RequestContext) {
const data = request.store.get("data");
return <h1>Hello {data[props.name]}</h1>;
}
If you want to know more check this out.