@depup/h3 2.0.1-rc.17-depup.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +25 -0
  3. package/bin/h3.mjs +35 -0
  4. package/changes.json +5 -0
  5. package/dist/THIRD-PARTY-LICENSES.md +70 -0
  6. package/dist/_entries/bun.d.mts +8 -0
  7. package/dist/_entries/bun.mjs +11 -0
  8. package/dist/_entries/cloudflare.d.mts +8 -0
  9. package/dist/_entries/cloudflare.mjs +11 -0
  10. package/dist/_entries/deno.d.mts +8 -0
  11. package/dist/_entries/deno.mjs +11 -0
  12. package/dist/_entries/generic.d.mts +8 -0
  13. package/dist/_entries/generic.mjs +11 -0
  14. package/dist/_entries/node.d.mts +12 -0
  15. package/dist/_entries/node.mjs +14 -0
  16. package/dist/_entries/service-worker.d.mts +8 -0
  17. package/dist/_entries/service-worker.mjs +11 -0
  18. package/dist/h3-C304D6TZ.d.mts +1275 -0
  19. package/dist/h3-CGHxXEqb.mjs +2605 -0
  20. package/dist/h3-DagAgogP.mjs +4 -0
  21. package/dist/h3-QfzdiyNf.d.mts +836 -0
  22. package/dist/tracing.d.mts +26 -0
  23. package/dist/tracing.mjs +76 -0
  24. package/package.json +128 -0
  25. package/skills/h3/SKILL.md +10 -0
  26. package/skills/h3/docs/TOC.md +35 -0
  27. package/skills/h3/docs/_navigation.json +311 -0
  28. package/skills/h3/docs/examples/handle-cookie.md +67 -0
  29. package/skills/h3/docs/examples/handle-session.md +130 -0
  30. package/skills/h3/docs/examples/index.md +16 -0
  31. package/skills/h3/docs/examples/serve-static-assets.md +66 -0
  32. package/skills/h3/docs/examples/stream-response.md +76 -0
  33. package/skills/h3/docs/examples/validate-data.md +193 -0
  34. package/skills/h3/docs/guide/advanced/nightly.md +13 -0
  35. package/skills/h3/docs/guide/advanced/plugins.md +50 -0
  36. package/skills/h3/docs/guide/advanced/websocket.md +124 -0
  37. package/skills/h3/docs/guide/api/h3.md +145 -0
  38. package/skills/h3/docs/guide/api/h3event.md +113 -0
  39. package/skills/h3/docs/guide/basics/error.md +117 -0
  40. package/skills/h3/docs/guide/basics/handler.md +165 -0
  41. package/skills/h3/docs/guide/basics/lifecycle.md +68 -0
  42. package/skills/h3/docs/guide/basics/middleware.md +97 -0
  43. package/skills/h3/docs/guide/basics/nested-apps.md +57 -0
  44. package/skills/h3/docs/guide/basics/response.md +162 -0
  45. package/skills/h3/docs/guide/basics/routing.md +92 -0
  46. package/skills/h3/docs/guide/index.md +117 -0
  47. package/skills/h3/docs/migration/index.md +200 -0
  48. package/skills/h3/docs/utils/community.md +42 -0
  49. package/skills/h3/docs/utils/cookie.md +33 -0
  50. package/skills/h3/docs/utils/index.md +46 -0
  51. package/skills/h3/docs/utils/mcp.md +71 -0
  52. package/skills/h3/docs/utils/more.md +78 -0
  53. package/skills/h3/docs/utils/proxy.md +31 -0
  54. package/skills/h3/docs/utils/request.md +355 -0
  55. package/skills/h3/docs/utils/response.md +144 -0
  56. package/skills/h3/docs/utils/security.md +109 -0
