h3 0.8.5 → 0.8.6
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/README.md +1 -0
- package/dist/index.cjs +76 -4
- package/dist/index.d.ts +19 -2
- package/dist/index.mjs +76 -5
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -136,6 +136,7 @@ H3 has concept of compasable utilities that accept `event` (from `eventHandler((
|
|
|
136
136
|
- `isMethod(event, expected, allowHead?)`
|
|
137
137
|
- `assertMethod(event, expected, allowHead?)`
|
|
138
138
|
- `createError({ statusCode, statusMessage, data? })`
|
|
139
|
+
- `sendProxy(event, { target, headers?, fetchOptions?, fetch?, sendStream? })`
|
|
139
140
|
|
|
140
141
|
👉 You can learn more about usage in [JSDocs Documentation](https://www.jsdocs.io/package/h3#package-functions).
|
|
141
142
|
|
package/dist/index.cjs
CHANGED
|
@@ -25,6 +25,19 @@ class H3Error extends Error {
|
|
|
25
25
|
this.unhandled = false;
|
|
26
26
|
this.statusMessage = void 0;
|
|
27
27
|
}
|
|
28
|
+
toJSON() {
|
|
29
|
+
const obj = {
|
|
30
|
+
message: this.message,
|
|
31
|
+
statusCode: this.statusCode
|
|
32
|
+
};
|
|
33
|
+
if (this.statusMessage) {
|
|
34
|
+
obj.statusMessage = this.statusMessage;
|
|
35
|
+
}
|
|
36
|
+
if (this.data !== void 0) {
|
|
37
|
+
obj.data = this.data;
|
|
38
|
+
}
|
|
39
|
+
return obj;
|
|
40
|
+
}
|
|
28
41
|
}
|
|
29
42
|
H3Error.__h3_error__ = true;
|
|
30
43
|
function createError(input) {
|
|
@@ -47,14 +60,18 @@ function createError(input) {
|
|
|
47
60
|
}
|
|
48
61
|
}
|
|
49
62
|
}
|
|
63
|
+
if (input.data) {
|
|
64
|
+
err.data = input.data;
|
|
65
|
+
}
|
|
50
66
|
if (input.statusCode) {
|
|
51
67
|
err.statusCode = input.statusCode;
|
|
68
|
+
} else if (input.status) {
|
|
69
|
+
err.statusCode = input.status;
|
|
52
70
|
}
|
|
53
71
|
if (input.statusMessage) {
|
|
54
72
|
err.statusMessage = input.statusMessage;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
err.data = input.data;
|
|
73
|
+
} else if (input.statusText) {
|
|
74
|
+
err.statusMessage = input.statusText;
|
|
58
75
|
}
|
|
59
76
|
if (input.fatal !== void 0) {
|
|
60
77
|
err.fatal = input.fatal;
|
|
@@ -349,6 +366,44 @@ function deleteCookie(event, name, serializeOptions) {
|
|
|
349
366
|
});
|
|
350
367
|
}
|
|
351
368
|
|
|
369
|
+
async function sendProxy(event, target, opts = {}) {
|
|
370
|
+
const _fetch = opts.fetch || globalThis.fetch;
|
|
371
|
+
if (!_fetch) {
|
|
372
|
+
throw new Error("fetch is not available. Try importing `node-fetch-native/polyfill` for Node.js.");
|
|
373
|
+
}
|
|
374
|
+
const response = await _fetch(target, {
|
|
375
|
+
headers: opts.headers,
|
|
376
|
+
...opts.fetchOptions
|
|
377
|
+
});
|
|
378
|
+
event.res.statusCode = response.status;
|
|
379
|
+
event.res.statusMessage = response.statusText;
|
|
380
|
+
for (const [key, value] of response.headers.entries()) {
|
|
381
|
+
if (key === "content-encoding") {
|
|
382
|
+
continue;
|
|
383
|
+
}
|
|
384
|
+
if (key === "content-length") {
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
event.res.setHeader(key, value);
|
|
388
|
+
}
|
|
389
|
+
try {
|
|
390
|
+
if (response.body) {
|
|
391
|
+
if (opts.sendStream === false) {
|
|
392
|
+
const data = new Uint8Array(await response.arrayBuffer());
|
|
393
|
+
event.res.end(data);
|
|
394
|
+
} else {
|
|
395
|
+
for await (const chunk of response.body) {
|
|
396
|
+
event.res.write(chunk);
|
|
397
|
+
}
|
|
398
|
+
event.res.end();
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
} catch (err) {
|
|
402
|
+
event.res.end();
|
|
403
|
+
throw err;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
352
407
|
class H3Headers {
|
|
353
408
|
constructor(init) {
|
|
354
409
|
if (!init) {
|
|
@@ -361,6 +416,18 @@ class H3Headers {
|
|
|
361
416
|
this._headers = Object.fromEntries(Object.entries(init).map(([key, value]) => [key.toLowerCase(), value]));
|
|
362
417
|
}
|
|
363
418
|
}
|
|
419
|
+
[Symbol.iterator]() {
|
|
420
|
+
return this.entries();
|
|
421
|
+
}
|
|
422
|
+
entries() {
|
|
423
|
+
throw Object.entries(this._headers)[Symbol.iterator]();
|
|
424
|
+
}
|
|
425
|
+
keys() {
|
|
426
|
+
return Object.keys(this._headers)[Symbol.iterator]();
|
|
427
|
+
}
|
|
428
|
+
values() {
|
|
429
|
+
throw Object.values(this._headers)[Symbol.iterator]();
|
|
430
|
+
}
|
|
364
431
|
append(name, value) {
|
|
365
432
|
const _name = name.toLowerCase();
|
|
366
433
|
this.set(_name, [this.get(_name), value].filter(Boolean).join(", "));
|
|
@@ -700,7 +767,11 @@ function createRouter(opts = {}) {
|
|
|
700
767
|
router[method] = (path, handle) => router.add(path, handle, method);
|
|
701
768
|
}
|
|
702
769
|
router.handler = eventHandler((event) => {
|
|
703
|
-
|
|
770
|
+
let path = event.req.url || "/";
|
|
771
|
+
const qIndex = path.indexOf("?");
|
|
772
|
+
if (qIndex !== -1) {
|
|
773
|
+
path = path.substring(0, qIndex);
|
|
774
|
+
}
|
|
704
775
|
const matched = _router.lookup(path);
|
|
705
776
|
if (!matched) {
|
|
706
777
|
if (opts.preemtive) {
|
|
@@ -778,6 +849,7 @@ exports.readBody = readBody;
|
|
|
778
849
|
exports.readRawBody = readRawBody;
|
|
779
850
|
exports.send = send;
|
|
780
851
|
exports.sendError = sendError;
|
|
852
|
+
exports.sendProxy = sendProxy;
|
|
781
853
|
exports.sendRedirect = sendRedirect;
|
|
782
854
|
exports.sendStream = sendStream;
|
|
783
855
|
exports.setCookie = setCookie;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { IncomingMessage, ServerResponse, OutgoingMessage } from 'http';
|
|
2
2
|
export { IncomingMessage as NodeIncomingMessage, ServerResponse as NodeServerResponse } from 'http';
|
|
3
3
|
import { CookieSerializeOptions } from 'cookie-es';
|
|
4
|
+
import { RequestHeaders as RequestHeaders$1 } from 'src/types';
|
|
4
5
|
import * as ufo from 'ufo';
|
|
5
6
|
|
|
6
7
|
declare type HTTPMethod = 'GET' | 'HEAD' | 'PATCH' | 'POST' | 'PUT' | 'DELETE' | 'CONNECT' | 'OPTIONS' | 'TRACE';
|
|
@@ -30,6 +31,10 @@ declare function callNodeListener(handler: NodeMiddleware, req: IncomingMessage,
|
|
|
30
31
|
declare class H3Headers implements Headers {
|
|
31
32
|
_headers: Record<string, string>;
|
|
32
33
|
constructor(init?: HeadersInit);
|
|
34
|
+
[Symbol.iterator](): IterableIterator<[string, string]>;
|
|
35
|
+
entries(): IterableIterator<[string, string]>;
|
|
36
|
+
keys(): IterableIterator<string>;
|
|
37
|
+
values(): IterableIterator<string>;
|
|
33
38
|
append(name: string, value: string): void;
|
|
34
39
|
delete(name: string): void;
|
|
35
40
|
get(name: string): string | null;
|
|
@@ -127,6 +132,7 @@ declare function createAppEventHandler(stack: Stack, options: AppOptions): Event
|
|
|
127
132
|
*/
|
|
128
133
|
declare class H3Error extends Error {
|
|
129
134
|
static __h3_error__: boolean;
|
|
135
|
+
toJSON(): Pick<H3Error, "statusCode" | "statusMessage" | "data" | "message">;
|
|
130
136
|
statusCode: number;
|
|
131
137
|
fatal: boolean;
|
|
132
138
|
unhandled: boolean;
|
|
@@ -139,7 +145,10 @@ declare class H3Error extends Error {
|
|
|
139
145
|
* @param input {Partial<H3Error>}
|
|
140
146
|
* @return {H3Error} An instance of the H3Error
|
|
141
147
|
*/
|
|
142
|
-
declare function createError(input: string | Partial<H3Error>
|
|
148
|
+
declare function createError(input: string | Partial<H3Error> & {
|
|
149
|
+
status?: number;
|
|
150
|
+
statusText?: string;
|
|
151
|
+
}): H3Error;
|
|
143
152
|
/**
|
|
144
153
|
* Receive an error and return the corresponding response.<br>
|
|
145
154
|
* H3 internally uses this function to handle unhandled errors.<br>
|
|
@@ -243,6 +252,14 @@ declare function setCookie(event: H3Event, name: string, value: string, serializ
|
|
|
243
252
|
*/
|
|
244
253
|
declare function deleteCookie(event: H3Event, name: string, serializeOptions?: CookieSerializeOptions): void;
|
|
245
254
|
|
|
255
|
+
interface SendProxyOptions {
|
|
256
|
+
headers?: RequestHeaders$1 | HeadersInit;
|
|
257
|
+
fetchOptions?: RequestInit;
|
|
258
|
+
fetch?: typeof fetch;
|
|
259
|
+
sendStream?: boolean;
|
|
260
|
+
}
|
|
261
|
+
declare function sendProxy(event: H3Event, target: string, opts?: SendProxyOptions): Promise<void>;
|
|
262
|
+
|
|
246
263
|
declare function getQuery(event: H3Event): ufo.QueryObject;
|
|
247
264
|
/** @deprecated Use `h3.getQuery` */
|
|
248
265
|
declare const useQuery: typeof getQuery;
|
|
@@ -288,4 +305,4 @@ interface CreateRouterOptions {
|
|
|
288
305
|
}
|
|
289
306
|
declare function createRouter(opts?: CreateRouterOptions): Router;
|
|
290
307
|
|
|
291
|
-
export { AddRouteShortcuts, App, AppOptions, AppUse, CacheConditions, CreateRouterOptions, DynamicEventHandler, Encoding, EventHandler, EventHandlerResponse, H3Error, H3Event, H3EventContext, H3Headers, H3Response, HTTPMethod, InputLayer, InputStack, Layer, LazyEventHandler, MIMES, Matcher, NodeListener, NodeMiddleware, NodePromisifiedHandler, RequestHeaders, Router, RouterMethod, RouterUse, Stack, appendHeader, appendHeaders, appendResponseHeader, appendResponseHeaders, assertMethod, callNodeListener, createApp, createAppEventHandler, createError, createEvent, createRouter, defaultContentType, defineEventHandler, defineLazyEventHandler, defineNodeListener, defineNodeMiddleware, deleteCookie, dynamicEventHandler, eventHandler, fromNodeMiddleware, getCookie, getHeader, getHeaders, getMethod, getQuery, getRequestHeader, getRequestHeaders, getResponseHeader, getResponseHeaders, getRouterParam, getRouterParams, handleCacheHeaders, isError, isEvent, isEventHandler, isMethod, isStream, lazyEventHandler, parseCookies, promisifyNodeListener, readBody, readRawBody, send, sendError, sendRedirect, sendStream, setCookie, setHeader, setHeaders, setResponseHeader, setResponseHeaders, toEventHandler, toNodeListener, use, useBase, useBody, useCookie, useCookies, useMethod, useQuery, useRawBody, writeEarlyHints };
|
|
308
|
+
export { AddRouteShortcuts, App, AppOptions, AppUse, CacheConditions, CreateRouterOptions, DynamicEventHandler, Encoding, EventHandler, EventHandlerResponse, H3Error, H3Event, H3EventContext, H3Headers, H3Response, HTTPMethod, InputLayer, InputStack, Layer, LazyEventHandler, MIMES, Matcher, NodeListener, NodeMiddleware, NodePromisifiedHandler, RequestHeaders, Router, RouterMethod, RouterUse, SendProxyOptions, Stack, appendHeader, appendHeaders, appendResponseHeader, appendResponseHeaders, assertMethod, callNodeListener, createApp, createAppEventHandler, createError, createEvent, createRouter, defaultContentType, defineEventHandler, defineLazyEventHandler, defineNodeListener, defineNodeMiddleware, deleteCookie, dynamicEventHandler, eventHandler, fromNodeMiddleware, getCookie, getHeader, getHeaders, getMethod, getQuery, getRequestHeader, getRequestHeaders, getResponseHeader, getResponseHeaders, getRouterParam, getRouterParams, handleCacheHeaders, isError, isEvent, isEventHandler, isMethod, isStream, lazyEventHandler, parseCookies, promisifyNodeListener, readBody, readRawBody, send, sendError, sendProxy, sendRedirect, sendStream, setCookie, setHeader, setHeaders, setResponseHeader, setResponseHeaders, toEventHandler, toNodeListener, use, useBase, useBody, useCookie, useCookies, useMethod, useQuery, useRawBody, writeEarlyHints };
|
package/dist/index.mjs
CHANGED
|
@@ -23,6 +23,19 @@ class H3Error extends Error {
|
|
|
23
23
|
this.unhandled = false;
|
|
24
24
|
this.statusMessage = void 0;
|
|
25
25
|
}
|
|
26
|
+
toJSON() {
|
|
27
|
+
const obj = {
|
|
28
|
+
message: this.message,
|
|
29
|
+
statusCode: this.statusCode
|
|
30
|
+
};
|
|
31
|
+
if (this.statusMessage) {
|
|
32
|
+
obj.statusMessage = this.statusMessage;
|
|
33
|
+
}
|
|
34
|
+
if (this.data !== void 0) {
|
|
35
|
+
obj.data = this.data;
|
|
36
|
+
}
|
|
37
|
+
return obj;
|
|
38
|
+
}
|
|
26
39
|
}
|
|
27
40
|
H3Error.__h3_error__ = true;
|
|
28
41
|
function createError(input) {
|
|
@@ -45,14 +58,18 @@ function createError(input) {
|
|
|
45
58
|
}
|
|
46
59
|
}
|
|
47
60
|
}
|
|
61
|
+
if (input.data) {
|
|
62
|
+
err.data = input.data;
|
|
63
|
+
}
|
|
48
64
|
if (input.statusCode) {
|
|
49
65
|
err.statusCode = input.statusCode;
|
|
66
|
+
} else if (input.status) {
|
|
67
|
+
err.statusCode = input.status;
|
|
50
68
|
}
|
|
51
69
|
if (input.statusMessage) {
|
|
52
70
|
err.statusMessage = input.statusMessage;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
err.data = input.data;
|
|
71
|
+
} else if (input.statusText) {
|
|
72
|
+
err.statusMessage = input.statusText;
|
|
56
73
|
}
|
|
57
74
|
if (input.fatal !== void 0) {
|
|
58
75
|
err.fatal = input.fatal;
|
|
@@ -347,6 +364,44 @@ function deleteCookie(event, name, serializeOptions) {
|
|
|
347
364
|
});
|
|
348
365
|
}
|
|
349
366
|
|
|
367
|
+
async function sendProxy(event, target, opts = {}) {
|
|
368
|
+
const _fetch = opts.fetch || globalThis.fetch;
|
|
369
|
+
if (!_fetch) {
|
|
370
|
+
throw new Error("fetch is not available. Try importing `node-fetch-native/polyfill` for Node.js.");
|
|
371
|
+
}
|
|
372
|
+
const response = await _fetch(target, {
|
|
373
|
+
headers: opts.headers,
|
|
374
|
+
...opts.fetchOptions
|
|
375
|
+
});
|
|
376
|
+
event.res.statusCode = response.status;
|
|
377
|
+
event.res.statusMessage = response.statusText;
|
|
378
|
+
for (const [key, value] of response.headers.entries()) {
|
|
379
|
+
if (key === "content-encoding") {
|
|
380
|
+
continue;
|
|
381
|
+
}
|
|
382
|
+
if (key === "content-length") {
|
|
383
|
+
continue;
|
|
384
|
+
}
|
|
385
|
+
event.res.setHeader(key, value);
|
|
386
|
+
}
|
|
387
|
+
try {
|
|
388
|
+
if (response.body) {
|
|
389
|
+
if (opts.sendStream === false) {
|
|
390
|
+
const data = new Uint8Array(await response.arrayBuffer());
|
|
391
|
+
event.res.end(data);
|
|
392
|
+
} else {
|
|
393
|
+
for await (const chunk of response.body) {
|
|
394
|
+
event.res.write(chunk);
|
|
395
|
+
}
|
|
396
|
+
event.res.end();
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
} catch (err) {
|
|
400
|
+
event.res.end();
|
|
401
|
+
throw err;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
350
405
|
class H3Headers {
|
|
351
406
|
constructor(init) {
|
|
352
407
|
if (!init) {
|
|
@@ -359,6 +414,18 @@ class H3Headers {
|
|
|
359
414
|
this._headers = Object.fromEntries(Object.entries(init).map(([key, value]) => [key.toLowerCase(), value]));
|
|
360
415
|
}
|
|
361
416
|
}
|
|
417
|
+
[Symbol.iterator]() {
|
|
418
|
+
return this.entries();
|
|
419
|
+
}
|
|
420
|
+
entries() {
|
|
421
|
+
throw Object.entries(this._headers)[Symbol.iterator]();
|
|
422
|
+
}
|
|
423
|
+
keys() {
|
|
424
|
+
return Object.keys(this._headers)[Symbol.iterator]();
|
|
425
|
+
}
|
|
426
|
+
values() {
|
|
427
|
+
throw Object.values(this._headers)[Symbol.iterator]();
|
|
428
|
+
}
|
|
362
429
|
append(name, value) {
|
|
363
430
|
const _name = name.toLowerCase();
|
|
364
431
|
this.set(_name, [this.get(_name), value].filter(Boolean).join(", "));
|
|
@@ -698,7 +765,11 @@ function createRouter(opts = {}) {
|
|
|
698
765
|
router[method] = (path, handle) => router.add(path, handle, method);
|
|
699
766
|
}
|
|
700
767
|
router.handler = eventHandler((event) => {
|
|
701
|
-
|
|
768
|
+
let path = event.req.url || "/";
|
|
769
|
+
const qIndex = path.indexOf("?");
|
|
770
|
+
if (qIndex !== -1) {
|
|
771
|
+
path = path.substring(0, qIndex);
|
|
772
|
+
}
|
|
702
773
|
const matched = _router.lookup(path);
|
|
703
774
|
if (!matched) {
|
|
704
775
|
if (opts.preemtive) {
|
|
@@ -727,4 +798,4 @@ function createRouter(opts = {}) {
|
|
|
727
798
|
return router;
|
|
728
799
|
}
|
|
729
800
|
|
|
730
|
-
export { H3Error, H3Event, H3Headers, H3Response, MIMES, appendHeader, appendHeaders, appendResponseHeader, appendResponseHeaders, assertMethod, callNodeListener, createApp, createAppEventHandler, createError, createEvent, createRouter, defaultContentType, defineEventHandler, defineLazyEventHandler, defineNodeListener, defineNodeMiddleware, deleteCookie, dynamicEventHandler, eventHandler, fromNodeMiddleware, getCookie, getHeader, getHeaders, getMethod, getQuery, getRequestHeader, getRequestHeaders, getResponseHeader, getResponseHeaders, getRouterParam, getRouterParams, handleCacheHeaders, isError, isEvent, isEventHandler, isMethod, isStream, lazyEventHandler, parseCookies, promisifyNodeListener, readBody, readRawBody, send, sendError, sendRedirect, sendStream, setCookie, setHeader, setHeaders, setResponseHeader, setResponseHeaders, toEventHandler, toNodeListener, use, useBase, useBody, useCookie, useCookies, useMethod, useQuery, useRawBody, writeEarlyHints };
|
|
801
|
+
export { H3Error, H3Event, H3Headers, H3Response, MIMES, appendHeader, appendHeaders, appendResponseHeader, appendResponseHeaders, assertMethod, callNodeListener, createApp, createAppEventHandler, createError, createEvent, createRouter, defaultContentType, defineEventHandler, defineLazyEventHandler, defineNodeListener, defineNodeMiddleware, deleteCookie, dynamicEventHandler, eventHandler, fromNodeMiddleware, getCookie, getHeader, getHeaders, getMethod, getQuery, getRequestHeader, getRequestHeaders, getResponseHeader, getResponseHeaders, getRouterParam, getRouterParams, handleCacheHeaders, isError, isEvent, isEventHandler, isMethod, isStream, lazyEventHandler, parseCookies, promisifyNodeListener, readBody, readRawBody, send, sendError, sendProxy, sendRedirect, sendStream, setCookie, setHeader, setHeaders, setResponseHeader, setResponseHeaders, toEventHandler, toNodeListener, use, useBase, useBody, useCookie, useCookies, useMethod, useQuery, useRawBody, writeEarlyHints };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "h3",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.6",
|
|
4
4
|
"description": "Tiny JavaScript Server",
|
|
5
5
|
"repository": "unjs/h3",
|
|
6
6
|
"license": "MIT",
|
|
@@ -29,23 +29,24 @@
|
|
|
29
29
|
"0x": "^5.4.1",
|
|
30
30
|
"@nuxtjs/eslint-config-typescript": "^11.0.0",
|
|
31
31
|
"@types/express": "^4.17.14",
|
|
32
|
-
"@types/node": "^18.11.
|
|
32
|
+
"@types/node": "^18.11.7",
|
|
33
33
|
"@types/supertest": "^2.0.12",
|
|
34
34
|
"@vitest/coverage-c8": "^0.24.3",
|
|
35
35
|
"autocannon": "^7.10.0",
|
|
36
36
|
"changelogen": "^0.3.5",
|
|
37
37
|
"connect": "^3.7.0",
|
|
38
|
-
"eslint": "^8.
|
|
38
|
+
"eslint": "^8.26.0",
|
|
39
39
|
"express": "^4.18.2",
|
|
40
40
|
"get-port": "^6.1.2",
|
|
41
41
|
"jiti": "^1.16.0",
|
|
42
42
|
"listhen": "^0.3.4",
|
|
43
|
-
"
|
|
43
|
+
"node-fetch-native": "^0.1.8",
|
|
44
|
+
"supertest": "^6.3.1",
|
|
44
45
|
"typescript": "^4.8.4",
|
|
45
46
|
"unbuild": "^0.9.4",
|
|
46
47
|
"vitest": "^0.24.3"
|
|
47
48
|
},
|
|
48
|
-
"packageManager": "pnpm@7.
|
|
49
|
+
"packageManager": "pnpm@7.14.0",
|
|
49
50
|
"scripts": {
|
|
50
51
|
"build": "unbuild",
|
|
51
52
|
"dev": "vitest",
|