Skip to content

Update middleware docs #1010

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 64 commits into from
Feb 18, 2025
Merged
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
2c024f1
draft
amirhhashemi Jan 9, 2025
7bb39d4
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Jan 10, 2025
a88a85c
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Jan 10, 2025
1c210d3
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Jan 10, 2025
b94f07d
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Jan 10, 2025
c53bca2
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Jan 11, 2025
a013d57
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Jan 13, 2025
3bb0e91
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Jan 13, 2025
250e489
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Jan 17, 2025
7a54c37
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Jan 18, 2025
bf2058d
update
amirhhashemi Jan 12, 2025
38c21f9
update
amirhhashemi Jan 19, 2025
bb4c551
update
amirhhashemi Jan 25, 2025
f56071b
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Jan 25, 2025
e4d6706
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Jan 27, 2025
e9beddf
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Jan 28, 2025
d7907b7
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Jan 28, 2025
6c32d24
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Jan 28, 2025
d548034
Update src/routes/solid-start/advanced/middleware.mdx
amirhhashemi Jan 28, 2025
fcba8b5
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Jan 28, 2025
d4d4a32
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Jan 28, 2025
c348b17
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Jan 28, 2025
082ad76
Update src/routes/solid-start/advanced/middleware.mdx
amirhhashemi Jan 29, 2025
aafc73b
Update src/routes/solid-start/advanced/middleware.mdx
amirhhashemi Jan 29, 2025
d82db67
Update src/routes/solid-start/advanced/middleware.mdx
amirhhashemi Jan 29, 2025
e3888ee
Update src/routes/solid-start/advanced/middleware.mdx
amirhhashemi Jan 29, 2025
e96d75a
Update src/routes/solid-start/advanced/middleware.mdx
amirhhashemi Jan 29, 2025
d1f9dec
Update src/routes/solid-start/advanced/middleware.mdx
amirhhashemi Jan 29, 2025
0ca1b5d
Update src/routes/solid-start/advanced/middleware.mdx
amirhhashemi Jan 29, 2025
2f44d77
Update src/routes/solid-start/advanced/middleware.mdx
amirhhashemi Jan 29, 2025
d2e6290
Update src/routes/solid-start/advanced/middleware.mdx
amirhhashemi Jan 29, 2025
60d44df
fix formatting issues
amirhhashemi Jan 29, 2025
afe7ae9
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Jan 29, 2025
b216446
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Jan 29, 2025
7012608
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Jan 30, 2025
616d68c
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Jan 30, 2025
656db68
Update src/routes/solid-start/advanced/middleware.mdx
amirhhashemi Jan 31, 2025
7d4d5a2
Update src/routes/solid-start/advanced/middleware.mdx
amirhhashemi Jan 31, 2025
4f9795d
Update src/routes/solid-start/advanced/middleware.mdx
amirhhashemi Jan 31, 2025
802747e
Update src/routes/solid-start/advanced/middleware.mdx
amirhhashemi Jan 31, 2025
90baec1
Update src/routes/solid-start/advanced/middleware.mdx
amirhhashemi Jan 31, 2025
93d2d56
Update src/routes/solid-start/advanced/middleware.mdx
amirhhashemi Jan 31, 2025
1f36ab1
Update src/routes/solid-start/advanced/middleware.mdx
amirhhashemi Jan 31, 2025
fbe6d3f
Update src/routes/solid-start/advanced/middleware.mdx
amirhhashemi Jan 31, 2025
a07a8a0
Update src/routes/solid-start/advanced/middleware.mdx
amirhhashemi Jan 31, 2025
9685ff0
Update src/routes/solid-start/advanced/middleware.mdx
amirhhashemi Jan 31, 2025
73372b5
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Feb 6, 2025
b768d7c
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Feb 6, 2025
9fd7a3c
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Feb 7, 2025
cfdd037
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Feb 7, 2025
d673e4a
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Feb 7, 2025
0eecf28
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Feb 7, 2025
82e53f9
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Feb 10, 2025
4249f84
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Feb 13, 2025
c1bdea6
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Feb 13, 2025
546ae6c
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Feb 13, 2025
a22b0ea
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Feb 13, 2025
b4e993a
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Feb 16, 2025
feafee5
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Feb 16, 2025
1c42e1c
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Feb 16, 2025
0d90adf
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Feb 18, 2025
123789a
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Feb 18, 2025
3265790
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Feb 18, 2025
de132c0
Merge branch 'main' into update-middleware-docs
kodiakhq[bot] Feb 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
271 changes: 260 additions & 11 deletions src/routes/solid-start/advanced/middleware.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,277 @@
title: "Middleware"
---

Middlewares may be included by passing file you specify in your start config.
Middleware intercepts HTTP requests and responses to perform tasks like authentication, redirection, logging, and more.
It also enables sharing request-scoped data across the application using the `event.locals` object.

