h3 2.0.0-beta.2 → 2.0.0-beta.4
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.
- package/dist/_entries/bun.d.mts +2 -2
- package/dist/_entries/bun.mjs +3 -3
- package/dist/_entries/cloudflare.d.mts +2 -2
- package/dist/_entries/cloudflare.mjs +3 -3
- package/dist/_entries/deno.d.mts +2 -2
- package/dist/_entries/deno.mjs +3 -3
- package/dist/_entries/generic.d.mts +2 -2
- package/dist/_entries/generic.mjs +3 -3
- package/dist/_entries/node.d.mts +2 -2
- package/dist/_entries/node.mjs +3 -3
- package/dist/_entries/service-worker.d.mts +2 -2
- package/dist/_entries/service-worker.mjs +3 -3
- package/dist/h3.d.mts +89 -45
- package/dist/h3.mjs +631 -512
- package/package.json +19 -20
package/dist/h3.mjs
CHANGED
|
@@ -49,7 +49,7 @@ var H3Event = class {
|
|
|
49
49
|
*/
|
|
50
50
|
_res;
|
|
51
51
|
constructor(req, context, app) {
|
|
52
|
-
this.context = context || new EmptyObject();
|
|
52
|
+
this.context = context || req.context || new EmptyObject();
|
|
53
53
|
this.req = req;
|
|
54
54
|
this.app = app;
|
|
55
55
|
const _url = req._url;
|
|
@@ -297,9 +297,9 @@ function isJSONSerializable(value, _type) {
|
|
|
297
297
|
const kNotFound = /* @__PURE__ */ Symbol.for("h3.notFound");
|
|
298
298
|
const kHandled = /* @__PURE__ */ Symbol.for("h3.handled");
|
|
299
299
|
function toResponse(val, event, config = {}) {
|
|
300
|
-
if (
|
|
300
|
+
if (typeof val?.then === "function") return (val.catch?.((error) => error) || Promise.resolve(val)).then((resolvedVal) => toResponse(resolvedVal, event, config));
|
|
301
301
|
const response = prepareResponse(val, event, config);
|
|
302
|
-
if (response
|
|
302
|
+
if (typeof response?.then === "function") return toResponse(response, event, config);
|
|
303
303
|
const { onResponse: onResponse$1 } = config;
|
|
304
304
|
return onResponse$1 ? Promise.resolve(onResponse$1(response, event)).then(() => response) : response;
|
|
305
305
|
}
|
|
@@ -440,190 +440,77 @@ function callMiddleware(event, middleware, handler, index = 0) {
|
|
|
440
440
|
return nextResult;
|
|
441
441
|
};
|
|
442
442
|
const ret = fn(event, next);
|
|
443
|
-
return ret === void 0 || ret === kNotFound ? next() : ret
|
|
443
|
+
return ret === void 0 || ret === kNotFound ? next() : typeof ret?.then === "function" ? ret.then((resolved) => resolved === void 0 || resolved === kNotFound ? next() : resolved) : ret;
|
|
444
444
|
}
|
|
445
445
|
|
|
446
446
|
//#endregion
|
|
447
|
-
//#region src/
|
|
448
|
-
const
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
447
|
+
//#region src/utils/internal/query.ts
|
|
448
|
+
const plusRegex = /\+/g;
|
|
449
|
+
function parseQuery(input) {
|
|
450
|
+
const params = new EmptyObject();
|
|
451
|
+
if (!input || input === "?") return params;
|
|
452
|
+
const inputLength = input.length;
|
|
453
|
+
let key = "";
|
|
454
|
+
let value = "";
|
|
455
|
+
let startingIndex = -1;
|
|
456
|
+
let equalityIndex = -1;
|
|
457
|
+
let shouldDecodeKey = false;
|
|
458
|
+
let shouldDecodeValue = false;
|
|
459
|
+
let keyHasPlus = false;
|
|
460
|
+
let valueHasPlus = false;
|
|
461
|
+
let hasBothKeyValuePair = false;
|
|
462
|
+
let c = 0;
|
|
463
|
+
for (let i = 0; i < inputLength + 1; i++) {
|
|
464
|
+
c = i === inputLength ? 38 : input.charCodeAt(i);
|
|
465
|
+
switch (c) {
|
|
466
|
+
case 38: {
|
|
467
|
+
hasBothKeyValuePair = equalityIndex > startingIndex;
|
|
468
|
+
if (!hasBothKeyValuePair) equalityIndex = i;
|
|
469
|
+
key = input.slice(startingIndex + 1, equalityIndex);
|
|
470
|
+
if (hasBothKeyValuePair || key.length > 0) {
|
|
471
|
+
if (keyHasPlus) key = key.replace(plusRegex, " ");
|
|
472
|
+
if (shouldDecodeKey) try {
|
|
473
|
+
key = decodeURIComponent(key);
|
|
474
|
+
} catch {}
|
|
475
|
+
if (hasBothKeyValuePair) {
|
|
476
|
+
value = input.slice(equalityIndex + 1, i);
|
|
477
|
+
if (valueHasPlus) value = value.replace(plusRegex, " ");
|
|
478
|
+
if (shouldDecodeValue) try {
|
|
479
|
+
value = decodeURIComponent(value);
|
|
480
|
+
} catch {}
|
|
481
|
+
}
|
|
482
|
+
const currentValue = params[key];
|
|
483
|
+
if (currentValue === void 0) params[key] = value;
|
|
484
|
+
else if (Array.isArray(currentValue)) currentValue.push(value);
|
|
485
|
+
else params[key] = [currentValue, value];
|
|
486
|
+
}
|
|
487
|
+
value = "";
|
|
488
|
+
startingIndex = i;
|
|
489
|
+
equalityIndex = i;
|
|
490
|
+
shouldDecodeKey = false;
|
|
491
|
+
shouldDecodeValue = false;
|
|
492
|
+
keyHasPlus = false;
|
|
493
|
+
valueHasPlus = false;
|
|
494
|
+
break;
|
|
490
495
|
}
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
*/
|
|
496
|
-
register(plugin) {
|
|
497
|
-
plugin(this);
|
|
498
|
-
return this;
|
|
499
|
-
}
|
|
500
|
-
_findRoute(_event) {}
|
|
501
|
-
_addRoute(_route) {
|
|
502
|
-
this._routes.push(_route);
|
|
503
|
-
}
|
|
504
|
-
handler(event) {
|
|
505
|
-
const route = this._findRoute(event);
|
|
506
|
-
if (route) {
|
|
507
|
-
event.context.params = route.params;
|
|
508
|
-
event.context.matchedRoute = route.data;
|
|
496
|
+
case 61: {
|
|
497
|
+
if (equalityIndex <= startingIndex) equalityIndex = i;
|
|
498
|
+
else shouldDecodeValue = true;
|
|
499
|
+
break;
|
|
509
500
|
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
}
|
|
515
|
-
mount(base, input) {
|
|
516
|
-
if ("handler" in input) {
|
|
517
|
-
if (input._middleware.length > 0) this._middleware.push((event, next) => {
|
|
518
|
-
return event.url.pathname.startsWith(base) ? callMiddleware(event, input._middleware, next) : next();
|
|
519
|
-
});
|
|
520
|
-
for (const r of input._routes) this._addRoute({
|
|
521
|
-
...r,
|
|
522
|
-
route: base + r.route
|
|
523
|
-
});
|
|
524
|
-
} else {
|
|
525
|
-
const fetchHandler = "fetch" in input ? input.fetch : input;
|
|
526
|
-
this.all(`${base}/**`, (event) => {
|
|
527
|
-
const url = new URL(event.url);
|
|
528
|
-
url.pathname = url.pathname.slice(base.length) || "/";
|
|
529
|
-
return fetchHandler(new Request(url, event.req));
|
|
530
|
-
});
|
|
501
|
+
case 43: {
|
|
502
|
+
if (equalityIndex > startingIndex) valueHasPlus = true;
|
|
503
|
+
else keyHasPlus = true;
|
|
504
|
+
break;
|
|
531
505
|
}
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
}
|
|
537
|
-
on(method, route, handler, opts) {
|
|
538
|
-
const _method = (method || "").toUpperCase();
|
|
539
|
-
route = new URL(route, "http://_").pathname;
|
|
540
|
-
this._addRoute({
|
|
541
|
-
method: _method,
|
|
542
|
-
route,
|
|
543
|
-
handler,
|
|
544
|
-
middleware: opts?.middleware,
|
|
545
|
-
meta: {
|
|
546
|
-
...handler.meta,
|
|
547
|
-
...opts?.meta
|
|
548
|
-
}
|
|
549
|
-
});
|
|
550
|
-
return this;
|
|
551
|
-
}
|
|
552
|
-
use(arg1, arg2, arg3) {
|
|
553
|
-
let route;
|
|
554
|
-
let fn;
|
|
555
|
-
let opts;
|
|
556
|
-
if (typeof arg1 === "string") {
|
|
557
|
-
route = arg1;
|
|
558
|
-
fn = arg2;
|
|
559
|
-
opts = arg3;
|
|
560
|
-
} else {
|
|
561
|
-
fn = arg1;
|
|
562
|
-
opts = arg2;
|
|
506
|
+
case 37: {
|
|
507
|
+
if (equalityIndex > startingIndex) shouldDecodeValue = true;
|
|
508
|
+
else shouldDecodeKey = true;
|
|
509
|
+
break;
|
|
563
510
|
}
|
|
564
|
-
this._middleware.push(normalizeMiddleware(fn, route ? {
|
|
565
|
-
...opts,
|
|
566
|
-
route
|
|
567
|
-
} : opts));
|
|
568
|
-
return this;
|
|
569
511
|
}
|
|
570
512
|
}
|
|
571
|
-
|
|
572
|
-
return this.on(method, route, handler, opts);
|
|
573
|
-
};
|
|
574
|
-
return H3Core$1;
|
|
575
|
-
})();
|
|
576
|
-
var H3 = class extends H3Core {
|
|
577
|
-
/**
|
|
578
|
-
* @internal
|
|
579
|
-
*/
|
|
580
|
-
_rou3;
|
|
581
|
-
constructor(config = {}) {
|
|
582
|
-
super(config);
|
|
583
|
-
this._rou3 = createRouter();
|
|
584
|
-
}
|
|
585
|
-
_findRoute(_event) {
|
|
586
|
-
return findRoute(this._rou3, _event.req.method, _event.url.pathname);
|
|
587
|
-
}
|
|
588
|
-
_addRoute(_route) {
|
|
589
|
-
addRoute(this._rou3, _route.method, _route.route, _route);
|
|
590
|
-
super._addRoute(_route);
|
|
591
|
-
}
|
|
592
|
-
};
|
|
593
|
-
function toRequest(_request, _init) {
|
|
594
|
-
if (typeof _request === "string") {
|
|
595
|
-
let url = _request;
|
|
596
|
-
if (url[0] === "/") {
|
|
597
|
-
const headers = _init?.headers ? new Headers(_init.headers) : void 0;
|
|
598
|
-
const host = headers?.get("host") || "localhost";
|
|
599
|
-
const proto = headers?.get("x-forwarded-proto") === "https" ? "https" : "http";
|
|
600
|
-
url = `${proto}://${host}${url}`;
|
|
601
|
-
}
|
|
602
|
-
return new Request(url, _init);
|
|
603
|
-
} else if (_init || _request instanceof URL) return new Request(_request, _init);
|
|
604
|
-
return _request;
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
//#endregion
|
|
608
|
-
//#region src/utils/event.ts
|
|
609
|
-
/**
|
|
610
|
-
* Checks if the input is an H3Event object.
|
|
611
|
-
* @param input - The input to check.
|
|
612
|
-
* @returns True if the input is an H3Event object, false otherwise.
|
|
613
|
-
* @see H3Event
|
|
614
|
-
*/
|
|
615
|
-
function isEvent(input) {
|
|
616
|
-
return input instanceof H3Event || input?.constructor?.__is_event__;
|
|
617
|
-
}
|
|
618
|
-
function mockEvent(_request, options) {
|
|
619
|
-
let request;
|
|
620
|
-
if (typeof _request === "string") {
|
|
621
|
-
let url = _request;
|
|
622
|
-
if (url[0] === "/") url = `http://localhost${url}`;
|
|
623
|
-
request = new Request(url, options);
|
|
624
|
-
} else if (options || _request instanceof URL) request = new Request(_request, options);
|
|
625
|
-
else request = _request;
|
|
626
|
-
return new H3Event(request);
|
|
513
|
+
return params;
|
|
627
514
|
}
|
|
628
515
|
|
|
629
516
|
//#endregion
|
|
@@ -689,226 +576,65 @@ function createValidationError(validateError) {
|
|
|
689
576
|
}
|
|
690
577
|
|
|
691
578
|
//#endregion
|
|
692
|
-
//#region src/
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
579
|
+
//#region src/utils/event.ts
|
|
580
|
+
/**
|
|
581
|
+
* Checks if the input is an H3Event object.
|
|
582
|
+
* @param input - The input to check.
|
|
583
|
+
* @returns True if the input is an H3Event object, false otherwise.
|
|
584
|
+
* @see H3Event
|
|
585
|
+
*/
|
|
586
|
+
function isEvent(input) {
|
|
587
|
+
return input instanceof H3Event || input?.constructor?.__is_event__;
|
|
699
588
|
}
|
|
700
589
|
/**
|
|
701
|
-
*
|
|
590
|
+
* Checks if the input is an object with `{ req: Request }` signature.
|
|
591
|
+
* @param input - The input to check.
|
|
592
|
+
* @returns True if the input is is `{ req: Request }`
|
|
702
593
|
*/
|
|
703
|
-
function
|
|
704
|
-
|
|
705
|
-
return defineHandler({
|
|
706
|
-
...def,
|
|
707
|
-
handler: (event) => {
|
|
708
|
-
event.req = validatedRequest(event.req, def.validate);
|
|
709
|
-
event.url = validatedURL(event.url, def.validate);
|
|
710
|
-
return def.handler(event);
|
|
711
|
-
}
|
|
712
|
-
});
|
|
594
|
+
function isHTTPEvent(input) {
|
|
595
|
+
return input?.req instanceof Request;
|
|
713
596
|
}
|
|
714
|
-
function handlerWithFetch(handler) {
|
|
715
|
-
return Object.assign(handler, { fetch: (_req, _init) => {
|
|
716
|
-
const req = toRequest(_req, _init);
|
|
717
|
-
const event = new H3Event(req);
|
|
718
|
-
try {
|
|
719
|
-
return Promise.resolve(toResponse(handler(event), event));
|
|
720
|
-
} catch (error) {
|
|
721
|
-
return Promise.resolve(toResponse(error, event));
|
|
722
|
-
}
|
|
723
|
-
} });
|
|
724
|
-
}
|
|
725
|
-
function dynamicEventHandler(initial) {
|
|
726
|
-
let current = initial;
|
|
727
|
-
return Object.assign(defineHandler((event) => current?.(event)), { set: (handler) => {
|
|
728
|
-
current = handler;
|
|
729
|
-
} });
|
|
730
|
-
}
|
|
731
|
-
function defineLazyEventHandler(load) {
|
|
732
|
-
let _promise;
|
|
733
|
-
let _resolved;
|
|
734
|
-
const resolveHandler = () => {
|
|
735
|
-
if (_resolved) return Promise.resolve(_resolved);
|
|
736
|
-
if (!_promise) _promise = Promise.resolve(load()).then((r) => {
|
|
737
|
-
const handler = r.default || r;
|
|
738
|
-
if (typeof handler !== "function") throw new TypeError("Invalid lazy handler result. It should be a function:", handler);
|
|
739
|
-
_resolved = { handler: r.default || r };
|
|
740
|
-
return _resolved;
|
|
741
|
-
});
|
|
742
|
-
return _promise;
|
|
743
|
-
};
|
|
744
|
-
return defineHandler((event) => {
|
|
745
|
-
if (_resolved) return _resolved.handler(event);
|
|
746
|
-
return resolveHandler().then((r) => r.handler(event));
|
|
747
|
-
});
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
//#endregion
|
|
751
|
-
//#region src/adapters.ts
|
|
752
597
|
/**
|
|
753
|
-
*
|
|
598
|
+
* Gets the context of the event, if it does not exists, initializes a new context on `req.context`.
|
|
754
599
|
*/
|
|
755
|
-
function
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
600
|
+
function getEventContext(event) {
|
|
601
|
+
if (event.context) return event.context;
|
|
602
|
+
event.req.context ??= {};
|
|
603
|
+
return event.req.context;
|
|
759
604
|
}
|
|
760
|
-
function
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
}
|
|
770
|
-
function defineNodeHandler(handler) {
|
|
771
|
-
return handler;
|
|
772
|
-
}
|
|
773
|
-
function defineNodeMiddleware(handler) {
|
|
774
|
-
return handler;
|
|
775
|
-
}
|
|
776
|
-
/**
|
|
777
|
-
* Convert H3 app instance to a NodeHandler with (IncomingMessage, ServerResponse) => void signature.
|
|
778
|
-
*/
|
|
779
|
-
function toNodeHandler$1(app) {
|
|
780
|
-
return toNodeHandler(app.fetch);
|
|
781
|
-
}
|
|
782
|
-
function callNodeHandler(handler, req, res) {
|
|
783
|
-
const isMiddleware = handler.length > 2;
|
|
784
|
-
return new Promise((resolve, reject) => {
|
|
785
|
-
res.once("close", () => resolve(kHandled));
|
|
786
|
-
res.once("finish", () => resolve(kHandled));
|
|
787
|
-
res.once("pipe", (stream) => resolve(stream));
|
|
788
|
-
res.once("error", (error) => reject(error));
|
|
789
|
-
try {
|
|
790
|
-
if (isMiddleware) Promise.resolve(handler(req, res, (error) => error ? reject(new HTTPError({
|
|
791
|
-
cause: error,
|
|
792
|
-
unhandled: true
|
|
793
|
-
})) : resolve(void 0))).catch((error) => reject(new HTTPError({
|
|
794
|
-
cause: error,
|
|
795
|
-
unhandled: true
|
|
796
|
-
})));
|
|
797
|
-
else return Promise.resolve(handler(req, res)).then(() => resolve(kHandled)).catch((error) => reject(new HTTPError({
|
|
798
|
-
cause: error,
|
|
799
|
-
unhandled: true
|
|
800
|
-
})));
|
|
801
|
-
} catch (error) {
|
|
802
|
-
reject(new HTTPError({
|
|
803
|
-
cause: error,
|
|
804
|
-
unhandled: true
|
|
805
|
-
}));
|
|
806
|
-
}
|
|
807
|
-
});
|
|
605
|
+
function mockEvent(_request, options) {
|
|
606
|
+
let request;
|
|
607
|
+
if (typeof _request === "string") {
|
|
608
|
+
let url = _request;
|
|
609
|
+
if (url[0] === "/") url = `http://localhost${url}`;
|
|
610
|
+
request = new Request(url, options);
|
|
611
|
+
} else if (options || _request instanceof URL) request = new Request(_request, options);
|
|
612
|
+
else request = _request;
|
|
613
|
+
return new H3Event(request);
|
|
808
614
|
}
|
|
809
615
|
|
|
810
616
|
//#endregion
|
|
811
|
-
//#region src/utils/
|
|
617
|
+
//#region src/utils/request.ts
|
|
812
618
|
/**
|
|
813
|
-
*
|
|
619
|
+
* Convert input into a web [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request).
|
|
814
620
|
*
|
|
815
|
-
*
|
|
816
|
-
* ```js
|
|
817
|
-
* import { z } from "zod";
|
|
621
|
+
* If input is a relative URL, it will be normalized into a full path based on headers.
|
|
818
622
|
*
|
|
819
|
-
*
|
|
820
|
-
* method: 'POST',
|
|
821
|
-
* validate: {
|
|
822
|
-
* query: z.object({ id: z.string().uuid() }),
|
|
823
|
-
* body: z.object({ name: z.string() }),
|
|
824
|
-
* },
|
|
825
|
-
* handler: (event) => {
|
|
826
|
-
* return { success: true };
|
|
827
|
-
* }
|
|
828
|
-
* });
|
|
829
|
-
*
|
|
830
|
-
* app.register(userRoute);
|
|
831
|
-
* ```
|
|
623
|
+
* If input is already a Request and no options are provided, it will be returned as-is.
|
|
832
624
|
*/
|
|
833
|
-
function
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
//#region src/utils/internal/query.ts
|
|
842
|
-
const plusRegex = /\+/g;
|
|
843
|
-
function parseQuery(input) {
|
|
844
|
-
const params = new EmptyObject();
|
|
845
|
-
if (!input || input === "?") return params;
|
|
846
|
-
const inputLength = input.length;
|
|
847
|
-
let key = "";
|
|
848
|
-
let value = "";
|
|
849
|
-
let startingIndex = -1;
|
|
850
|
-
let equalityIndex = -1;
|
|
851
|
-
let shouldDecodeKey = false;
|
|
852
|
-
let shouldDecodeValue = false;
|
|
853
|
-
let keyHasPlus = false;
|
|
854
|
-
let valueHasPlus = false;
|
|
855
|
-
let hasBothKeyValuePair = false;
|
|
856
|
-
let c = 0;
|
|
857
|
-
for (let i = 0; i < inputLength + 1; i++) {
|
|
858
|
-
c = i === inputLength ? 38 : input.charCodeAt(i);
|
|
859
|
-
switch (c) {
|
|
860
|
-
case 38: {
|
|
861
|
-
hasBothKeyValuePair = equalityIndex > startingIndex;
|
|
862
|
-
if (!hasBothKeyValuePair) equalityIndex = i;
|
|
863
|
-
key = input.slice(startingIndex + 1, equalityIndex);
|
|
864
|
-
if (hasBothKeyValuePair || key.length > 0) {
|
|
865
|
-
if (keyHasPlus) key = key.replace(plusRegex, " ");
|
|
866
|
-
if (shouldDecodeKey) try {
|
|
867
|
-
key = decodeURIComponent(key);
|
|
868
|
-
} catch {}
|
|
869
|
-
if (hasBothKeyValuePair) {
|
|
870
|
-
value = input.slice(equalityIndex + 1, i);
|
|
871
|
-
if (valueHasPlus) value = value.replace(plusRegex, " ");
|
|
872
|
-
if (shouldDecodeValue) try {
|
|
873
|
-
value = decodeURIComponent(value);
|
|
874
|
-
} catch {}
|
|
875
|
-
}
|
|
876
|
-
const currentValue = params[key];
|
|
877
|
-
if (currentValue === void 0) params[key] = value;
|
|
878
|
-
else if (Array.isArray(currentValue)) currentValue.push(value);
|
|
879
|
-
else params[key] = [currentValue, value];
|
|
880
|
-
}
|
|
881
|
-
value = "";
|
|
882
|
-
startingIndex = i;
|
|
883
|
-
equalityIndex = i;
|
|
884
|
-
shouldDecodeKey = false;
|
|
885
|
-
shouldDecodeValue = false;
|
|
886
|
-
keyHasPlus = false;
|
|
887
|
-
valueHasPlus = false;
|
|
888
|
-
break;
|
|
889
|
-
}
|
|
890
|
-
case 61: {
|
|
891
|
-
if (equalityIndex <= startingIndex) equalityIndex = i;
|
|
892
|
-
else shouldDecodeValue = true;
|
|
893
|
-
break;
|
|
894
|
-
}
|
|
895
|
-
case 43: {
|
|
896
|
-
if (equalityIndex > startingIndex) valueHasPlus = true;
|
|
897
|
-
else keyHasPlus = true;
|
|
898
|
-
break;
|
|
899
|
-
}
|
|
900
|
-
case 37: {
|
|
901
|
-
if (equalityIndex > startingIndex) shouldDecodeValue = true;
|
|
902
|
-
else shouldDecodeKey = true;
|
|
903
|
-
break;
|
|
904
|
-
}
|
|
625
|
+
function toRequest(input, options) {
|
|
626
|
+
if (typeof input === "string") {
|
|
627
|
+
let url = input;
|
|
628
|
+
if (url[0] === "/") {
|
|
629
|
+
const headers = options?.headers ? new Headers(options.headers) : void 0;
|
|
630
|
+
const host = headers?.get("host") || "localhost";
|
|
631
|
+
const proto = headers?.get("x-forwarded-proto") === "https" ? "https" : "http";
|
|
632
|
+
url = `${proto}://${host}${url}`;
|
|
905
633
|
}
|
|
906
|
-
|
|
907
|
-
return
|
|
634
|
+
return new Request(url, options);
|
|
635
|
+
} else if (options || input instanceof URL) return new Request(input, options);
|
|
636
|
+
return input;
|
|
908
637
|
}
|
|
909
|
-
|
|
910
|
-
//#endregion
|
|
911
|
-
//#region src/utils/request.ts
|
|
912
638
|
/**
|
|
913
639
|
* Get parsed query string object from the request URL.
|
|
914
640
|
*
|
|
@@ -918,7 +644,8 @@ function parseQuery(input) {
|
|
|
918
644
|
* });
|
|
919
645
|
*/
|
|
920
646
|
function getQuery(event) {
|
|
921
|
-
|
|
647
|
+
const url = event.url || new URL(event.req.url);
|
|
648
|
+
return parseQuery(url.search.slice(1));
|
|
922
649
|
}
|
|
923
650
|
/**
|
|
924
651
|
* Get the query param from the request URL validated with validate function.
|
|
@@ -958,7 +685,8 @@ function getValidatedQuery(event, validate) {
|
|
|
958
685
|
* });
|
|
959
686
|
*/
|
|
960
687
|
function getRouterParams(event, opts = {}) {
|
|
961
|
-
|
|
688
|
+
const context = getEventContext(event);
|
|
689
|
+
let params = context.params || {};
|
|
962
690
|
if (opts.decode) {
|
|
963
691
|
params = { ...params };
|
|
964
692
|
for (const key in params) params[key] = decodeURIComponent(params[key]);
|
|
@@ -1009,126 +737,423 @@ function getRouterParam(event, name, opts = {}) {
|
|
|
1009
737
|
return params[name];
|
|
1010
738
|
}
|
|
1011
739
|
/**
|
|
1012
|
-
*
|
|
1013
|
-
* Checks if the incoming request method is of the expected type.
|
|
1014
|
-
*
|
|
1015
|
-
* If `allowHead` is `true`, it will allow `HEAD` requests to pass if the expected method is `GET`.
|
|
1016
|
-
*
|
|
1017
|
-
* @example
|
|
1018
|
-
* app.get("/", (event) => {
|
|
1019
|
-
* if (isMethod(event, "GET")) {
|
|
1020
|
-
* // Handle GET request
|
|
1021
|
-
* } else if (isMethod(event, ["POST", "PUT"])) {
|
|
1022
|
-
* // Handle POST or PUT request
|
|
1023
|
-
* }
|
|
1024
|
-
* });
|
|
740
|
+
*
|
|
741
|
+
* Checks if the incoming request method is of the expected type.
|
|
742
|
+
*
|
|
743
|
+
* If `allowHead` is `true`, it will allow `HEAD` requests to pass if the expected method is `GET`.
|
|
744
|
+
*
|
|
745
|
+
* @example
|
|
746
|
+
* app.get("/", (event) => {
|
|
747
|
+
* if (isMethod(event, "GET")) {
|
|
748
|
+
* // Handle GET request
|
|
749
|
+
* } else if (isMethod(event, ["POST", "PUT"])) {
|
|
750
|
+
* // Handle POST or PUT request
|
|
751
|
+
* }
|
|
752
|
+
* });
|
|
753
|
+
*/
|
|
754
|
+
function isMethod(event, expected, allowHead) {
|
|
755
|
+
if (allowHead && event.req.method === "HEAD") return true;
|
|
756
|
+
if (typeof expected === "string") {
|
|
757
|
+
if (event.req.method === expected) return true;
|
|
758
|
+
} else if (expected.includes(event.req.method)) return true;
|
|
759
|
+
return false;
|
|
760
|
+
}
|
|
761
|
+
/**
|
|
762
|
+
* Asserts that the incoming request method is of the expected type using `isMethod`.
|
|
763
|
+
*
|
|
764
|
+
* If the method is not allowed, it will throw a 405 error with the message "HTTP method is not allowed".
|
|
765
|
+
*
|
|
766
|
+
* If `allowHead` is `true`, it will allow `HEAD` requests to pass if the expected method is `GET`.
|
|
767
|
+
*
|
|
768
|
+
* @example
|
|
769
|
+
* app.get("/", (event) => {
|
|
770
|
+
* assertMethod(event, "GET");
|
|
771
|
+
* // Handle GET request, otherwise throw 405 error
|
|
772
|
+
* });
|
|
773
|
+
*/
|
|
774
|
+
function assertMethod(event, expected, allowHead) {
|
|
775
|
+
if (!isMethod(event, expected, allowHead)) throw new HTTPError({ status: 405 });
|
|
776
|
+
}
|
|
777
|
+
/**
|
|
778
|
+
* Get the request hostname.
|
|
779
|
+
*
|
|
780
|
+
* If `xForwardedHost` is `true`, it will use the `x-forwarded-host` header if it exists.
|
|
781
|
+
*
|
|
782
|
+
* If no host header is found, it will default to "localhost".
|
|
783
|
+
*
|
|
784
|
+
* @example
|
|
785
|
+
* app.get("/", (event) => {
|
|
786
|
+
* const host = getRequestHost(event); // "example.com"
|
|
787
|
+
* });
|
|
788
|
+
*/
|
|
789
|
+
function getRequestHost(event, opts = {}) {
|
|
790
|
+
if (opts.xForwardedHost) {
|
|
791
|
+
const _header = event.req.headers.get("x-forwarded-host");
|
|
792
|
+
const xForwardedHost = (_header || "").split(",").shift()?.trim();
|
|
793
|
+
if (xForwardedHost) return xForwardedHost;
|
|
794
|
+
}
|
|
795
|
+
return event.req.headers.get("host") || "";
|
|
796
|
+
}
|
|
797
|
+
/**
|
|
798
|
+
* Get the request protocol.
|
|
799
|
+
*
|
|
800
|
+
* If `x-forwarded-proto` header is set to "https", it will return "https". You can disable this behavior by setting `xForwardedProto` to `false`.
|
|
801
|
+
*
|
|
802
|
+
* If protocol cannot be determined, it will default to "http".
|
|
803
|
+
*
|
|
804
|
+
* @example
|
|
805
|
+
* app.get("/", (event) => {
|
|
806
|
+
* const protocol = getRequestProtocol(event); // "https"
|
|
807
|
+
* });
|
|
808
|
+
*/
|
|
809
|
+
function getRequestProtocol(event, opts = {}) {
|
|
810
|
+
if (opts.xForwardedProto !== false) {
|
|
811
|
+
const forwardedProto = event.req.headers.get("x-forwarded-proto");
|
|
812
|
+
if (forwardedProto === "https") return "https";
|
|
813
|
+
if (forwardedProto === "http") return "http";
|
|
814
|
+
}
|
|
815
|
+
const url = event.url || new URL(event.req.url);
|
|
816
|
+
return url.protocol.slice(0, -1);
|
|
817
|
+
}
|
|
818
|
+
/**
|
|
819
|
+
* Generated the full incoming request URL.
|
|
820
|
+
*
|
|
821
|
+
* If `xForwardedHost` is `true`, it will use the `x-forwarded-host` header if it exists.
|
|
822
|
+
*
|
|
823
|
+
* If `xForwardedProto` is `false`, it will not use the `x-forwarded-proto` header.
|
|
824
|
+
*
|
|
825
|
+
* @example
|
|
826
|
+
* app.get("/", (event) => {
|
|
827
|
+
* const url = getRequestURL(event); // "https://example.com/path"
|
|
828
|
+
* });
|
|
829
|
+
*/
|
|
830
|
+
function getRequestURL(event, opts = {}) {
|
|
831
|
+
const url = new URL(event.url || event.req.url);
|
|
832
|
+
url.protocol = getRequestProtocol(event, opts);
|
|
833
|
+
if (opts.xForwardedHost) {
|
|
834
|
+
const host = getRequestHost(event, opts);
|
|
835
|
+
if (host) {
|
|
836
|
+
url.host = host;
|
|
837
|
+
if (!host.includes(":")) url.port = "";
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
return url;
|
|
841
|
+
}
|
|
842
|
+
/**
|
|
843
|
+
* Try to get the client IP address from the incoming request.
|
|
844
|
+
*
|
|
845
|
+
* If `xForwardedFor` is `true`, it will use the `x-forwarded-for` header if it exists.
|
|
846
|
+
*
|
|
847
|
+
* If IP cannot be determined, it will default to `undefined`.
|
|
848
|
+
*
|
|
849
|
+
* @example
|
|
850
|
+
* app.get("/", (event) => {
|
|
851
|
+
* const ip = getRequestIP(event); // "192.0.2.0"
|
|
852
|
+
* });
|
|
853
|
+
*/
|
|
854
|
+
function getRequestIP(event, opts = {}) {
|
|
855
|
+
if (opts.xForwardedFor) {
|
|
856
|
+
const _header = event.req.headers.get("x-forwarded-for");
|
|
857
|
+
const xForwardedFor = (_header || "")?.split(",").shift()?.trim();
|
|
858
|
+
if (xForwardedFor) return xForwardedFor;
|
|
859
|
+
}
|
|
860
|
+
return event.req.context?.clientAddress || event.req.ip || void 0;
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
//#endregion
|
|
864
|
+
//#region src/h3.ts
|
|
865
|
+
const H3Core = /* @__PURE__ */ (() => {
|
|
866
|
+
const HTTPMethods = [
|
|
867
|
+
"GET",
|
|
868
|
+
"POST",
|
|
869
|
+
"PUT",
|
|
870
|
+
"DELETE",
|
|
871
|
+
"PATCH",
|
|
872
|
+
"HEAD",
|
|
873
|
+
"OPTIONS",
|
|
874
|
+
"CONNECT",
|
|
875
|
+
"TRACE"
|
|
876
|
+
];
|
|
877
|
+
class H3Core$1 {
|
|
878
|
+
_middleware;
|
|
879
|
+
_routes = [];
|
|
880
|
+
config;
|
|
881
|
+
constructor(config = {}) {
|
|
882
|
+
this._middleware = [];
|
|
883
|
+
this.config = config;
|
|
884
|
+
this.fetch = this.fetch.bind(this);
|
|
885
|
+
this.request = this.request.bind(this);
|
|
886
|
+
this.handler = this.handler.bind(this);
|
|
887
|
+
config.plugins?.forEach((plugin) => plugin(this));
|
|
888
|
+
}
|
|
889
|
+
fetch(request) {
|
|
890
|
+
return this._request(request);
|
|
891
|
+
}
|
|
892
|
+
request(_req, _init, context) {
|
|
893
|
+
return this._request(toRequest(_req, _init), context);
|
|
894
|
+
}
|
|
895
|
+
_request(request, context) {
|
|
896
|
+
const event = new H3Event(request, context, this);
|
|
897
|
+
let handlerRes;
|
|
898
|
+
try {
|
|
899
|
+
if (this.config.onRequest) {
|
|
900
|
+
const hookRes = this.config.onRequest(event);
|
|
901
|
+
handlerRes = typeof hookRes?.then === "function" ? hookRes.then(() => this.handler(event)) : this.handler(event);
|
|
902
|
+
} else handlerRes = this.handler(event);
|
|
903
|
+
} catch (error) {
|
|
904
|
+
handlerRes = Promise.reject(error);
|
|
905
|
+
}
|
|
906
|
+
return toResponse(handlerRes, event, this.config);
|
|
907
|
+
}
|
|
908
|
+
/**
|
|
909
|
+
* Immediately register an H3 plugin.
|
|
910
|
+
*/
|
|
911
|
+
register(plugin) {
|
|
912
|
+
plugin(this);
|
|
913
|
+
return this;
|
|
914
|
+
}
|
|
915
|
+
_findRoute(_event) {}
|
|
916
|
+
_addRoute(_route) {
|
|
917
|
+
this._routes.push(_route);
|
|
918
|
+
}
|
|
919
|
+
handler(event) {
|
|
920
|
+
const route = this._findRoute(event);
|
|
921
|
+
if (route) {
|
|
922
|
+
event.context.params = route.params;
|
|
923
|
+
event.context.matchedRoute = route.data;
|
|
924
|
+
}
|
|
925
|
+
const middleware = route?.data.middleware ? [...this._middleware, ...route.data.middleware] : this._middleware;
|
|
926
|
+
return callMiddleware(event, middleware, () => {
|
|
927
|
+
return route ? route.data.handler(event) : kNotFound;
|
|
928
|
+
});
|
|
929
|
+
}
|
|
930
|
+
mount(base, input) {
|
|
931
|
+
if ("handler" in input) {
|
|
932
|
+
if (input._middleware.length > 0) this._middleware.push((event, next) => {
|
|
933
|
+
return event.url.pathname.startsWith(base) ? callMiddleware(event, input._middleware, next) : next();
|
|
934
|
+
});
|
|
935
|
+
for (const r of input._routes) this._addRoute({
|
|
936
|
+
...r,
|
|
937
|
+
route: base + r.route
|
|
938
|
+
});
|
|
939
|
+
} else {
|
|
940
|
+
const fetchHandler = "fetch" in input ? input.fetch : input;
|
|
941
|
+
this.all(`${base}/**`, (event) => {
|
|
942
|
+
const url = new URL(event.url);
|
|
943
|
+
url.pathname = url.pathname.slice(base.length) || "/";
|
|
944
|
+
return fetchHandler(new Request(url, event.req));
|
|
945
|
+
});
|
|
946
|
+
}
|
|
947
|
+
return this;
|
|
948
|
+
}
|
|
949
|
+
all(route, handler, opts) {
|
|
950
|
+
return this.on("", route, handler, opts);
|
|
951
|
+
}
|
|
952
|
+
on(method, route, handler, opts) {
|
|
953
|
+
const _method = (method || "").toUpperCase();
|
|
954
|
+
route = new URL(route, "http://_").pathname;
|
|
955
|
+
this._addRoute({
|
|
956
|
+
method: _method,
|
|
957
|
+
route,
|
|
958
|
+
handler,
|
|
959
|
+
middleware: opts?.middleware,
|
|
960
|
+
meta: {
|
|
961
|
+
...handler.meta,
|
|
962
|
+
...opts?.meta
|
|
963
|
+
}
|
|
964
|
+
});
|
|
965
|
+
return this;
|
|
966
|
+
}
|
|
967
|
+
use(arg1, arg2, arg3) {
|
|
968
|
+
let route;
|
|
969
|
+
let fn;
|
|
970
|
+
let opts;
|
|
971
|
+
if (typeof arg1 === "string") {
|
|
972
|
+
route = arg1;
|
|
973
|
+
fn = arg2;
|
|
974
|
+
opts = arg3;
|
|
975
|
+
} else {
|
|
976
|
+
fn = arg1;
|
|
977
|
+
opts = arg2;
|
|
978
|
+
}
|
|
979
|
+
this._middleware.push(normalizeMiddleware(fn, route ? {
|
|
980
|
+
...opts,
|
|
981
|
+
route
|
|
982
|
+
} : opts));
|
|
983
|
+
return this;
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
for (const method of HTTPMethods) H3Core$1.prototype[method.toLowerCase()] = function(route, handler, opts) {
|
|
987
|
+
return this.on(method, route, handler, opts);
|
|
988
|
+
};
|
|
989
|
+
return H3Core$1;
|
|
990
|
+
})();
|
|
991
|
+
var H3 = class extends H3Core {
|
|
992
|
+
/**
|
|
993
|
+
* @internal
|
|
994
|
+
*/
|
|
995
|
+
_rou3;
|
|
996
|
+
constructor(config = {}) {
|
|
997
|
+
super(config);
|
|
998
|
+
this._rou3 = createRouter();
|
|
999
|
+
}
|
|
1000
|
+
_findRoute(_event) {
|
|
1001
|
+
return findRoute(this._rou3, _event.req.method, _event.url.pathname);
|
|
1002
|
+
}
|
|
1003
|
+
_addRoute(_route) {
|
|
1004
|
+
addRoute(this._rou3, _route.method, _route.route, _route);
|
|
1005
|
+
super._addRoute(_route);
|
|
1006
|
+
}
|
|
1007
|
+
};
|
|
1008
|
+
|
|
1009
|
+
//#endregion
|
|
1010
|
+
//#region src/handler.ts
|
|
1011
|
+
function defineHandler(arg1) {
|
|
1012
|
+
if (typeof arg1 === "function") return handlerWithFetch(arg1);
|
|
1013
|
+
const { middleware, handler, meta } = arg1;
|
|
1014
|
+
const _handler = handlerWithFetch(middleware?.length ? (event) => callMiddleware(event, middleware, handler) : handler);
|
|
1015
|
+
_handler.meta = meta;
|
|
1016
|
+
return _handler;
|
|
1017
|
+
}
|
|
1018
|
+
/**
|
|
1019
|
+
* @experimental defineValidatedHandler is an experimental feature and API may change.
|
|
1025
1020
|
*/
|
|
1026
|
-
function
|
|
1027
|
-
if (
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1021
|
+
function defineValidatedHandler(def) {
|
|
1022
|
+
if (!def.validate) return defineHandler(def);
|
|
1023
|
+
return defineHandler({
|
|
1024
|
+
...def,
|
|
1025
|
+
handler: (event) => {
|
|
1026
|
+
event.req = validatedRequest(event.req, def.validate);
|
|
1027
|
+
event.url = validatedURL(event.url, def.validate);
|
|
1028
|
+
return def.handler(event);
|
|
1029
|
+
}
|
|
1030
|
+
});
|
|
1032
1031
|
}
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
* });
|
|
1045
|
-
*/
|
|
1046
|
-
function assertMethod(event, expected, allowHead) {
|
|
1047
|
-
if (!isMethod(event, expected, allowHead)) throw new HTTPError({ status: 405 });
|
|
1032
|
+
function handlerWithFetch(handler) {
|
|
1033
|
+
return Object.assign(handler, { fetch: (req) => {
|
|
1034
|
+
if (typeof req === "string") req = new URL(req, "http://_");
|
|
1035
|
+
if (req instanceof URL) req = new Request(req);
|
|
1036
|
+
const event = new H3Event(req);
|
|
1037
|
+
try {
|
|
1038
|
+
return Promise.resolve(toResponse(handler(event), event));
|
|
1039
|
+
} catch (error) {
|
|
1040
|
+
return Promise.resolve(toResponse(error, event));
|
|
1041
|
+
}
|
|
1042
|
+
} });
|
|
1048
1043
|
}
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1044
|
+
function dynamicEventHandler(initial) {
|
|
1045
|
+
let current = initial;
|
|
1046
|
+
return Object.assign(defineHandler((event) => current?.(event)), { set: (handler) => {
|
|
1047
|
+
current = handler;
|
|
1048
|
+
} });
|
|
1049
|
+
}
|
|
1050
|
+
function defineLazyEventHandler(load) {
|
|
1051
|
+
let _promise;
|
|
1052
|
+
let _resolved;
|
|
1053
|
+
const resolveHandler = () => {
|
|
1054
|
+
if (_resolved) return Promise.resolve(_resolved);
|
|
1055
|
+
if (!_promise) _promise = Promise.resolve(load()).then((r) => {
|
|
1056
|
+
const handler = r.default || r;
|
|
1057
|
+
if (typeof handler !== "function") throw new TypeError("Invalid lazy handler result. It should be a function:", handler);
|
|
1058
|
+
_resolved = { handler: r.default || r };
|
|
1059
|
+
return _resolved;
|
|
1060
|
+
});
|
|
1061
|
+
return _promise;
|
|
1062
|
+
};
|
|
1063
|
+
return defineHandler((event) => {
|
|
1064
|
+
if (_resolved) return _resolved.handler(event);
|
|
1065
|
+
return resolveHandler().then((r) => r.handler(event));
|
|
1066
|
+
});
|
|
1068
1067
|
}
|
|
1068
|
+
|
|
1069
|
+
//#endregion
|
|
1070
|
+
//#region src/adapters.ts
|
|
1069
1071
|
/**
|
|
1070
|
-
*
|
|
1071
|
-
*
|
|
1072
|
-
* If `x-forwarded-proto` header is set to "https", it will return "https". You can disable this behavior by setting `xForwardedProto` to `false`.
|
|
1073
|
-
*
|
|
1074
|
-
* If protocol cannot be determined, it will default to "http".
|
|
1075
|
-
*
|
|
1076
|
-
* @example
|
|
1077
|
-
* app.get("/", (event) => {
|
|
1078
|
-
* const protocol = getRequestProtocol(event); // "https"
|
|
1079
|
-
* });
|
|
1072
|
+
* @deprecated Since h3 v2 you can directly use `app.fetch(request, init?, context?)`
|
|
1080
1073
|
*/
|
|
1081
|
-
function
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
return event.
|
|
1074
|
+
function toWebHandler(app) {
|
|
1075
|
+
return (request, context) => {
|
|
1076
|
+
return Promise.resolve(app.request(request, void 0, context || request.context));
|
|
1077
|
+
};
|
|
1078
|
+
}
|
|
1079
|
+
function fromWebHandler(handler) {
|
|
1080
|
+
return (event) => handler(event.req, event.context);
|
|
1081
|
+
}
|
|
1082
|
+
function fromNodeHandler(handler) {
|
|
1083
|
+
if (typeof handler !== "function") throw new TypeError(`Invalid handler. It should be a function: ${handler}`);
|
|
1084
|
+
return (event) => {
|
|
1085
|
+
if (!event.runtime?.node?.res) throw new Error("[h3] Executing Node.js middleware is not supported in this server!");
|
|
1086
|
+
return callNodeHandler(handler, event.runtime?.node.req, event.runtime?.node.res);
|
|
1087
|
+
};
|
|
1088
|
+
}
|
|
1089
|
+
function defineNodeHandler(handler) {
|
|
1090
|
+
return handler;
|
|
1091
|
+
}
|
|
1092
|
+
function defineNodeMiddleware(handler) {
|
|
1093
|
+
return handler;
|
|
1088
1094
|
}
|
|
1089
1095
|
/**
|
|
1090
|
-
*
|
|
1091
|
-
*
|
|
1092
|
-
* If `xForwardedHost` is `true`, it will use the `x-forwarded-host` header if it exists.
|
|
1093
|
-
*
|
|
1094
|
-
* If `xForwardedProto` is `false`, it will not use the `x-forwarded-proto` header.
|
|
1095
|
-
*
|
|
1096
|
-
* @example
|
|
1097
|
-
* app.get("/", (event) => {
|
|
1098
|
-
* const url = getRequestURL(event); // "https://example.com/path"
|
|
1099
|
-
* });
|
|
1096
|
+
* Convert H3 app instance to a NodeHandler with (IncomingMessage, ServerResponse) => void signature.
|
|
1100
1097
|
*/
|
|
1101
|
-
function
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1098
|
+
function toNodeHandler$1(app) {
|
|
1099
|
+
return toNodeHandler(app.fetch);
|
|
1100
|
+
}
|
|
1101
|
+
function callNodeHandler(handler, req, res) {
|
|
1102
|
+
const isMiddleware = handler.length > 2;
|
|
1103
|
+
return new Promise((resolve, reject) => {
|
|
1104
|
+
res.once("close", () => resolve(kHandled));
|
|
1105
|
+
res.once("finish", () => resolve(kHandled));
|
|
1106
|
+
res.once("pipe", (stream) => resolve(stream));
|
|
1107
|
+
res.once("error", (error) => reject(error));
|
|
1108
|
+
try {
|
|
1109
|
+
if (isMiddleware) Promise.resolve(handler(req, res, (error) => error ? reject(new HTTPError({
|
|
1110
|
+
cause: error,
|
|
1111
|
+
unhandled: true
|
|
1112
|
+
})) : resolve(void 0))).catch((error) => reject(new HTTPError({
|
|
1113
|
+
cause: error,
|
|
1114
|
+
unhandled: true
|
|
1115
|
+
})));
|
|
1116
|
+
else return Promise.resolve(handler(req, res)).then(() => resolve(kHandled)).catch((error) => reject(new HTTPError({
|
|
1117
|
+
cause: error,
|
|
1118
|
+
unhandled: true
|
|
1119
|
+
})));
|
|
1120
|
+
} catch (error) {
|
|
1121
|
+
reject(new HTTPError({
|
|
1122
|
+
cause: error,
|
|
1123
|
+
unhandled: true
|
|
1124
|
+
}));
|
|
1109
1125
|
}
|
|
1110
|
-
}
|
|
1111
|
-
return url;
|
|
1126
|
+
});
|
|
1112
1127
|
}
|
|
1128
|
+
|
|
1129
|
+
//#endregion
|
|
1130
|
+
//#region src/utils/route.ts
|
|
1113
1131
|
/**
|
|
1114
|
-
*
|
|
1115
|
-
*
|
|
1116
|
-
* If `xForwardedFor` is `true`, it will use the `x-forwarded-for` header if it exists.
|
|
1117
|
-
*
|
|
1118
|
-
* If IP cannot be determined, it will default to `undefined`.
|
|
1132
|
+
* Define a route as a plugin that can be registered with app.register()
|
|
1119
1133
|
*
|
|
1120
1134
|
* @example
|
|
1121
|
-
*
|
|
1122
|
-
*
|
|
1135
|
+
* ```js
|
|
1136
|
+
* import { z } from "zod";
|
|
1137
|
+
*
|
|
1138
|
+
* const userRoute = defineRoute({
|
|
1139
|
+
* method: 'POST',
|
|
1140
|
+
* validate: {
|
|
1141
|
+
* query: z.object({ id: z.string().uuid() }),
|
|
1142
|
+
* body: z.object({ name: z.string() }),
|
|
1143
|
+
* },
|
|
1144
|
+
* handler: (event) => {
|
|
1145
|
+
* return { success: true };
|
|
1146
|
+
* }
|
|
1123
1147
|
* });
|
|
1148
|
+
*
|
|
1149
|
+
* app.register(userRoute);
|
|
1150
|
+
* ```
|
|
1124
1151
|
*/
|
|
1125
|
-
function
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
}
|
|
1131
|
-
return event.context.clientAddress || event.req.ip || void 0;
|
|
1152
|
+
function defineRoute(def) {
|
|
1153
|
+
const handler = defineValidatedHandler(def);
|
|
1154
|
+
return (h3) => {
|
|
1155
|
+
h3.on(def.method, def.route, handler);
|
|
1156
|
+
};
|
|
1132
1157
|
}
|
|
1133
1158
|
|
|
1134
1159
|
//#endregion
|
|
@@ -1282,7 +1307,7 @@ function noContent(event, code) {
|
|
|
1282
1307
|
if (!code && currentStatus && currentStatus !== 200) code = event.res.status;
|
|
1283
1308
|
event.res.status = sanitizeStatusCode(code, 204);
|
|
1284
1309
|
if (event.res.status === 204) event.res.headers.delete("content-length");
|
|
1285
|
-
return
|
|
1310
|
+
return new FastResponse(null, event.res);
|
|
1286
1311
|
}
|
|
1287
1312
|
/**
|
|
1288
1313
|
* Send a redirect response to the client.
|
|
@@ -1494,7 +1519,7 @@ async function proxy(event, target, opts = {}) {
|
|
|
1494
1519
|
};
|
|
1495
1520
|
let response;
|
|
1496
1521
|
try {
|
|
1497
|
-
response = target[0] === "/" ? await event.app.
|
|
1522
|
+
response = target[0] === "/" ? await event.app.fetch(createSubRequest(event, target, fetchOptions)) : await fetch(target, fetchOptions);
|
|
1498
1523
|
} catch (error) {
|
|
1499
1524
|
throw new HTTPError({
|
|
1500
1525
|
status: 502,
|
|
@@ -1528,7 +1553,17 @@ async function proxy(event, target, opts = {}) {
|
|
|
1528
1553
|
*/
|
|
1529
1554
|
function getProxyRequestHeaders(event, opts) {
|
|
1530
1555
|
const headers = new EmptyObject();
|
|
1531
|
-
for (const [name, value] of event.req.headers.entries())
|
|
1556
|
+
for (const [name, value] of event.req.headers.entries()) {
|
|
1557
|
+
if (opts?.filterHeaders?.includes(name)) continue;
|
|
1558
|
+
if (opts?.forwardHeaders?.includes(name)) {
|
|
1559
|
+
headers[name] = value;
|
|
1560
|
+
continue;
|
|
1561
|
+
}
|
|
1562
|
+
if (!ignoredHeaders.has(name) || name === "host" && opts?.host) {
|
|
1563
|
+
headers[name] = value;
|
|
1564
|
+
continue;
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1532
1567
|
return headers;
|
|
1533
1568
|
}
|
|
1534
1569
|
/**
|
|
@@ -1536,7 +1571,7 @@ function getProxyRequestHeaders(event, opts) {
|
|
|
1536
1571
|
*/
|
|
1537
1572
|
async function fetchWithEvent(event, url, init) {
|
|
1538
1573
|
if (url[0] !== "/") return fetch(url, init);
|
|
1539
|
-
return event.app.
|
|
1574
|
+
return event.app.fetch(createSubRequest(event, url, {
|
|
1540
1575
|
...init,
|
|
1541
1576
|
headers: mergeHeaders(getProxyRequestHeaders(event, { host: true }), init?.headers)
|
|
1542
1577
|
}));
|
|
@@ -1614,7 +1649,7 @@ async function readBody(event) {
|
|
|
1614
1649
|
* const body = await readValidatedBody(event, objectSchema);
|
|
1615
1650
|
* });
|
|
1616
1651
|
*
|
|
1617
|
-
* @param event The
|
|
1652
|
+
* @param event The HTTPEvent passed by the handler.
|
|
1618
1653
|
* @param validate The function to use for body validation. It will be called passing the read request body. If the result is not false, the parsed body will be returned.
|
|
1619
1654
|
* @throws If the validation function returns `false` or throws, a validation error will be thrown.
|
|
1620
1655
|
* @return {*} The `Object`, `Array`, `String`, `Number`, `Boolean`, or `null` value corresponding to the request JSON body.
|
|
@@ -1627,9 +1662,11 @@ async function readValidatedBody(event, validate) {
|
|
|
1627
1662
|
|
|
1628
1663
|
//#endregion
|
|
1629
1664
|
//#region src/utils/cookie.ts
|
|
1665
|
+
const CHUNKED_COOKIE = "__chunked__";
|
|
1666
|
+
const CHUNKS_MAX_LENGTH = 4e3;
|
|
1630
1667
|
/**
|
|
1631
1668
|
* Parse the request to get HTTP Cookie header string and returning an object of all cookie name-value pairs.
|
|
1632
|
-
* @param event {
|
|
1669
|
+
* @param event {HTTPEvent} H3 event or req passed by h3 handler
|
|
1633
1670
|
* @returns Object of cookie name-value pairs
|
|
1634
1671
|
* ```ts
|
|
1635
1672
|
* const cookies = parseCookies(event)
|
|
@@ -1640,7 +1677,7 @@ function parseCookies(event) {
|
|
|
1640
1677
|
}
|
|
1641
1678
|
/**
|
|
1642
1679
|
* Get a cookie value by name.
|
|
1643
|
-
* @param event {
|
|
1680
|
+
* @param event {HTTPEvent} H3 event or req passed by h3 handler
|
|
1644
1681
|
* @param name Name of the cookie to get
|
|
1645
1682
|
* @returns {*} Value of the cookie (String or undefined)
|
|
1646
1683
|
* ```ts
|
|
@@ -1695,6 +1732,59 @@ function deleteCookie(event, name, serializeOptions) {
|
|
|
1695
1732
|
});
|
|
1696
1733
|
}
|
|
1697
1734
|
/**
|
|
1735
|
+
* Get a chunked cookie value by name. Will join chunks together.
|
|
1736
|
+
* @param event {HTTPEvent} { req: Request }
|
|
1737
|
+
* @param name Name of the cookie to get
|
|
1738
|
+
* @returns {*} Value of the cookie (String or undefined)
|
|
1739
|
+
* ```ts
|
|
1740
|
+
* const authorization = getCookie(request, 'Session')
|
|
1741
|
+
* ```
|
|
1742
|
+
*/
|
|
1743
|
+
function getChunkedCookie(event, name) {
|
|
1744
|
+
const mainCookie = getCookie(event, name);
|
|
1745
|
+
if (!mainCookie || !mainCookie.startsWith(CHUNKED_COOKIE)) return mainCookie;
|
|
1746
|
+
const chunksCount = getChunkedCookieCount(mainCookie);
|
|
1747
|
+
if (chunksCount === 0) return void 0;
|
|
1748
|
+
const chunks = [];
|
|
1749
|
+
for (let i = 1; i <= chunksCount; i++) {
|
|
1750
|
+
const chunk = getCookie(event, chunkCookieName(name, i));
|
|
1751
|
+
if (!chunk) return void 0;
|
|
1752
|
+
chunks.push(chunk);
|
|
1753
|
+
}
|
|
1754
|
+
return chunks.join("");
|
|
1755
|
+
}
|
|
1756
|
+
/**
|
|
1757
|
+
* Set a cookie value by name. Chunked cookies will be created as needed.
|
|
1758
|
+
* @param event {H3Event} H3 event or res passed by h3 handler
|
|
1759
|
+
* @param name Name of the cookie to set
|
|
1760
|
+
* @param value Value of the cookie to set
|
|
1761
|
+
* @param options {CookieSerializeOptions} Options for serializing the cookie
|
|
1762
|
+
* ```ts
|
|
1763
|
+
* setCookie(res, 'Session', '<session data>')
|
|
1764
|
+
* ```
|
|
1765
|
+
*/
|
|
1766
|
+
function setChunkedCookie(event, name, value, options) {
|
|
1767
|
+
const chunkMaxLength = options?.chunkMaxLength || CHUNKS_MAX_LENGTH;
|
|
1768
|
+
const chunkCount = Math.ceil(value.length / chunkMaxLength);
|
|
1769
|
+
const previousCookie = getCookie(event, name);
|
|
1770
|
+
if (previousCookie?.startsWith(CHUNKED_COOKIE)) {
|
|
1771
|
+
const previousChunkCount = getChunkedCookieCount(previousCookie);
|
|
1772
|
+
if (previousChunkCount > chunkCount) for (let i = chunkCount; i <= previousChunkCount; i++) deleteCookie(event, chunkCookieName(name, i), options);
|
|
1773
|
+
}
|
|
1774
|
+
if (chunkCount <= 1) {
|
|
1775
|
+
setCookie(event, name, value, options);
|
|
1776
|
+
return;
|
|
1777
|
+
}
|
|
1778
|
+
const mainCookieValue = `${CHUNKED_COOKIE}${chunkCount}`;
|
|
1779
|
+
setCookie(event, name, mainCookieValue, options);
|
|
1780
|
+
for (let i = 1; i <= chunkCount; i++) {
|
|
1781
|
+
const start = (i - 1) * chunkMaxLength;
|
|
1782
|
+
const end = start + chunkMaxLength;
|
|
1783
|
+
const chunkValue = value.slice(start, end);
|
|
1784
|
+
setCookie(event, chunkCookieName(name, i), chunkValue, options);
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1787
|
+
/**
|
|
1698
1788
|
* Cookies are unique by "cookie-name, domain-value, and path-value".
|
|
1699
1789
|
*
|
|
1700
1790
|
* @see https://httpwg.org/specs/rfc6265.html#rfc.section.4.1.2
|
|
@@ -1706,6 +1796,13 @@ function _getDistinctCookieKey(name, options) {
|
|
|
1706
1796
|
options.path || "/"
|
|
1707
1797
|
].join(";");
|
|
1708
1798
|
}
|
|
1799
|
+
function getChunkedCookieCount(cookie) {
|
|
1800
|
+
if (!cookie?.startsWith(CHUNKED_COOKIE)) return Number.NaN;
|
|
1801
|
+
return Number.parseInt(cookie.slice(CHUNKED_COOKIE.length));
|
|
1802
|
+
}
|
|
1803
|
+
function chunkCookieName(name, chunkNumber) {
|
|
1804
|
+
return `${name}.${chunkNumber}`;
|
|
1805
|
+
}
|
|
1709
1806
|
|
|
1710
1807
|
//#endregion
|
|
1711
1808
|
//#region src/utils/internal/event-stream.ts
|
|
@@ -1748,6 +1845,18 @@ var EventStream = class {
|
|
|
1748
1845
|
}
|
|
1749
1846
|
await this._sendEvent(message);
|
|
1750
1847
|
}
|
|
1848
|
+
async pushComment(comment) {
|
|
1849
|
+
if (this._writerIsClosed) return;
|
|
1850
|
+
if (this._paused && !this._unsentData) {
|
|
1851
|
+
this._unsentData = formatEventStreamComment(comment);
|
|
1852
|
+
return;
|
|
1853
|
+
}
|
|
1854
|
+
if (this._paused) {
|
|
1855
|
+
this._unsentData += formatEventStreamComment(comment);
|
|
1856
|
+
return;
|
|
1857
|
+
}
|
|
1858
|
+
await this._writer.write(this._encoder.encode(formatEventStreamComment(comment))).catch();
|
|
1859
|
+
}
|
|
1751
1860
|
async _sendEvent(message) {
|
|
1752
1861
|
if (this._writerIsClosed) return;
|
|
1753
1862
|
if (this._paused && !this._unsentData) {
|
|
@@ -1814,6 +1923,9 @@ var EventStream = class {
|
|
|
1814
1923
|
return this._transformStream.readable;
|
|
1815
1924
|
}
|
|
1816
1925
|
};
|
|
1926
|
+
function formatEventStreamComment(comment) {
|
|
1927
|
+
return `: ${comment}\n\n`;
|
|
1928
|
+
}
|
|
1817
1929
|
function formatEventStreamMessage(message) {
|
|
1818
1930
|
let result = "";
|
|
1819
1931
|
if (message.id) result += `id: ${message.id}\n`;
|
|
@@ -2294,10 +2406,12 @@ async function useSession(event, config) {
|
|
|
2294
2406
|
await getSession(event, config);
|
|
2295
2407
|
const sessionManager = {
|
|
2296
2408
|
get id() {
|
|
2297
|
-
|
|
2409
|
+
const context = getEventContext(event);
|
|
2410
|
+
return context?.sessions?.[sessionName]?.id;
|
|
2298
2411
|
},
|
|
2299
2412
|
get data() {
|
|
2300
|
-
|
|
2413
|
+
const context = getEventContext(event);
|
|
2414
|
+
return context.sessions?.[sessionName]?.data || {};
|
|
2301
2415
|
},
|
|
2302
2416
|
update: async (update) => {
|
|
2303
2417
|
await updateSession(event, config, update);
|
|
@@ -2315,29 +2429,30 @@ async function useSession(event, config) {
|
|
|
2315
2429
|
*/
|
|
2316
2430
|
async function getSession(event, config) {
|
|
2317
2431
|
const sessionName = config.name || DEFAULT_SESSION_NAME;
|
|
2318
|
-
|
|
2319
|
-
|
|
2432
|
+
const context = getEventContext(event);
|
|
2433
|
+
if (!context.sessions) context.sessions = new EmptyObject();
|
|
2434
|
+
const existingSession = context.sessions[sessionName];
|
|
2320
2435
|
if (existingSession) return existingSession[kGetSession] || existingSession;
|
|
2321
2436
|
const session = {
|
|
2322
2437
|
id: "",
|
|
2323
2438
|
createdAt: 0,
|
|
2324
2439
|
data: new EmptyObject()
|
|
2325
2440
|
};
|
|
2326
|
-
|
|
2441
|
+
context.sessions[sessionName] = session;
|
|
2327
2442
|
let sealedSession;
|
|
2328
2443
|
if (config.sessionHeader !== false) {
|
|
2329
2444
|
const headerName = typeof config.sessionHeader === "string" ? config.sessionHeader.toLowerCase() : `x-${sessionName.toLowerCase()}-session`;
|
|
2330
2445
|
const headerValue = event.req.headers.get(headerName);
|
|
2331
2446
|
if (typeof headerValue === "string") sealedSession = headerValue;
|
|
2332
2447
|
}
|
|
2333
|
-
if (!sealedSession) sealedSession =
|
|
2448
|
+
if (!sealedSession) sealedSession = getChunkedCookie(event, sessionName);
|
|
2334
2449
|
if (sealedSession) {
|
|
2335
2450
|
const promise = unsealSession(event, config, sealedSession).catch(() => {}).then((unsealed) => {
|
|
2336
2451
|
Object.assign(session, unsealed);
|
|
2337
|
-
delete
|
|
2452
|
+
delete context.sessions[sessionName][kGetSession];
|
|
2338
2453
|
return session;
|
|
2339
2454
|
});
|
|
2340
|
-
|
|
2455
|
+
context.sessions[sessionName][kGetSession] = promise;
|
|
2341
2456
|
await promise;
|
|
2342
2457
|
}
|
|
2343
2458
|
if (!session.id) {
|
|
@@ -2352,12 +2467,13 @@ async function getSession(event, config) {
|
|
|
2352
2467
|
*/
|
|
2353
2468
|
async function updateSession(event, config, update) {
|
|
2354
2469
|
const sessionName = config.name || DEFAULT_SESSION_NAME;
|
|
2355
|
-
const
|
|
2470
|
+
const context = getEventContext(event);
|
|
2471
|
+
const session = context.sessions?.[sessionName] || await getSession(event, config);
|
|
2356
2472
|
if (typeof update === "function") update = update(session.data);
|
|
2357
2473
|
if (update) Object.assign(session.data, update);
|
|
2358
|
-
if (config.cookie !== false) {
|
|
2474
|
+
if (config.cookie !== false && event.res) {
|
|
2359
2475
|
const sealed = await sealSession(event, config);
|
|
2360
|
-
|
|
2476
|
+
setChunkedCookie(event, sessionName, sealed, {
|
|
2361
2477
|
...DEFAULT_SESSION_COOKIE,
|
|
2362
2478
|
expires: config.maxAge ? new Date(session.createdAt + config.maxAge * 1e3) : void 0,
|
|
2363
2479
|
...config.cookie
|
|
@@ -2370,7 +2486,8 @@ async function updateSession(event, config, update) {
|
|
|
2370
2486
|
*/
|
|
2371
2487
|
async function sealSession(event, config) {
|
|
2372
2488
|
const sessionName = config.name || DEFAULT_SESSION_NAME;
|
|
2373
|
-
const
|
|
2489
|
+
const context = getEventContext(event);
|
|
2490
|
+
const session = context.sessions?.[sessionName] || await getSession(event, config);
|
|
2374
2491
|
const sealed = await seal(session, config.password, {
|
|
2375
2492
|
...defaults,
|
|
2376
2493
|
ttl: config.maxAge ? config.maxAge * 1e3 : 0,
|
|
@@ -2397,9 +2514,10 @@ async function unsealSession(_event, config, sealed) {
|
|
|
2397
2514
|
* Clear the session data for the current request.
|
|
2398
2515
|
*/
|
|
2399
2516
|
function clearSession(event, config) {
|
|
2517
|
+
const context = getEventContext(event);
|
|
2400
2518
|
const sessionName = config.name || DEFAULT_SESSION_NAME;
|
|
2401
|
-
if (
|
|
2402
|
-
|
|
2519
|
+
if (context.sessions?.[sessionName]) delete context.sessions[sessionName];
|
|
2520
|
+
if (event.res && config.cookie !== false) setChunkedCookie(event, sessionName, "", {
|
|
2403
2521
|
...DEFAULT_SESSION_COOKIE,
|
|
2404
2522
|
...config.cookie
|
|
2405
2523
|
});
|
|
@@ -2604,7 +2722,8 @@ async function requireBasicAuth(event, opts) {
|
|
|
2604
2722
|
if (opts.username && username !== opts.username) throw autheFailed(event, opts?.realm);
|
|
2605
2723
|
if (opts.password && password !== opts.password) throw autheFailed(event, opts?.realm);
|
|
2606
2724
|
if (opts.validate && !await opts.validate(username, password)) throw autheFailed(event, opts?.realm);
|
|
2607
|
-
|
|
2725
|
+
const context = getEventContext(event);
|
|
2726
|
+
context.basicAuth = {
|
|
2608
2727
|
username,
|
|
2609
2728
|
password,
|
|
2610
2729
|
realm: opts.realm
|
|
@@ -2646,7 +2765,7 @@ async function getRequestFingerprint(event, opts = {}) {
|
|
|
2646
2765
|
const fingerprint = [];
|
|
2647
2766
|
if (opts.ip !== false) fingerprint.push(getRequestIP(event, { xForwardedFor: opts.xForwardedFor }));
|
|
2648
2767
|
if (opts.method === true) fingerprint.push(event.req.method);
|
|
2649
|
-
if (opts.url === true) fingerprint.push(event.url
|
|
2768
|
+
if (opts.url === true) fingerprint.push(event.req.url);
|
|
2650
2769
|
if (opts.userAgent === true) fingerprint.push(event.req.headers.get("user-agent"));
|
|
2651
2770
|
const fingerprintString = fingerprint.filter(Boolean).join("|");
|
|
2652
2771
|
if (!fingerprintString) return null;
|
|
@@ -2839,4 +2958,4 @@ const createRouter$1 = (config) => new H3(config);
|
|
|
2839
2958
|
const useBase = withBase;
|
|
2840
2959
|
|
|
2841
2960
|
//#endregion
|
|
2842
|
-
export { H3, H3Core, H3Error, H3Event, HTTPError, appendCorsHeaders, appendCorsPreflightHeaders, appendHeader, appendHeaders, appendResponseHeader, appendResponseHeaders, assertMethod, basicAuth, clearResponseHeaders, clearSession, createApp, createError, createEventStream, createRouter$1 as createRouter, defaultContentType, defineEventHandler, defineHandler, defineLazyEventHandler, defineMiddleware, defineNodeHandler, defineNodeListener, defineNodeMiddleware, definePlugin, defineRoute, defineValidatedHandler, defineWebSocket, defineWebSocketHandler, deleteCookie, dynamicEventHandler, eventHandler, fetchWithEvent, freezeApp, fromNodeHandler, fromNodeMiddleware, fromWebHandler, getBodyStream, getCookie, getHeader, getHeaders, getMethod, getProxyRequestHeaders, getQuery, getRequestFingerprint, getRequestHeader, getRequestHeaders, getRequestHost, getRequestIP, getRequestPath, getRequestProtocol, getRequestURL, getRequestWebStream, getResponseHeader, getResponseHeaders, getResponseStatus, getResponseStatusText, getRouterParam, getRouterParams, getSession, getValidatedQuery, getValidatedRouterParams, handleCacheHeaders, handleCors, html, isCorsOriginAllowed, isError, isEvent, isMethod, isPreflightRequest, iterable, lazyEventHandler, mockEvent, noContent, onError, onRequest, onResponse, parseCookies, proxy, proxyRequest, readBody, readFormData, readFormDataBody, readMultipartFormData, readRawBody, readValidatedBody, redirect, removeResponseHeader, requireBasicAuth, sanitizeStatusCode, sanitizeStatusMessage, sealSession, sendIterable, sendNoContent, sendProxy, sendRedirect, sendStream, sendWebResponse, serveStatic, setCookie, setHeader, setHeaders, setResponseHeader, setResponseHeaders, setResponseStatus, toEventHandler, toNodeHandler$1 as toNodeHandler, toNodeListener, toResponse, toWebHandler, unsealSession, updateSession, useBase, useSession, withBase, writeEarlyHints };
|
|
2961
|
+
export { H3, H3Core, H3Error, H3Event, HTTPError, appendCorsHeaders, appendCorsPreflightHeaders, appendHeader, appendHeaders, appendResponseHeader, appendResponseHeaders, assertMethod, basicAuth, clearResponseHeaders, clearSession, createApp, createError, createEventStream, createRouter$1 as createRouter, defaultContentType, defineEventHandler, defineHandler, defineLazyEventHandler, defineMiddleware, defineNodeHandler, defineNodeListener, defineNodeMiddleware, definePlugin, defineRoute, defineValidatedHandler, defineWebSocket, defineWebSocketHandler, deleteCookie, dynamicEventHandler, eventHandler, fetchWithEvent, freezeApp, fromNodeHandler, fromNodeMiddleware, fromWebHandler, getBodyStream, getCookie, getEventContext, getHeader, getHeaders, getMethod, getProxyRequestHeaders, getQuery, getRequestFingerprint, getRequestHeader, getRequestHeaders, getRequestHost, getRequestIP, getRequestPath, getRequestProtocol, getRequestURL, getRequestWebStream, getResponseHeader, getResponseHeaders, getResponseStatus, getResponseStatusText, getRouterParam, getRouterParams, getSession, getValidatedQuery, getValidatedRouterParams, handleCacheHeaders, handleCors, html, isCorsOriginAllowed, isError, isEvent, isHTTPEvent, isMethod, isPreflightRequest, iterable, lazyEventHandler, mockEvent, noContent, onError, onRequest, onResponse, parseCookies, proxy, proxyRequest, readBody, readFormData, readFormDataBody, readMultipartFormData, readRawBody, readValidatedBody, redirect, removeResponseHeader, requireBasicAuth, sanitizeStatusCode, sanitizeStatusMessage, sealSession, sendIterable, sendNoContent, sendProxy, sendRedirect, sendStream, sendWebResponse, serveStatic, setCookie, setHeader, setHeaders, setResponseHeader, setResponseHeaders, setResponseStatus, toEventHandler, toNodeHandler$1 as toNodeHandler, toNodeListener, toRequest, toResponse, toWebHandler, unsealSession, updateSession, useBase, useSession, withBase, writeEarlyHints };
|