@@ -0,0 +1,145 @@
1
+ # H3
2
+
3
+ > H3 class is the core of server.
4
+
5
+ You can create a new H3 app instance using `new H3()`:
6
+
7
+ ```js
8
+ import { H3 } from "h3";
9
+
10
+ const app = new H3({
11
+ /* optional config */
12
+ });
13
+ ```
14
+
15
+ ## `H3` Methods
16
+
17
+ ### `H3.request`
18
+
19
+ A [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)-compatible function allowing to fetch app routes.
20
+
21
+ - Input can be a relative path, [URL](https://developer.mozilla.org/en-US/docs/Web/API/URL), or [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request).
22
+ - Returned value is a [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) promise.
23
+
24
+ ```ts
25
+ const response = await app.request("/");
26
+ console.log(response, await response.text());
27
+ ```
28
+
29
+ ### `H3.fetch`
30
+ Similar to `H3.request` but only accepts one `(req: Request)` argument for cross runtime compatibility.
31
+
32
+ ### `H3.on`
33
+
34
+ Register route handler for specific HTTP method.
35
+
36
+ ```js
37
+ const app = new H3().on("GET", "/", () => "OK");
38
+ ```
39
+
40
+ <read-more></read-more>
41
+
42
+ ### `H3.[method]`
43
+
44
+ Register route handler for specific HTTP method (shortcut for `app.on(method, ...)`).
45
+
46
+ ```js
47
+ const app = new H3().get("/", () => "OK");
48
+ ```
49
+
50
+ ### `H3.all`
51
+
52
+ Register route handler for all HTTP methods.
53
+
54
+ ```js
55
+ const app = new H3().all("/", () => "OK");
56
+ ```
57
+
58
+ ### `H3.use`
59
+
60
+ Register a global [middleware](/guide/basics/middleware).
61
+
62
+ ```js
63
+ const app = new H3()
64
+ .use((event) => {
65
+ console.log(`request: ${event.req.url}`);
66
+ })
67
+ .all("/", () => "OK");
68
+ ```
69
+
70
+ <read-more></read-more>
71
+
72
+ ### `H3.register`
73
+
74
+ Register a H3 plugin to extend app.
75
+
76
+ <read-more></read-more>
77
+
78
+ ### `H3.handler`
79
+
80
+ An H3 [event handler](/guide/basics/handler) useful to compose multiple H3 app instances.
81
+
82
+ **Example:** Nested apps.
83
+
84
+ ```js
85
+ import { H3, serve, redirect, withBase } from "h3";
86
+
87
+ const nestedApp = new H3().get("/test", () => "/test (sub app)");
88
+
89
+ const app = new H3()
90
+ .get("/", (event) => redirect(event, "/api/test"))
91
+ .all("/api/**", withBase("/api", nestedApp.handler));
92
+
93
+ serve(app);
94
+ ```
95
+
96
+ ### `H3.mount`
97
+
98
+ Using `.mount` method, you can register a sub-app with prefix.
99
+
100
+ <read-more></read-more>
101
+
102
+ ## `H3` Options
103
+
104
+ You can pass global app configuration when initializing an app.
105
+
106
+ Supported options:
107
+
108
+ - `debug`: Displays debugging stack traces in HTTP responses (potentially dangerous for production!).
109
+ - `silent`: When enabled, console errors for unhandled exceptions will not be displayed.
110
+ - `plugins`: (see [plugins](/guide/advanced/plugins) for more information)
111
+
112
+ > [!IMPORTANT]
113
+ Enabling `debug` option, sends important stuff like stack traces in error responses. Only enable during development.
114
+
115
+ ### Global Hooks
116
+
117
+ When initializing an H3 app, you can register global hooks:
118
+
119
+ - `onError`
120
+ - `onRequest`
121
+ - `onResponse`
122
+ These hooks are called for every request and can be used to add global logic to your app such as logging, error handling, etc.
123
+
124
+ ```js
125
+ const app = new H3({
126
+ onRequest: (event) => {
127
+ console.log("Request:", event.req.url);
128
+ },
129
+ onResponse: (response, event) => {
130
+ console.log("Response:", event.url.pathname, response.status);
131
+ },
132
+ onError: (error, event) => {
133
+ console.error(error);
134
+ },
135
+ });
136
+ ```
137
+
138
+ > [!IMPORTANT]
139
+ > Global hooks only run from main H3 app and **not** sub-apps. Use [middleware](/guide/basics/middleware) for more flexibility.
140
+
141
+ ## `H3` Properties
142
+
143
+ ### `H3.config`
144
+
145
+ Global H3 instance config.
@@ -0,0 +1,113 @@
1
+ # H3Event
2
+
3
+ > H3Event, carries incoming request, prepared response and context.
4
+
5
+ With each HTTP request, H3 internally creates an `H3Event` object and passes it though event handlers until sending the response.
6
+
7
+ <read-more></read-more>
8
+
9
+ An event is passed through all the lifecycle hooks and composable utils to use it as context.
10
+
11
+ **Example:**
12
+
13
+ ```js
14
+ app.get("/", async (event) => {
15
+ // Log HTTP request
16
+ console.log(`[${event.req.method}] ${event.req.url}`);
17
+
18
+ // Parsed URL and query params
19
+ const searchParams = event.url.searchParams;
20
+
21
+ // Try to read request JSON body
22
+ const jsonBody = await event.req.json().catch(() => {});
23
+
24
+ return "OK";
25
+ });
26
+ ```
27
+
28
+ ## `H3Event` Methods
29
+
30
+ ### `H3Event.waitUntil`
31
+
32
+ Tell the runtime about an ongoing operation that shouldn't close until the promise resolves.
33
+
34
+ ```js [app.mjs]
35
+ import { logRequest } from "./tracing.mjs";
36
+
37
+ app.get("/", (event) => {
38
+ request.waitUntil(logRequest(request));
39
+ return "OK";
40
+ });
41
+ ```
42
+
43
+ ```js [tracing.mjs]
44
+ export async function logRequest(request) {
45
+ await fetch("https://telemetry.example.com", {
46
+ method: "POST",
47
+ body: JSON.stringify({
48
+ method: request.method,
49
+ url: request.url,
50
+ ip: request.ip,
51
+ }),
52
+ });
53
+ }
54
+ ```
55
+
56
+ ## `H3Event` Properties
57
+
58
+ ### `H3Event.app?`
59
+
60
+ Access to the H3 [application instance](/guide/api/h3).
61
+
62
+ ### `H3Event.context`
63
+
64
+ The context is an object that contains arbitrary information about the request.
65
+
66
+ You can store your custom properties inside `event.context` to share across utils.
67
+
68
+ **Known context keys:**
69
+
70
+ - `context.params`: Matched router parameters.
71
+ - `middlewareParams`: Matched middleware parameters
72
+ - `matchedRoute`: Matched router route object.
73
+ - `sessions`: Cached session data.
74
+ - `basicAuth`: Basic authentication data.
75
+
76
+ ### `H3Event.req`
77
+ Incoming HTTP request info based on native [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) with additional runtime addons (see [srvx docs](https://srvx.h3.dev/guide/handler#extended-request-context)).
78
+
79
+ ```ts
80
+ app.get("/", async (event) => {
81
+ const url = event.req.url;
82
+ const method = event.req.method;
83
+ const headers = event.req.headers;
84
+
85
+ // (note: you can consume body only once with either of this)
86
+ const bodyStream = await event.req.body;
87
+ const textBody = await event.req.text();
88
+ const jsonBody = await event.req.json();
89
+ const formDataBody = await event.req.formData();
90
+
91
+ return "OK";
92
+ });
93
+ ```
94
+
95
+ ### `H3Event.url`
96
+
97
+ Access to the full parsed request [URL](https://developer.mozilla.org/en-US/docs/Web/API/URL).
98
+
99
+ ### `H3Event.res`
100
+
101
+ Prepared HTTP response status and headers.
102
+
103
+ ```ts
104
+ app.get("/", (event) => {
105
+ event.res.status = 200;
106
+ event.res.statusText = "OK";
107
+ event.res.headers.set("x-test", "works");
108
+
109
+ return "OK";
110
+ });
111
+ ```
112
+
113
+ <read-more></read-more>
@@ -0,0 +1,117 @@
1
+ # Error Handling
2
+
3
+ > Send errors by throwing an HTTPError.
4
+
5
+ H3 captures all possible errors during [request lifecycle](/guide/basics/lifecycle).
6
+
7
+ ## `HTTPError`
8
+
9
+ You can create and throw HTTP errors using `HTTPError` with different syntaxes.
10
+
11
+ ```js
12
+ import { HTTPError } from "h3";
13
+
14
+ app.get("/error", (event) => {
15
+ // Using message and details
16
+ throw new HTTPError("Invalid user input", { status: 400 });
17
+
18
+ // Using HTTPError.status(code)
19
+ throw HTTPError.status(400, "Bad Request");
20
+
21
+ // Using single pbject
22
+ throw new HTTPError({
23
+ status: 400,
24
+ statusText: "Bad Request",
25
+ message: "Invalid user input",
26
+ data: { field: "email" },
27
+ body: { date: new Date().toJSON() },
28
+ headers: {},
29
+ });
30
+ });
31
+ ```
32
+
33
+ This will end the request with `400 - Bad Request` status code and the following JSON response:
34
+
35
+ ```json
36
+ {
37
+ "date": "2025-06-05T04:20:00.0Z",
38
+ "status": 400,
39
+ "statusText": "Bad Request",
40
+ "message": "Invalid user input",
41
+ "data": {
42
+ "field": "email"
43
+ }
44
+ }
45
+ ```
46
+
47
+ ### `HTTPError` Fields
48
+
49
+ - `status`: HTTP status code in the range 200–599.
50
+ - `statusText`: HTTP status text to be sent in the response header.
51
+ - `message`: Error message to be included in the JSON body.
52
+ - `data`: Additional data to be attached under the `data` key in the error JSON body.
53
+ - `body`: Additional top-level properties to be attached in the error JSON body.
54
+ - `headers`: Additional HTTP headers to be sent in the error response.
55
+ - `cause`: The original error object that caused this error, useful for tracing and debugging.
56
+ - `unhandled`: Indicates whether the error was thrown for unknown reasons. See [Unhandled Errors](#unhandled-errors).
57
+
58
+ > [!TIP]
59
+ The recommended way to include headers in error responses is to use `new HTTPError({ headers })`:
60
+
61
+ > ```js
62
+ > throw new HTTPError({
63
+ > status: 400,
64
+ > message: "Invalid input",
65
+ > headers: { "x-request-id": requestId },
66
+ > });
67
+ > ```
68
+
69
+ > When an error is thrown, any [prepared headers](/guide/basics/response#preparing-response) set via `event.res.headers` are **not** included in the error response. As a last resort for headers that need to be set implicitly before the error is known (e.g., CORS headers), you can use `event.res.errHeaders`. Built-in utilities like `handleCors` automatically set both.
70
+
71
+ > [!IMPORTANT]
72
+ > Error `statusText` should be short (max 512 to 1024 characters) and only include tab, spaces or visible ASCII characters and extended characters (byte value 128–255). Prefer `message` in JSON body for extended message.
73
+
74
+ ## Unhandled Errors
75
+
76
+ Any error that occurs during calling [request lifecycle](/guide/basics/lifecycle) without using `HTTPError` will be processed as an <u>unhandled</u> error.
77
+
78
+ ```js
79
+ app.get("/error", (event) => {
80
+ // This will cause an unhandled error.
81
+ throw new Error("Something went wrong");
82
+ });
83
+ ```
84
+
85
+ > [!TIP]
86
+ > For enhanced security, H3 hides certain fields of unhandled errors (`data`, `body`, `stack` and `message`) in JSON response.
87
+
88
+ ## Catching Errors
89
+
90
+ Using global [`onError`](/guide/api/h3#global-hooks) hook:
91
+
92
+ ```js
93
+ import { H3, onError } from "h3";
94
+
95
+ // Globally handling errors
96
+ const app = new H3({
97
+ onError: (error) => {
98
+ console.error(error);
99
+ },
100
+ });
101
+ ```
102
+
103
+ Using [`onError` middleware](/guide/basics/middleware) to catch errors.
104
+
105
+ ```js
106
+ import { onError } from "h3";
107
+
108
+ // Handling errors using middleware
109
+ app.use(
110
+ onError((error, event) => {
111
+ console.error(error);
112
+ }),
113
+ );
114
+ ```
115
+
116
+ > [!TIP]
117
+ > When using nested apps, global hooks of sub-apps will not be called. Therefore it is better to use `onError` middleware.
@@ -0,0 +1,165 @@
1
+ # Event Handlers
2
+
3
+ > An event handler is a function that receives an H3Event and returns a response.
4
+
5
+ You can define typed event handlers using `defineHandler`.
6
+
7
+ ```js
8
+ import { H3, defineHandler } from "h3";
9
+
10
+ const app = new H3();
11
+
12
+ const handler = defineHandler((event) => "Response");
13
+
14
+ app.get("/", handler);
15
+ ```
16
+
17
+ > [!NOTE]
18
+ > Using `defineHandler` is optional.
19
+ > You can instead, simply use a function that accepts an [`H3Event`](/guide/api/h3event) and returns a response.
20
+
21
+ The callback function can be sync or async:
22
+
23
+ ```js
24
+ defineHandler(async (event) => "Response");
25
+ ```
26
+
27
+ ## Object Syntax
28
+
29
+ ### middleware
30
+
31
+ You can optionally register some [middleware](/guide/basics/middleware) to run with event handler to intercept request, response or errors.
32
+
33
+ ```js
34
+ import { basicAuth } from "h3";
35
+
36
+ defineHandler({
37
+ middleware: [basicAuth({ password: "test" })],
38
+ handler: (event) => "Hi!",
39
+ });
40
+ ```
41
+
42
+ <read-more></read-more>
43
+
44
+ <read-more></read-more>
45
+
46
+ ### meta
47
+
48
+ You can define optional route meta attached to handlers, and access them from any other middleware.
49
+
50
+ ```js
51
+ import { H3, defineHandler } from "h3";
52
+
53
+ const app = new H3();
54
+
55
+ app.use((event) => {
56
+ console.log(event.context.matchedRoute?.meta); // { tag: "admin" }
57
+ });
58
+
59
+ app.get("/admin/**", defineHandler({
60
+ meta: { tag: "admin" },
61
+ handler: (event) => "Hi!",
62
+ })
63
+ ```
64
+
65
+ <read-more>
66
+
67
+ It is also possible to add route meta when registering them to app instance.
68
+ </read-more>
69
+
70
+ ## Handler `.fetch`
71
+
72
+ Event handlers defined with `defineHandler`, can act as a web handler without even using [H3](/guide/api/h3) class.
73
+
74
+ ```js
75
+ const handler = defineHandler(async (event) => `Request: ${event.req.url}`);
76
+
77
+ const response = await handler.fetch("http://localhost/");
78
+ console.log(response, await response.text());
79
+ ```
80
+
81
+ ## Lazy Handlers
82
+
83
+ You can define lazy event handlers using `defineLazyEventHandler`. This allow you to define some one-time logic that will be executed only once when the first request matching the route is received.
84
+
85
+ A lazy event handler must return an event handler.
86
+
87
+ ```js
88
+ import { defineLazyEventHandler } from "h3";
89
+
90
+ defineLazyEventHandler(async () => {
91
+ await initSomething(); // Will be executed only once
92
+ return (event) => {
93
+ return "Response";
94
+ };
95
+ });
96
+ ```
97
+
98
+ This is useful to define some one-time logic such as configuration, class initialization, heavy computation, etc.
99
+
100
+ Another use-case is lazy loading route chunks:
101
+
102
+ ```js [app.mjs]
103
+ import { H3, defineLazyEventHandler } from "h3";
104
+
105
+ const app = new H3();
106
+
107
+ app.all(
108
+ "/route",
109
+ defineLazyEventHandler(() => import("./route.mjs").then((mod) => mod.default)),
110
+ );
111
+ ```
112
+
113
+ ```js [route.mjs]
114
+ import { defineHandler } from "h3";
115
+
116
+ export default defineHandler((event) => "Hello!");
117
+ ```
118
+
119
+ ## Converting to Handler
120
+
121
+ There are situations that you might want to convert an event handler or utility made for Node.js or another framework to H3.
122
+ There are built-in utils to do this.
123
+
124
+ ### From Web Handlers
125
+
126
+ Request handlers with [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) => [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) signuture can be converted into H3 event handlers using `fromWebHandler` utility or [H3.mount](/guide/api/h3#h3mount).
127
+
128
+ ```js
129
+ import { H3, fromWebHandler } from "h3";
130
+
131
+ export const app = new H3();
132
+
133
+ const webHandler = (request) => new Response("👋 Hello!");
134
+
135
+ // Using fromWebHandler utiliy
136
+ app.all("/web", fromWebHandler(webHandler));
137
+
138
+ // Using simple wrapper
139
+ app.all("/web", (event) => webHandler(event.req));
140
+
141
+ // Using app.mount
142
+ app.mount("/web", webHandler);
143
+ ```
144
+
145
+ ### From Node.js Handlers
146
+
147
+ If you have a legacy request handler with `(req, res) => {}` syntax made for Node.js, you can use `fromNodeHandler` to convert it to an h3 event handler.
148
+
149
+ > [!IMPORTANT]
150
+ > Node.js event handlers can only run within Node.js server runtime!
151
+
152
+ ```js
153
+ import { H3, fromNodeHandler } from "h3";
154
+
155
+ // Force using Node.js compatibility (also works with Bun and Deno)
156
+ import { serve } from "h3/node";
157
+
158
+ export const app = new H3();
159
+
160
+ const nodeHandler = (req, res) => {
161
+ res.end("Node handlers work!");
162
+ };
163
+
164
+ app.get("/web", fromNodeHandler(nodeHandler));
165
+ ```
@@ -0,0 +1,68 @@
1
+ # Request Lifecycle
2
+
3
+ > H3 dispatches incoming web requests to final web responses.
4
+
5
+ Below is an overview of what happens in a H3 server from when an HTTP request arrives until a response is generated.
6
+
7
+ ## 1. Incoming Request
8
+
9
+ When An HTTP request is made by Browser or [fetch()](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API), server fetch handler receives a [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object.
10
+
11
+ ```mermaid
12
+ %%{init: {'theme':'neutral'}}%%
13
+ flowchart LR
14
+ A1["<code>fetch(request)</code>"] --> A2["<code>server.fetch(request)</code>"]
15
+
16
+ click A2 "/guide/api/h3#h3fetch"
17
+ ```
18
+
19
+ > [!TIP]
20
+ > ​[💥 Srvx](https://srvx.h3.dev) provides unified `server.fetch` interface and adds [Node.js compatibility](https://srvx.h3.dev/guide/node).
21
+
22
+ ## 2. Accept Request
23
+
24
+ H3 Initializes an [`H3Event`](/guide/api/h3event) instance from incoming request, calls [`onRequest`](/guide/api/h3#global-hooks) global hook and finally [`H3.handler`](/guide/api/h3#h3handler) with the initialized event.
25
+
26
+ ```mermaid
27
+ %%{init: {'theme':'neutral'}}%%
28
+ flowchart LR
29
+ B1["<code>new H3Event(request)</code>"] --> B2["<code>onRequest(event)</code>"] --> B3["<code>h3.handler(event)</code>"]
30
+
31
+ click B1 "/guide/api/h3event"
32
+ click B2 "/guide/api/h3#global-hooks"
33
+ click B3 "/guide/api/h3#apphandler"
34
+ ```
35
+
36
+ ## 3. Dispatch Request
37
+
38
+ H3 [matches route](/guide/basics/routing) based on `request.url` and `request.method`, calls global [middleware](/guide/basics/middleware) and finally matched route handler function with event.
39
+
40
+ ```mermaid
41
+ %%{init: {'theme':'neutral'}}%%
42
+ sequenceDiagram
43
+ participant MiddlewareA as Middleware1(event, next)
44
+ participant MiddlewareB as Middleware2(event, next)
45
+ participant Route as RouteHandler(event)
46
+
47
+ MiddlewareA->>+MiddlewareB: await next()
48
+ MiddlewareB->>+Route: await next()
49
+ Route-->>-MiddlewareB: rawBody
50
+ MiddlewareB-->>-MiddlewareA: rawBody
51
+
52
+ ```
53
+
54
+ > [!TIP]
55
+ > 🚀 Internally, H3 uses srvx `FastURL` instead of `new URL(req.url).pathname`.
56
+
57
+ ## 4. Send Response
58
+
59
+ H3 [converts](/guide/basics/response#response-types) returned value and [prepared headers](/guide/basics/response#preparing-response) into a [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response), calls [`onResponse`](/guide/api/h3#global-hooks) global hook and finally returns response back to the server fetch handler.
60
+
61
+ ```mermaid
62
+ %%{init: {'theme':'neutral'}}%%
63
+ flowchart LR
64
+ D1["Returned Value => Response"] --> D2["<code>onResponse(response)</code>"] --> D3["Response"]
65
+
66
+ click D1 "/guide/basics/response"
67
+ click D2 "/guide/api/h3#global-hooks"
68
+ ```
@@ -0,0 +1,97 @@
1
+ # Middleware
2
+
3
+ > Intercept request, response and errors using H3 middleware.
4
+
5
+ > [!IMPORTANT]
6
+ > We recommend using composable utilities whenever possible. Global middleware can complicate application logic, making it less predictable and harder to understand.
7
+
8
+ Global middleware run on each request before route handler and act as wrappers to intercept request, response and errors.
9
+
10
+ <read-more></read-more>
11
+
12
+ You can register global middleware to [app instance](/guide/api/h3) using the [`H3.use`](/guide/api/h3#h3use).
13
+
14
+ **Example:** Register a global middleware that logs every request.
15
+
16
+ ```js
17
+ app.use((event) => {
18
+ console.log(event);
19
+ });
20
+ ```
21
+
22
+ **Example:** Register a global middleware that matches certain requests.
23
+
24
+ ```js
25
+ app.use(
26
+ "/blog/**",
27
+ (event, next) => {
28
+ console.log("[alert] POST request on /blog paths!");
29
+ },
30
+ {
31
+ method: "POST",
32
+ // match: (event) => event.req.method === "POST",
33
+ },
34
+ );
35
+ ```
36
+
37
+ You can register middleware with `next` argument to intercept return values of next middleware and handler.
38
+
39
+ ```js
40
+ app.use(async (event, next) => {
41
+ const rawBody = await next();
42
+ // [intercept response]
43
+ return rawBody;
44
+ });
45
+ ```
46
+
47
+ Example below, always responds with `Middleware 1`.
48
+
49
+ ```js
50
+ app
51
+ .use(() => "Middleware 1")
52
+ .use(() => "Middleware 2")
53
+ .get("/", "Hello");
54
+ ```
55
+
56
+ > [!IMPORTANT]
57
+ > If middleware returns a value other than `undefined` or the result of `next()`, it immediately intercepts request handling and sends a response.
58
+
59
+ When adding routes, you can register middleware that only run with them.
60
+
61
+ ```js
62
+ import { basicAuth } from "h3";
63
+
64
+ app.get(
65
+ "/secret",
66
+ (event) => {
67
+ /* ... */
68
+ },
69
+ {
70
+ middleware: [basicAuth({ password: "test" })],
71
+ },
72
+ );
73
+ ```
74
+
75
+ For convenience, H3 provides middleware factory functions `onRequest`, `onResponse`, and `onError`:
76
+
77
+ ```js
78
+ import { onRequest, onResponse, onError } from "h3";
79
+
80
+ app.use(
81
+ onRequest((event) => {
82
+ console.log(`[${event.req.method}] ${event.url.pathname}`);
83
+ }),
84
+ );
85
+
86
+ app.use(
87
+ onResponse((response, event) => {
88
+ console.log(`[${event.req.method}] ${event.url.pathname} ~>`, response.status);
89
+ }),
90
+ );
91
+
92
+ app.use(
93
+ onError((error, event) => {
94
+ console.log(`[${event.req.method}] ${event.url.pathname} !! ${error.message}`);
95
+ }),
96
+ );
97
+ ```