```js
## Common use cases

Here are some common use cases for middleware:

- **Request and response header management:** Middleware allows modifying headers to control caching (e.g., `Cache-Control`), improve security (e.g., `Content-Security-Policy`), or implement custom behaviour based on request characteristics.
- **Global data sharing:** The `event.locals` object allows storing and sharing request-scoped data between middleware and any server-side context (e.g., API routes, server-only queries/actions). This is useful for passing information like user authentication status, feature flags, or other request-related data.
- **Server-side redirects:** Middleware can redirect users based on various request properties, such as locale, authentication state, or custom query parameters.
- **Request preprocessing:** Middleware can perform lightweight preprocessing tasks, such as validating tokens or normalizing paths.

## Limitations

While middleware is powerful, certain tasks are better handled in other parts of your application for performance, maintainability, or security reasons:

- **Authorization:** Middleware does _not_ run on every request, especially during client-side navigations.
Relying on it for authorization would create a significant security vulnerability.
As a result, authorization checks should be performed as close to the data source as possible.
This means it within API routes, server-only queries/actions, or other server-side utilities.
- **Heavy computation or long-running processes:** Middleware should be lightweight and execute quickly to avoid impacting performance.
CPU-intensive tasks, long-running processes, or blocking operations (e.g., complex calculations, external API calls) are best handled by dedicated route handlers, server-side utilities, or background jobs.
- **Database operations:** Performing direct database queries within middleware can lead to performance bottlenecks and make your application harder to maintain.
Database interactions should be handled by server-side utilities or route handlers, which will create better management of database connections and handling of potential errors.

## Basic usage

Middleware is configured by exporting a configuration object from a dedicated file (e.g., `src/middleware/index.ts`).
This object, created using the [`createMiddleware`](/solid-start/reference/server/create-middleware) function, defines when middleware functions execute throughout the request lifecycle.

```ts title="src/middleware/index.ts"
import { createMiddleware } from "@solidjs/start/middleware";

export default createMiddleware({
onRequest: (event) => {
console.log("Request received:", event.request.url);

event.locals.startTime = Date.now();
},
onBeforeResponse: (event) => {
const endTime = Date.now();
const duration = endTime - event.locals.startTime;
console.log(`Request took ${duration}ms`);
},
});
```

For SolidStart to recognize the configuration object, the file path is declared in `app.config.ts`:

```ts title="app.config.ts"
import { defineConfig } from "@solidjs/start/config";

export default defineConfig({
middleware: "./src/middleware.ts"
middleware: "src/middleware/index.ts",
});
```

## Lifecycle events

A middleware function executes at specific points in the request lifecycle, using two key events: `onRequest` and `onBeforeResponse`.

### `onRequest`

The `onRequest` event is triggered at the beginning of the request lifecycle, before the request is handled by the route handler.
This is the ideal place to:

- Store request-scoped data in `event.locals` for use in later middleware functions or route handlers.
- Set or modify request headers.
- Perform early redirects.

### `onBeforeResponse`

The `onBeforeResponse` event is triggered after a request has been processed by the route handler but before the response is sent to the client.
This is the ideal place to:

- Set or modify response headers.
- Log response metrics or perform other post-processing tasks.
- Modify the response body.

## Locals

In web applications, there's often a need to share request-specific data across different parts of the server-side code.
This data might include user authentication status, trace IDs for debugging, or client metadata (e.g., user agent, geolocation).

The `event.locals` is a plain JavaScript object that can hold any JavaScript value.
This object provides a temporary, request-scoped storage layer to address this need.
Any data stored within it is only available during the processing of a single HTTP request and is automatically cleared afterward.

```ts
import { createMiddleware } from "@solidjs/start/middleware";

export default createMiddleware({
onRequest: (event) => {
event.locals.user = {
name: "John Wick",
};
event.locals.sayHello = () => {
return "Hello, " + event.locals.user.name;
};
},
});
```

Within middleware, `event.locals` can be accessed and modified directly.
Other server-side contexts must use the [`getRequestEvent`](/reference/server-utilities/get-request-event) function to access the `event.locals` object.

```tsx title="src/routes/index.tsx"
import { getRequestEvent } from "solid-js/web";
import { query, createAsync } from "@solidjs/router";

const getUser = query(async () => {
"use server";
const event = getRequestEvent();
return {
name: event?.locals?.user?.name,
greeting: event?.locals?.sayHello(),
};
}, "user");

export default function Page() {
const user = createAsync(() => getUser());

return (
<div>
<p>Name: {user()?.name}</p>
<button onClick={() => alert(user()?.greeting)}>Say Hello</button>
</div>
);
}
```

## Headers

Request and response headers can be accessed and modified using the `event.request.headers` and `event.response.headers` objects.
These follow the [standard Web API `Headers`](https://developer.mozilla.org/en-US/docs/Web/API/Headers) interface, exposing built-in methods for reading/updating headers.

```ts
import { createMiddleware } from "@solidjs/start/middleware";

