mirror of
https://github.com/Dvorinka/Devour.git
synced 2026-06-04 12:33:04 +00:00
17 lines
12 KiB
JSON
17 lines
12 KiB
JSON
{
|
|
"id": "36c7ae9bfdd55cf457b6540a",
|
|
"source": "solid:signals",
|
|
"type": "github-document",
|
|
"title": "middleware",
|
|
"content": "---\ntitle: Middleware\nuse_cases: \u003e-\n request interception, header management, global data sharing, request\n preprocessing, logging, redirects\ntags:\n - middleware\n - headers\n - interceptors\n - logging\n - preprocessing\n - locals\nversion: '1.0'\ndescription: \u003e-\n Intercept HTTP requests with middleware for authentication, logging, and\n header management. Share request-scoped data across your app.\n---\n\nMiddleware intercepts HTTP requests and responses to perform tasks like authentication, redirection, logging, and more.\nIt also enables sharing request-scoped data across the application using the `event.locals` object.\n\n## Common use cases\n\nHere are some common use cases for middleware:\n\n- **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.\n- **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.\n- **Server-side redirects:** Middleware can redirect users based on various request properties, such as locale, authentication state, or custom query parameters.\n- **Request preprocessing:** Middleware can perform lightweight preprocessing tasks, such as validating tokens or normalizing paths.\n\n## Limitations\n\nWhile middleware is powerful, certain tasks are better handled in other parts of your application for performance, maintainability, or security reasons:\n\n- **Authorization:** Middleware does _not_ run on every request, especially during client-side navigations.\n Relying on it for authorization would create a significant security vulnerability.\n As a result, authorization checks should be performed as close to the data source as possible.\n This means it within API routes, server-only queries/actions, or other server-side utilities.\n- **Heavy computation or long-running processes:** Middleware should be lightweight and execute quickly to avoid impacting performance.\n 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.\n- **Database operations:** Performing direct database queries within middleware can lead to performance bottlenecks and make your application harder to maintain.\n 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.\n\n## Basic usage\n\nMiddleware is configured by exporting a configuration object from a dedicated file (e.g., `src/middleware/index.ts`).\nThis object, created using the [`createMiddleware`](/solid-start/reference/server/create-middleware) function, defines when middleware functions execute throughout the request lifecycle.\n\n```ts title=\"src/middleware/index.ts\"\nimport { createMiddleware } from \"@solidjs/start/middleware\";\n\nexport default createMiddleware({\n\tonRequest: (event) =\u003e {\n\t\tconsole.log(\"Request received:\", event.request.url);\n\n\t\tevent.locals.startTime = Date.now();\n\t},\n\tonBeforeResponse: (event) =\u003e {\n\t\tconst endTime = Date.now();\n\t\tconst duration = endTime - event.locals.startTime;\n\t\tconsole.log(`Request took ${duration}ms`);\n\t},\n});\n```\n\nFor SolidStart to recognize the configuration object, the file path is declared in `app.config.ts`:\n\n```ts title=\"app.config.ts\"\nimport { defineConfig } from \"@solidjs/start/config\";\n\nexport default defineConfig({\n\tmiddleware: \"src/middleware/index.ts\",\n});\n```\n\n## Lifecycle events\n\nA middleware function executes at specific points in the request lifecycle, using two key events: `onRequest` and `onBeforeResponse`.\n\n### `onRequest`\n\nThe `onRequest` event is triggered at the beginning of the request lifecycle, before the request is handled by the route handler.\nThis is the ideal place to:\n\n- Store request-scoped data in `event.locals` for use in later middleware functions or route handlers.\n- Set or modify request headers.\n- Perform early redirects.\n\n### `onBeforeResponse`\n\nThe `onBeforeResponse` event is triggered after a request has been processed by the route handler but before the response is sent to the client.\nThis is the ideal place to:\n\n- Set or modify response headers.\n- Log response metrics or perform other post-processing tasks.\n- Modify the response body.\n\n## Locals\n\nIn web applications, there's often a need to share request-specific data across different parts of the server-side code.\nThis data might include user authentication status, trace IDs for debugging, or client metadata (e.g., user agent, geolocation).\n\nThe `event.locals` is a plain JavaScript object that can hold any JavaScript value.\nThis object provides a temporary, request-scoped storage layer to address this need.\nAny data stored within it is only available during the processing of a single HTTP request and is automatically cleared afterward.\n\n```ts\nimport { createMiddleware } from \"@solidjs/start/middleware\";\n\nexport default createMiddleware({\n\tonRequest: (event) =\u003e {\n\t\tevent.locals.user = {\n\t\t\tname: \"John Wick\",\n\t\t};\n\t\tevent.locals.sayHello = () =\u003e {\n\t\t\treturn \"Hello, \" + event.locals.user.name;\n\t\t};\n\t},\n});\n```\n\nWithin middleware, `event.locals` can be accessed and modified directly.\nOther server-side contexts must use the [`getRequestEvent`](/reference/server-utilities/get-request-event) function to access the `event.locals` object.\n\n```tsx title=\"src/routes/index.tsx\"\nimport { getRequestEvent } from \"solid-js/web\";\nimport { query, createAsync } from \"@solidjs/router\";\n\nconst getUser = query(async () =\u003e {\n\t\"use server\";\n\tconst event = getRequestEvent();\n\treturn {\n\t\tname: event?.locals?.user?.name,\n\t\tgreeting: event?.locals?.sayHello(),\n\t};\n}, \"user\");\n\nexport default function Page() {\n\tconst user = createAsync(() =\u003e getUser());\n\n\treturn (\n\t\t\u003cdiv\u003e\n\t\t\t\u003cp\u003eName: {user()?.name}\u003c/p\u003e\n\t\t\t\u003cbutton onClick={() =\u003e alert(user()?.greeting)}\u003eSay Hello\u003c/button\u003e\n\t\t\u003c/div\u003e\n\t);\n}\n```\n\n## Headers\n\nRequest and response headers can be accessed and modified using the `event.request.headers` and `event.response.headers` objects.\nThese 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.\n\n```ts\nimport { createMiddleware } from \"@solidjs/start/middleware\";\n\nexport default createMiddleware({\n\tonRequest: (event) =\u003e {\n\t\t// Reading client metadata for later use\n\t\tconst userAgent = event.request.headers.get(\"user-agent\");\n\t\t// Adding custom headers to request/response\n\t\tevent.request.headers.set(\"x-custom-request-header\", \"hello\");\n\t\tevent.response.headers.set(\"x-custom-response-header1\", \"hello\");\n\t},\n\tonBeforeResponse: (event) =\u003e {\n\t\t// Finalizing response headers before sending to client\n\t\tevent.response.headers.set(\"x-custom-response-header2\", \"hello\");\n\t},\n});\n```\n\nHeaders set in `onRequest` are applied **before** the route handler processes the request, allowing downstream middleware or route handlers to override them.\nHeaders set in `onBeforeResponse` are applied **after** the route handler and are finalized for the client.\n\n## Cookies\n\nHTTP cookies are accessible through the `Cookie` request header and `Set-Cookie` response header.\nWhile these headers can be manipulated directly, [Vinxi](https://vinxi.vercel.app), the underlying server toolkit powering SolidStart, provides helpers to simplify cookie management.\nSee the [Vinxi Cookies documentation](https://vinxi.vercel.app/api/server/cookies.html) for more information.\n\n```ts\nimport { createMiddleware } from \"@solidjs/start/middleware\";\nimport { getCookie, setCookie } from \"vinxi/http\";\n\nexport default createMiddleware({\n\tonRequest: (event) =\u003e {\n\t\t// Reading a cookie\n\t\tconst theme = getCookie(event.nativeEvent, \"theme\");\n\n\t\t// Setting a secure session cookie with expiration\n\t\tsetCookie(event.nativeEvent, \"session\", \"abc123\", {\n\t\t\thttpOnly: true,\n\t\t\tsecure: true,\n\t\t\tmaxAge: 60 * 60 * 24, // 1 day\n\t\t});\n\t},\n});\n```\n\n## Custom responses\n\nReturning a value from a middleware function immediately terminates the request processing pipeline and sends the returned value as the response to the client.\nThis means no further middleware functions or route handlers will be executed.\n\n```ts\nimport { createMiddleware } from \"@solidjs/start/middleware\";\n\nexport default createMiddleware({\n\tonRequest: () =\u003e {\n\t\treturn new Response(\"Unauthorized\", { status: 401 });\n\t},\n});\n```\n\nOnly [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) objects can be returned from middleware functions.\nReturning any other value will result in an error.\n\n### Redirects\n\n[Solid Router](/solid-router) provides the [`redirect` helper function](/solid-router/reference/response-helpers/redirect) which simplifies creating redirect responses.\n\n```ts\nimport { createMiddleware } from \"@solidjs/start/middleware\";\nimport { redirect } from \"@solidjs/router\";\n\nconst REDIRECT_MAP: Record\u003cstring, string\u003e = {\n\t\"/signup\": \"/auth/signup\",\n\t\"/login\": \"/auth/login\",\n};\n\nexport default createMiddleware({\n\tonRequest: (event) =\u003e {\n\t\tconst { pathname } = new URL(event.request.url);\n\n\t\t// Redirecting legacy routes permanently to new paths\n\t\tif (pathname in REDIRECT_MAP) {\n\t\t\treturn redirect(REDIRECT_MAP[pathname], 301);\n\t\t}\n\t},\n});\n```\n\nThis example checks the requested path and returns a redirect response if it matches a predefined path.\nThe 301 status code indicates a permanent redirect.\nOther redirect status codes (e.g., 302, 307) are available as needed.\n\n### JSON responses\n\nSolid Router provides the [`json` helper function](/solid-router/reference/response-helpers/json) which simplifies sending custom JSON responses.\n\n```ts\nimport { createMiddleware } from \"@solidjs/start/middleware\";\nimport { json } from \"@solidjs/router\";\n\nexport default createMiddleware({\n\tonRequest: (event) =\u003e {\n\t\t// Rejecting unauthorized API requests with a JSON error\n\t\tconst authHeader = event.request.headers.get(\"Authorization\");\n\t\tif (!authHeader) {\n\t\t\treturn json({ error: \"Unauthorized\" }, { status: 401 });\n\t\t}\n\t},\n});\n```\n\n## Chaining middleware functions\n\n`onRequest` and `onBeforeResponse` options in `createMiddleware` can accept either a single function or an array of middleware functions.\nWhen an array is provided, these functions execute sequentially within the same lifecycle event.\nThis enables composing smaller, more-focused middleware functions, rather than handling all logic in a single, large middleware function.\n\n```ts\nimport { createMiddleware } from \"@solidjs/start/middleware\";\nimport { type FetchEvent } from \"@solidjs/start/server\";\n\nfunction middleware1(event: FetchEvent) {\n\tevent.request.headers.set(\"x-custom-header1\", \"hello-from-middleware1\");\n}\n\nfunction middleware2(event: FetchEvent) {\n\tevent.request.headers.set(\"x-custom-header2\", \"hello-from-middleware2\");\n}\n\nexport default createMiddleware({\n\tonRequest: [middleware1, middleware2],\n});\n```\n\nThe order of middleware functions in the array determines their execution order.\nDependent middleware functions should be placed after the middleware functions they rely on.\nFor example, authentication middleware should typically run before logging middleware.",
|
|
"url": "https://github.com/solidjs/solid-docs/blob/HEAD/src/routes/solid-start/advanced/middleware.mdx",
|
|
"metadata": {
|
|
"path": "src/routes/solid-start/advanced/middleware.mdx",
|
|
"repo": "solidjs/solid-docs",
|
|
"repo_url": "https://github.com/solidjs/solid-docs.git",
|
|
"size": 11469,
|
|
"source_type": "github"
|
|
},
|
|
"hash": "fe259c90ebb95c7bde749ddc0040ca8736ac42b2094e9a226cbbdfc11efbe2de",
|
|
"timestamp": "2026-02-23T11:43:00.193593226+01:00"
|
|
} |