1 | import { getQuery as getQuery$1, withoutTrailingSlash, withoutBase } from 'ufo';
|
2 | import destr from 'destr';
|
3 | import { parse, serialize } from 'cookie-es';
|
4 | import { createRouter as createRouter$1 } from 'radix3';
|
5 |
|
6 | class H3Error extends Error {
|
7 | constructor() {
|
8 | super(...arguments);
|
9 | this.statusCode = 500;
|
10 | this.fatal = false;
|
11 | this.unhandled = false;
|
12 | this.statusMessage = "Internal Server Error";
|
13 | }
|
14 | }
|
15 | H3Error.__h3_error__ = true;
|
16 | function createError(input) {
|
17 | if (typeof input === "string") {
|
18 | return new H3Error(input);
|
19 | }
|
20 | if (isError(input)) {
|
21 | return input;
|
22 | }
|
23 | const err = new H3Error(input.message ?? input.statusMessage, input.cause ? { cause: input.cause } : void 0);
|
24 | if ("stack" in input) {
|
25 | try {
|
26 | Object.defineProperty(err, "stack", { get() {
|
27 | return input.stack;
|
28 | } });
|
29 | } catch {
|
30 | try {
|
31 | err.stack = input.stack;
|
32 | } catch {
|
33 | }
|
34 | }
|
35 | }
|
36 | if (input.statusCode) {
|
37 | err.statusCode = input.statusCode;
|
38 | }
|
39 | if (input.statusMessage) {
|
40 | err.statusMessage = input.statusMessage;
|
41 | }
|
42 | if (input.data) {
|
43 | err.data = input.data;
|
44 | }
|
45 | if (input.fatal !== void 0) {
|
46 | err.fatal = input.fatal;
|
47 | }
|
48 | if (input.unhandled !== void 0) {
|
49 | err.unhandled = input.unhandled;
|
50 | }
|
51 | return err;
|
52 | }
|
53 | function sendError(event, error, debug) {
|
54 | if (event.res.writableEnded) {
|
55 | return;
|
56 | }
|
57 | const h3Error = isError(error) ? error : createError(error);
|
58 | const responseBody = {
|
59 | statusCode: h3Error.statusCode,
|
60 | statusMessage: h3Error.statusMessage,
|
61 | stack: [],
|
62 | data: h3Error.data
|
63 | };
|
64 | if (debug) {
|
65 | responseBody.stack = (h3Error.stack || "").split("\n").map((l) => l.trim());
|
66 | }
|
67 | if (event.res.writableEnded) {
|
68 | return;
|
69 | }
|
70 | event.res.statusCode = h3Error.statusCode;
|
71 | event.res.statusMessage = h3Error.statusMessage;
|
72 | event.res.setHeader("Content-Type", MIMES.json);
|
73 | event.res.end(JSON.stringify(responseBody, null, 2));
|
74 | }
|
75 | function isError(input) {
|
76 | return input?.constructor?.__h3_error__ === true;
|
77 | }
|
78 |
|
79 | function getQuery(event) {
|
80 | return getQuery$1(event.req.url || "");
|
81 | }
|
82 | const useQuery = getQuery;
|
83 | function getRouterParams(event) {
|
84 | return event.context.params || {};
|
85 | }
|
86 | function getRouterParam(event, name) {
|
87 | const params = getRouterParams(event);
|
88 | return params[name];
|
89 | }
|
90 | function getMethod(event, defaultMethod = "GET") {
|
91 | return (event.req.method || defaultMethod).toUpperCase();
|
92 | }
|
93 | const useMethod = getMethod;
|
94 | function isMethod(event, expected, allowHead) {
|
95 | const method = getMethod(event);
|
96 | if (allowHead && method === "HEAD") {
|
97 | return true;
|
98 | }
|
99 | if (typeof expected === "string") {
|
100 | if (method === expected) {
|
101 | return true;
|
102 | }
|
103 | } else if (expected.includes(method)) {
|
104 | return true;
|
105 | }
|
106 | return false;
|
107 | }
|
108 | function assertMethod(event, expected, allowHead) {
|
109 | if (!isMethod(event, expected, allowHead)) {
|
110 | throw createError({
|
111 | statusCode: 405,
|
112 | statusMessage: "HTTP method is not allowed."
|
113 | });
|
114 | }
|
115 | }
|
116 | function getRequestHeaders(event) {
|
117 | return event.req.headers;
|
118 | }
|
119 | const getHeaders = getRequestHeaders;
|
120 | function getRequestHeader(event, name) {
|
121 | const headers = getRequestHeaders(event);
|
122 | const value = headers[name.toLowerCase()];
|
123 | return value;
|
124 | }
|
125 | const getHeader = getRequestHeader;
|
126 |
|
127 | const RawBodySymbol = Symbol.for("h3RawBody");
|
128 | const ParsedBodySymbol = Symbol.for("h3ParsedBody");
|
129 | const PayloadMethods = ["PATCH", "POST", "PUT", "DELETE"];
|
130 | function readRawBody(event, encoding = "utf-8") {
|
131 | assertMethod(event, PayloadMethods);
|
132 | if (RawBodySymbol in event.req) {
|
133 | const promise2 = Promise.resolve(event.req[RawBodySymbol]);
|
134 | return encoding ? promise2.then((buff) => buff.toString(encoding)) : promise2;
|
135 | }
|
136 | if ("body" in event.req) {
|
137 | return Promise.resolve(event.req.body);
|
138 | }
|
139 | const promise = event.req[RawBodySymbol] = new Promise((resolve, reject) => {
|
140 | const bodyData = [];
|
141 | event.req.on("error", (err) => {
|
142 | reject(err);
|
143 | }).on("data", (chunk) => {
|
144 | bodyData.push(chunk);
|
145 | }).on("end", () => {
|
146 | resolve(Buffer.concat(bodyData));
|
147 | });
|
148 | });
|
149 | return encoding ? promise.then((buff) => buff.toString(encoding)) : promise;
|
150 | }
|
151 | const useRawBody = readRawBody;
|
152 | async function readBody(event) {
|
153 | if (ParsedBodySymbol in event.req) {
|
154 | return event.req[ParsedBodySymbol];
|
155 | }
|
156 | const body = await readRawBody(event);
|
157 | if (event.req.headers["content-type"] === "application/x-www-form-urlencoded") {
|
158 | const parsedForm = Object.fromEntries(new URLSearchParams(body));
|
159 | return parsedForm;
|
160 | }
|
161 | const json = destr(body);
|
162 | event.req[ParsedBodySymbol] = json;
|
163 | return json;
|
164 | }
|
165 | const useBody = readBody;
|
166 |
|
167 | function handleCacheHeaders(event, opts) {
|
168 | const cacheControls = ["public"].concat(opts.cacheControls || []);
|
169 | let cacheMatched = false;
|
170 | if (opts.maxAge !== void 0) {
|
171 | cacheControls.push(`max-age=${+opts.maxAge}`, `s-maxage=${+opts.maxAge}`);
|
172 | }
|
173 | if (opts.modifiedTime) {
|
174 | const modifiedTime = new Date(opts.modifiedTime);
|
175 | const ifModifiedSince = event.req.headers["if-modified-since"];
|
176 | event.res.setHeader("Last-Modified", modifiedTime.toUTCString());
|
177 | if (ifModifiedSince) {
|
178 | if (new Date(ifModifiedSince) >= opts.modifiedTime) {
|
179 | cacheMatched = true;
|
180 | }
|
181 | }
|
182 | }
|
183 | if (opts.etag) {
|
184 | event.res.setHeader("Etag", opts.etag);
|
185 | const ifNonMatch = event.req.headers["if-none-match"];
|
186 | if (ifNonMatch === opts.etag) {
|
187 | cacheMatched = true;
|
188 | }
|
189 | }
|
190 | event.res.setHeader("Cache-Control", cacheControls.join(", "));
|
191 | if (cacheMatched) {
|
192 | event.res.statusCode = 304;
|
193 | event.res.end("");
|
194 | return true;
|
195 | }
|
196 | return false;
|
197 | }
|
198 |
|
199 | const MIMES = {
|
200 | html: "text/html",
|
201 | json: "application/json"
|
202 | };
|
203 |
|
204 | const defer = typeof setImmediate !== "undefined" ? setImmediate : (fn) => fn();
|
205 | function send(event, data, type) {
|
206 | if (type) {
|
207 | defaultContentType(event, type);
|
208 | }
|
209 | return new Promise((resolve) => {
|
210 | defer(() => {
|
211 | event.res.end(data);
|
212 | resolve(void 0);
|
213 | });
|
214 | });
|
215 | }
|
216 | function defaultContentType(event, type) {
|
217 | if (type && !event.res.getHeader("Content-Type")) {
|
218 | event.res.setHeader("Content-Type", type);
|
219 | }
|
220 | }
|
221 | function sendRedirect(event, location, code = 302) {
|
222 | event.res.statusCode = code;
|
223 | event.res.setHeader("Location", location);
|
224 | const encodedLoc = location.replace(/"/g, "%22");
|
225 | const html = `<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0; url=${encodedLoc}"></head></html>`;
|
226 | return send(event, html, MIMES.html);
|
227 | }
|
228 | function getResponseHeaders(event) {
|
229 | return event.res.getHeaders();
|
230 | }
|
231 | function getResponseHeader(event, name) {
|
232 | return event.res.getHeader(name);
|
233 | }
|
234 | function setResponseHeaders(event, headers) {
|
235 | Object.entries(headers).forEach(([name, value]) => event.res.setHeader(name, value));
|
236 | }
|
237 | const setHeaders = setResponseHeaders;
|
238 | function setResponseHeader(event, name, value) {
|
239 | event.res.setHeader(name, value);
|
240 | }
|
241 | const setHeader = setResponseHeader;
|
242 | function appendResponseHeaders(event, headers) {
|
243 | Object.entries(headers).forEach(([name, value]) => appendResponseHeader(event, name, value));
|
244 | }
|
245 | const appendHeaders = appendResponseHeaders;
|
246 | function appendResponseHeader(event, name, value) {
|
247 | let current = event.res.getHeader(name);
|
248 | if (!current) {
|
249 | event.res.setHeader(name, value);
|
250 | return;
|
251 | }
|
252 | if (!Array.isArray(current)) {
|
253 | current = [current.toString()];
|
254 | }
|
255 | event.res.setHeader(name, current.concat(value));
|
256 | }
|
257 | const appendHeader = appendResponseHeader;
|
258 | function isStream(data) {
|
259 | return data && typeof data === "object" && typeof data.pipe === "function" && typeof data.on === "function";
|
260 | }
|
261 | function sendStream(event, data) {
|
262 | return new Promise((resolve, reject) => {
|
263 | data.pipe(event.res);
|
264 | data.on("end", () => resolve(void 0));
|
265 | data.on("error", (error) => reject(createError(error)));
|
266 | });
|
267 | }
|
268 |
|
269 | function parseCookies(event) {
|
270 | return parse(event.req.headers.cookie || "");
|
271 | }
|
272 | const useCookies = parseCookies;
|
273 | function getCookie(event, name) {
|
274 | return parseCookies(event)[name];
|
275 | }
|
276 | const useCookie = getCookie;
|
277 | function setCookie(event, name, value, serializeOptions) {
|
278 | const cookieStr = serialize(name, value, {
|
279 | path: "/",
|
280 | ...serializeOptions
|
281 | });
|
282 | appendHeader(event, "Set-Cookie", cookieStr);
|
283 | }
|
284 | function deleteCookie(event, name, serializeOptions) {
|
285 | setCookie(event, name, "", {
|
286 | ...serializeOptions,
|
287 | maxAge: 0
|
288 | });
|
289 | }
|
290 |
|
291 | class H3Headers {
|
292 | constructor(init) {
|
293 | if (!init) {
|
294 | this._headers = {};
|
295 | } else if (Array.isArray(init)) {
|
296 | this._headers = Object.fromEntries(init.map(([key, value]) => [key.toLowerCase(), value]));
|
297 | } else if (init && "append" in init) {
|
298 | this._headers = Object.fromEntries([...init.entries()]);
|
299 | } else {
|
300 | this._headers = Object.fromEntries(Object.entries(init).map(([key, value]) => [key.toLowerCase(), value]));
|
301 | }
|
302 | }
|
303 | append(name, value) {
|
304 | const _name = name.toLowerCase();
|
305 | this.set(_name, [this.get(_name), value].filter(Boolean).join(", "));
|
306 | }
|
307 | delete(name) {
|
308 | delete this._headers[name.toLowerCase()];
|
309 | }
|
310 | get(name) {
|
311 | return this._headers[name.toLowerCase()];
|
312 | }
|
313 | has(name) {
|
314 | return name.toLowerCase() in this._headers;
|
315 | }
|
316 | set(name, value) {
|
317 | this._headers[name.toLowerCase()] = String(value);
|
318 | }
|
319 | forEach(callbackfn) {
|
320 | Object.entries(this._headers).forEach(([key, value]) => callbackfn(value, key, this));
|
321 | }
|
322 | }
|
323 |
|
324 | class H3Response {
|
325 | constructor(body = null, init = {}) {
|
326 | this.body = null;
|
327 | this.type = "default";
|
328 | this.bodyUsed = false;
|
329 | this.headers = new H3Headers(init.headers);
|
330 | this.status = init.status ?? 200;
|
331 | this.statusText = init.statusText || "";
|
332 | this.redirected = !!init.status && [301, 302, 307, 308].includes(init.status);
|
333 | this._body = body;
|
334 | this.url = "";
|
335 | this.ok = this.status < 300 && this.status > 199;
|
336 | }
|
337 | clone() {
|
338 | return new H3Response(this.body, {
|
339 | headers: this.headers,
|
340 | status: this.status,
|
341 | statusText: this.statusText
|
342 | });
|
343 | }
|
344 | arrayBuffer() {
|
345 | return Promise.resolve(this._body);
|
346 | }
|
347 | blob() {
|
348 | return Promise.resolve(this._body);
|
349 | }
|
350 | formData() {
|
351 | return Promise.resolve(this._body);
|
352 | }
|
353 | json() {
|
354 | return Promise.resolve(this._body);
|
355 | }
|
356 | text() {
|
357 | return Promise.resolve(this._body);
|
358 | }
|
359 | }
|
360 |
|
361 | class H3Event {
|
362 | constructor(req, res) {
|
363 | this["__is_event__"] = true;
|
364 | this.context = {};
|
365 | this.req = req;
|
366 | this.res = res;
|
367 | this.event = this;
|
368 | req.event = this;
|
369 | req.context = this.context;
|
370 | req.req = req;
|
371 | req.res = res;
|
372 | res.event = this;
|
373 | res.res = res;
|
374 | res.req = res.req || {};
|
375 | res.req.res = res;
|
376 | res.req.req = req;
|
377 | }
|
378 | respondWith(r) {
|
379 | Promise.resolve(r).then((_response) => {
|
380 | if (this.res.writableEnded) {
|
381 | return;
|
382 | }
|
383 | const response = _response instanceof H3Response ? _response : new H3Response(_response);
|
384 | response.headers.forEach((value, key) => {
|
385 | this.res.setHeader(key, value);
|
386 | });
|
387 | if (response.status) {
|
388 | this.res.statusCode = response.status;
|
389 | }
|
390 | if (response.statusText) {
|
391 | this.res.statusMessage = response.statusText;
|
392 | }
|
393 | if (response.redirected) {
|
394 | this.res.setHeader("Location", response.url);
|
395 | }
|
396 | if (!response._body) {
|
397 | return this.res.end();
|
398 | }
|
399 | if (typeof response._body === "string" || "buffer" in response._body || "byteLength" in response._body) {
|
400 | return this.res.end(response._body);
|
401 | }
|
402 | if (!response.headers.has("content-type")) {
|
403 | response.headers.set("content-type", MIMES.json);
|
404 | }
|
405 | this.res.end(JSON.stringify(response._body));
|
406 | });
|
407 | }
|
408 | }
|
409 | function isEvent(input) {
|
410 | return "__is_event__" in input;
|
411 | }
|
412 | function createEvent(req, res) {
|
413 | return new H3Event(req, res);
|
414 | }
|
415 |
|
416 | const defineHandler = (handler) => handler;
|
417 | const defineHandle = defineHandler;
|
418 | const defineMiddleware = (middleware) => middleware;
|
419 | function promisifyHandler(handler) {
|
420 | return function(req, res) {
|
421 | return callHandler(handler, req, res);
|
422 | };
|
423 | }
|
424 | const promisifyHandle = promisifyHandler;
|
425 | function callHandler(handler, req, res) {
|
426 | const isMiddleware = handler.length > 2;
|
427 | return new Promise((resolve, reject) => {
|
428 | const next = (err) => {
|
429 | if (isMiddleware) {
|
430 | res.off("close", next);
|
431 | res.off("error", next);
|
432 | }
|
433 | return err ? reject(createError(err)) : resolve(void 0);
|
434 | };
|
435 | try {
|
436 | const returned = handler(req, res, next);
|
437 | if (isMiddleware && returned === void 0) {
|
438 | res.once("close", next);
|
439 | res.once("error", next);
|
440 | } else {
|
441 | resolve(returned);
|
442 | }
|
443 | } catch (err) {
|
444 | next(err);
|
445 | }
|
446 | });
|
447 | }
|
448 | function defineLazyHandler(handler, promisify) {
|
449 | let _promise;
|
450 | const resolve = () => {
|
451 | if (!_promise) {
|
452 | _promise = Promise.resolve(handler()).then((r) => promisify ? promisifyHandler(r.default || r) : r.default || r);
|
453 | }
|
454 | return _promise;
|
455 | };
|
456 | return function(req, res) {
|
457 | return resolve().then((h) => h(req, res));
|
458 | };
|
459 | }
|
460 | const lazyHandle = defineLazyHandler;
|
461 | function useBase(base, handler) {
|
462 | base = withoutTrailingSlash(base);
|
463 | if (!base) {
|
464 | return handler;
|
465 | }
|
466 | return function(req, res) {
|
467 | req.originalUrl = req.originalUrl || req.url || "/";
|
468 | req.url = withoutBase(req.url || "/", base);
|
469 | return handler(req, res);
|
470 | };
|
471 | }
|
472 |
|
473 | function defineEventHandler(handler) {
|
474 | handler.__is_handler__ = true;
|
475 | return handler;
|
476 | }
|
477 | const eventHandler = defineEventHandler;
|
478 | function isEventHandler(input) {
|
479 | return "__is_handler__" in input;
|
480 | }
|
481 | function toEventHandler(handler) {
|
482 | if (isEventHandler(handler)) {
|
483 | return handler;
|
484 | }
|
485 | if (typeof handler !== "function") {
|
486 | throw new TypeError("Invalid handler. It should be a function:", handler);
|
487 | }
|
488 | return eventHandler((event) => {
|
489 | return callHandler(handler, event.req, event.res);
|
490 | });
|
491 | }
|
492 | function dynamicEventHandler(initial) {
|
493 | let current = initial;
|
494 | const wrapper = eventHandler((event) => {
|
495 | if (current) {
|
496 | return current(event);
|
497 | }
|
498 | });
|
499 | wrapper.set = (handler) => {
|
500 | current = handler;
|
501 | };
|
502 | return wrapper;
|
503 | }
|
504 | function defineLazyEventHandler(factory) {
|
505 | let _promise;
|
506 | let _resolved;
|
507 | const resolveHandler = () => {
|
508 | if (_resolved) {
|
509 | return Promise.resolve(_resolved);
|
510 | }
|
511 | if (!_promise) {
|
512 | _promise = Promise.resolve(factory()).then((r) => {
|
513 | const handler = r.default || r;
|
514 | if (typeof handler !== "function") {
|
515 | throw new TypeError("Invalid lazy handler result. It should be a function:", handler);
|
516 | }
|
517 | _resolved = toEventHandler(r.default || r);
|
518 | return _resolved;
|
519 | });
|
520 | }
|
521 | return _promise;
|
522 | };
|
523 | return eventHandler((event) => {
|
524 | if (_resolved) {
|
525 | return _resolved(event);
|
526 | }
|
527 | return resolveHandler().then((handler) => handler(event));
|
528 | });
|
529 | }
|
530 | const lazyEventHandler = defineLazyEventHandler;
|
531 |
|
532 | function createApp(options = {}) {
|
533 | const stack = [];
|
534 | const handler = createAppEventHandler(stack, options);
|
535 | const nodeHandler = async function(req, res) {
|
536 | const event = createEvent(req, res);
|
537 | try {
|
538 | await handler(event);
|
539 | } catch (_error) {
|
540 | const error = createError(_error);
|
541 | if (!isError(_error)) {
|
542 | error.unhandled = true;
|
543 | }
|
544 | if (options.onError) {
|
545 | await options.onError(error, event);
|
546 | } else {
|
547 | if (error.unhandled || error.fatal) {
|
548 | console.error("[h3]", error.fatal ? "[fatal]" : "[unhandled]", error);
|
549 | }
|
550 | await sendError(event, error, !!options.debug);
|
551 | }
|
552 | }
|
553 | };
|
554 | const app = nodeHandler;
|
555 | app.nodeHandler = nodeHandler;
|
556 | app.stack = stack;
|
557 | app.handler = handler;
|
558 | app.use = (arg1, arg2, arg3) => use(app, arg1, arg2, arg3);
|
559 | return app;
|
560 | }
|
561 | function use(app, arg1, arg2, arg3) {
|
562 | if (Array.isArray(arg1)) {
|
563 | arg1.forEach((i) => use(app, i, arg2, arg3));
|
564 | } else if (Array.isArray(arg2)) {
|
565 | arg2.forEach((i) => use(app, arg1, i, arg3));
|
566 | } else if (typeof arg1 === "string") {
|
567 | app.stack.push(normalizeLayer({ ...arg3, route: arg1, handler: arg2 }));
|
568 | } else if (typeof arg1 === "function") {
|
569 | app.stack.push(normalizeLayer({ ...arg2, route: "/", handler: arg1 }));
|
570 | } else {
|
571 | app.stack.push(normalizeLayer({ ...arg1 }));
|
572 | }
|
573 | return app;
|
574 | }
|
575 | function createAppEventHandler(stack, options) {
|
576 | const spacing = options.debug ? 2 : void 0;
|
577 | return eventHandler(async (event) => {
|
578 | event.req.originalUrl = event.req.originalUrl || event.req.url || "/";
|
579 | const reqUrl = event.req.url || "/";
|
580 | for (const layer of stack) {
|
581 | if (layer.route.length > 1) {
|
582 | if (!reqUrl.startsWith(layer.route)) {
|
583 | continue;
|
584 | }
|
585 | event.req.url = reqUrl.slice(layer.route.length) || "/";
|
586 | } else {
|
587 | event.req.url = reqUrl;
|
588 | }
|
589 | if (layer.match && !layer.match(event.req.url, event)) {
|
590 | continue;
|
591 | }
|
592 | const val = await layer.handler(event);
|
593 | if (event.res.writableEnded) {
|
594 | return;
|
595 | }
|
596 | const type = typeof val;
|
597 | if (type === "string") {
|
598 | return send(event, val, MIMES.html);
|
599 | } else if (isStream(val)) {
|
600 | return sendStream(event, val);
|
601 | } else if (val === null) {
|
602 | event.res.statusCode = 204;
|
603 | return send(event);
|
604 | } else if (type === "object" || type === "boolean" || type === "number") {
|
605 | if (val.buffer) {
|
606 | return send(event, val);
|
607 | } else if (val instanceof Error) {
|
608 | throw createError(val);
|
609 | } else {
|
610 | return send(event, JSON.stringify(val, null, spacing), MIMES.json);
|
611 | }
|
612 | }
|
613 | }
|
614 | if (!event.res.writableEnded) {
|
615 | throw createError({ statusCode: 404, statusMessage: "Not Found" });
|
616 | }
|
617 | });
|
618 | }
|
619 | function normalizeLayer(input) {
|
620 | let handler = input.handler || input.handle;
|
621 | if (handler.handler) {
|
622 | handler = handler.handler;
|
623 | }
|
624 | if (input.lazy) {
|
625 | handler = lazyEventHandler(handler);
|
626 | } else if (!isEventHandler(handler)) {
|
627 | handler = toEventHandler(handler);
|
628 | }
|
629 | return {
|
630 | route: withoutTrailingSlash(input.route),
|
631 | match: input.match,
|
632 | handler
|
633 | };
|
634 | }
|
635 |
|
636 | const RouterMethods = ["connect", "delete", "get", "head", "options", "post", "put", "trace", "patch"];
|
637 | function createRouter() {
|
638 | const _router = createRouter$1({});
|
639 | const routes = {};
|
640 | const router = {};
|
641 | const addRoute = (path, handler, method) => {
|
642 | let route = routes[path];
|
643 | if (!route) {
|
644 | routes[path] = route = { handlers: {} };
|
645 | _router.insert(path, route);
|
646 | }
|
647 | if (Array.isArray(method)) {
|
648 | method.forEach((m) => addRoute(path, handler, m));
|
649 | } else {
|
650 | route.handlers[method] = toEventHandler(handler);
|
651 | }
|
652 | return router;
|
653 | };
|
654 | router.use = router.add = (path, handler, method) => addRoute(path, handler, method || "all");
|
655 | for (const method of RouterMethods) {
|
656 | router[method] = (path, handle) => router.add(path, handle, method);
|
657 | }
|
658 | router.handler = eventHandler((event) => {
|
659 | let path = event.req.url || "/";
|
660 | const queryUrlIndex = path.lastIndexOf("?");
|
661 | if (queryUrlIndex > -1) {
|
662 | path = path.substring(0, queryUrlIndex);
|
663 | }
|
664 | const matched = _router.lookup(path);
|
665 | if (!matched) {
|
666 | throw createError({
|
667 | statusCode: 404,
|
668 | name: "Not Found",
|
669 | statusMessage: `Cannot find any route matching ${event.req.url || "/"}.`
|
670 | });
|
671 | }
|
672 | const method = (event.req.method || "get").toLowerCase();
|
673 | const handler = matched.handlers[method] || matched.handlers.all;
|
674 | if (!handler) {
|
675 | throw createError({
|
676 | statusCode: 405,
|
677 | name: "Method Not Allowed",
|
678 | statusMessage: `Method ${method} is not allowed on this route.`
|
679 | });
|
680 | }
|
681 | const params = matched.params || {};
|
682 | event.event.context.params = params;
|
683 | event.req.context.params = params;
|
684 | return handler(event);
|
685 | });
|
686 | return router;
|
687 | }
|
688 |
|
689 | export { H3Error, H3Event, H3Headers, H3Response, MIMES, appendHeader, appendHeaders, appendResponseHeader, appendResponseHeaders, assertMethod, callHandler, createApp, createAppEventHandler, createError, createEvent, createRouter, defaultContentType, defineEventHandler, defineHandle, defineHandler, defineLazyEventHandler, defineLazyHandler, defineMiddleware, deleteCookie, dynamicEventHandler, eventHandler, getCookie, getHeader, getHeaders, getMethod, getQuery, getRequestHeader, getRequestHeaders, getResponseHeader, getResponseHeaders, getRouterParam, getRouterParams, handleCacheHeaders, isError, isEvent, isEventHandler, isMethod, isStream, lazyEventHandler, lazyHandle, parseCookies, promisifyHandle, promisifyHandler, readBody, readRawBody, send, sendError, sendRedirect, sendStream, setCookie, setHeader, setHeaders, setResponseHeader, setResponseHeaders, toEventHandler, use, useBase, useBody, useCookie, useCookies, useMethod, useQuery, useRawBody };
|