export default createMiddleware({
onRequest: (event) => {
// Reading client metadata for later use
const userAgent = event.request.headers.get("user-agent");
// Adding custom headers to request/response
event.request.headers.set("x-custom-request-header", "hello");
event.response.headers.set("x-custom-response-header1", "hello");
},
onBeforeResponse: (event) => {
// Finalizing response headers before sending to client
event.response.headers.set("x-custom-response-header2", "hello");
},
});
```

Headers set in `onRequest` are applied **before** the route handler processes the request, allowing downstream middleware or route handlers to override them.
Headers set in `onBeforeResponse` are applied **after** the route handler and are finalized for the client.

## Cookies

HTTP cookies are accessible through the `Cookie` request header and `Set-Cookie` response header.
While these headers can be manipulated directly, [Vinxi](https://vinxi.vercel.app), the underlying server toolkit powering SolidStart, provides helpers to simplify cookie management.
See the [Vinxi Cookies documentation](https://vinxi.vercel.app/api/server/cookies.html) for more information.

```ts
import { createMiddleware } from "@solidjs/start/middleware";
import { getCookie, setCookie } from "vinxi/http";

export default createMiddleware({
onRequest: (event) => {
// Reading a cookie
const theme = getCookie(event.nativeEvent, "theme");

// Setting a secure session cookie with expiration
setCookie(event.nativeEvent, "session", "abc123", {
httpOnly: true,
secure: true,
maxAge: 60 * 60 * 24, // 1 day
});
},
});
```

## Custom responses

Returning a value from a middleware function immediately terminates the request processing pipeline and sends the returned value as the response to the client.
This means no further middleware functions or route handlers will be executed.

```ts
import { createMiddleware } from "@solidjs/start/middleware";

export default createMiddleware({
onRequest: () => {
return new Response("Unauthorized", { status: 401 });
},
});
```

Only [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) objects can be returned from middleware functions.
Returning any other value will result in an error.

### Redirects

[Solid Router](/solid-router) provides the [`redirect` helper function](/solid-router/reference/response-helpers/redirect) which simplifies creating redirect responses.

```ts
import { createMiddleware } from "@solidjs/start/middleware";
import { redirect } from "@solidjs/router";

const REDIRECT_MAP: Record<string, string> = {
"/signup": "/auth/signup",
"/login": "/auth/login",
};

export default createMiddleware({
onRequest: (event) => {
const { pathname } = new URL(event.request.url);

// Redirecting legacy routes permanently to new paths
if (pathname in REDIRECT_MAP) {
return redirect(REDIRECT_MAP[pathname], 301);
}
},
});
```

This example checks the requested path and returns a redirect response if it matches a predefined path.
The 301 status code indicates a permanent redirect.
Other redirect status codes (e.g., 302, 307) are available as needed.

### JSON responses

Solid Router provides the [`json` helper function](/solid-router/reference/response-helpers/json) which simplifies sending custom JSON responses.

```ts
import { createMiddleware } from "@solidjs/start/middleware";
import { json } from "@solidjs/router";

export default createMiddleware({
onRequest: (event) => {
// Rejecting unauthorized API requests with a JSON error
const authHeader = event.request.headers.get("Authorization");
if (!authHeader) {
return json({ error: "Unauthorized" }, { status: 401 });
}
},
});
```

Inside the middleware file, you can export a `createMiddleware` function.
## Chaining middleware functions

`onRequest` and `onBeforeResponse` options in `createMiddleware` can accept either a single function or an array of middleware functions.
When an array is provided, these functions execute sequentially within the same lifecycle event.
This enables composing smaller, more-focused middleware functions, rather than handling all logic in a single, large middleware function.

```tsx
```ts
import { createMiddleware } from "@solidjs/start/middleware";
import { type FetchEvent } from "@solidjs/start/server";

function middleware1(event: FetchEvent) {
event.request.headers.set("x-custom-header1", "hello-from-middleware1");
}

function middleware2(event: FetchEvent) {
event.request.headers.set("x-custom-header2", "hello-from-middleware2");
}

export default createMiddleware({
onRequest: [
event => {
console.log("GLOBAL", event.request.url);
}
]
onRequest: [middleware1, middleware2],
});
```

Middleware supports 2 lifecycles: `onRequest` and `onBeforeResponse`. If you return a value from middleware it will respond with that, otherwise it will run the next one in the chain.
The order of middleware functions in the array determines their execution order.
Dependent middleware functions should be placed after the middleware functions they rely on.
For example, authentication middleware should typically run before logging middleware.
Loading