h3 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -148,6 +148,8 @@ H3 has a concept of composable utilities that accept `event` (from `eventHandler
148
148
  - `createError({ statusCode, statusMessage, data? })`
149
149
  - `sendProxy(event, { target, headers?, fetchOptions?, fetch?, sendStream? })`
150
150
  - `proxyRequest(event, { target, headers?, fetchOptions?, fetch?, sendStream? })`
151
+ - `fetchWithEvent(event, req, init, { fetch? }?)`
152
+ - `getProxyRequestHeaders(event)`
151
153
  - `sendNoContent(event, code = 204)`
152
154
  - `setResponseStatus(event, status)`
153
155
  - `getResponseStatus(event)`
package/dist/index.cjs CHANGED
@@ -4,8 +4,8 @@ const ufo = require('ufo');
4
4
  const radix3 = require('radix3');
5
5
  const destr = require('destr');
6
6
  const cookieEs = require('cookie-es');
7
- const ironWebcrypto = require('iron-webcrypto');
8
7
  const crypto = require('uncrypto');
8
+ const ironWebcrypto = require('iron-webcrypto');
9
9
 
10
10
  function useBase(base, handler) {
11
11
  base = ufo.withoutTrailingSlash(base);
@@ -395,13 +395,7 @@ async function proxyRequest(event, target, opts = {}) {
395
395
  if (PayloadMethods.has(method)) {
396
396
  body = await readRawBody(event).catch(() => void 0);
397
397
  }
398
- const headers = /* @__PURE__ */ Object.create(null);
399
- const reqHeaders = getRequestHeaders(event);
400
- for (const name in reqHeaders) {
401
- if (!ignoredHeaders.has(name)) {
402
- headers[name] = reqHeaders[name];
403
- }
404
- }
398
+ const headers = getProxyRequestHeaders(event);
405
399
  if (opts.fetchOptions?.headers) {
406
400
  Object.assign(headers, opts.fetchOptions.headers);
407
401
  }
@@ -419,13 +413,7 @@ async function proxyRequest(event, target, opts = {}) {
419
413
  });
420
414
  }
421
415
  async function sendProxy(event, target, opts = {}) {
422
- const _fetch = opts.fetch || globalThis.fetch;
423
- if (!_fetch) {
424
- throw new Error(
425
- "fetch is not available. Try importing `node-fetch-native/polyfill` for Node.js."
426
- );
427
- }
428
- const response = await _fetch(target, {
416
+ const response = await _getFetch(opts.fetch)(target, {
429
417
  headers: opts.headers,
430
418
  ...opts.fetchOptions
431
419
  });
@@ -440,22 +428,49 @@ async function sendProxy(event, target, opts = {}) {
440
428
  }
441
429
  event.node.res.setHeader(key, value);
442
430
  }
443
- try {
444
- if (response.body) {
445
- if (opts.sendStream === false) {
446
- const data = new Uint8Array(await response.arrayBuffer());
447
- event.node.res.end(data);
448
- } else {
449
- for await (const chunk of response.body) {
450
- event.node.res.write(chunk);
451
- }
452
- event.node.res.end();
453
- }
431
+ if (response._data !== void 0) {
432
+ return response._data;
433
+ }
434
+ if (opts.sendStream === false) {
435
+ const data = new Uint8Array(await response.arrayBuffer());
436
+ return event.node.res.end(data);
437
+ }
438
+ for await (const chunk of response.body) {
439
+ event.node.res.write(chunk);
440
+ }
441
+ return event.node.res.end();
442
+ }
443
+ function getProxyRequestHeaders(event) {
444
+ const headers = /* @__PURE__ */ Object.create(null);
445
+ const reqHeaders = getRequestHeaders(event);
446
+ for (const name in reqHeaders) {
447
+ if (!ignoredHeaders.has(name)) {
448
+ headers[name] = reqHeaders[name];
454
449
  }
455
- } catch (error) {
456
- event.node.res.end();
457
- throw error;
458
450
  }
451
+ return headers;
452
+ }
453
+ function fetchWithEvent(event, req, init, options) {
454
+ return _getFetch(options?.fetch)(req, {
455
+ ...init,
456
+ // @ts-ignore (context is used for unenv and local fetch)
457
+ context: init.context || event.context,
458
+ headers: {
459
+ ...getProxyRequestHeaders(event),
460
+ ...init?.headers
461
+ }
462
+ });
463
+ }
464
+ function _getFetch(_fetch) {
465
+ if (_fetch) {
466
+ return _fetch;
467
+ }
468
+ if (globalThis.fetch) {
469
+ return globalThis.fetch;
470
+ }
471
+ throw new Error(
472
+ "fetch is not available. Try importing `node-fetch-native/polyfill` for Node.js."
473
+ );
459
474
  }
460
475
 
461
476
  const defer = typeof setImmediate !== "undefined" ? setImmediate : (fn) => fn();
@@ -1142,11 +1157,13 @@ exports.defineNodeMiddleware = defineNodeMiddleware;
1142
1157
  exports.deleteCookie = deleteCookie;
1143
1158
  exports.dynamicEventHandler = dynamicEventHandler;
1144
1159
  exports.eventHandler = eventHandler;
1160
+ exports.fetchWithEvent = fetchWithEvent;
1145
1161
  exports.fromNodeMiddleware = fromNodeMiddleware;
1146
1162
  exports.getCookie = getCookie;
1147
1163
  exports.getHeader = getHeader;
1148
1164
  exports.getHeaders = getHeaders;
1149
1165
  exports.getMethod = getMethod;
1166
+ exports.getProxyRequestHeaders = getProxyRequestHeaders;
1150
1167
  exports.getQuery = getQuery;
1151
1168
  exports.getRequestHeader = getRequestHeader;
1152
1169
  exports.getRequestHeaders = getRequestHeaders;
package/dist/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
- import { SealOptions } from 'iron-webcrypto';
2
1
  import { CookieSerializeOptions } from 'cookie-es';
2
+ import { SealOptions } from 'iron-webcrypto';
3
3
  import { IncomingMessage, ServerResponse, OutgoingMessage } from 'node:http';
4
4
  export { IncomingMessage as NodeIncomingMessage, ServerResponse as NodeServerResponse } from 'node:http';
5
5
  import * as ufo from 'ufo';
6
6
 
7
- type SessionDataT = Record<string, string | number | boolean>;
7
+ type SessionDataT = Record<string, any>;
8
8
  type SessionData<T extends SessionDataT = SessionDataT> = T;
9
9
  interface Session<T extends SessionDataT = SessionDataT> {
10
10
  id: string;
@@ -292,8 +292,12 @@ interface ProxyOptions {
292
292
  fetch?: typeof fetch;
293
293
  sendStream?: boolean;
294
294
  }
295
- declare function proxyRequest(event: H3Event, target: string, opts?: ProxyOptions): Promise<void>;
296
- declare function sendProxy(event: H3Event, target: string, opts?: ProxyOptions): Promise<void>;
295
+ declare function proxyRequest(event: H3Event, target: string, opts?: ProxyOptions): Promise<any>;
296
+ declare function sendProxy(event: H3Event, target: string, opts?: ProxyOptions): Promise<any>;
297
+ declare function getProxyRequestHeaders(event: H3Event): any;
298
+ declare function fetchWithEvent(event: H3Event, req: RequestInfo | URL, init?: RequestInit, options?: {
299
+ fetch: typeof fetch;
300
+ }): Promise<Response>;
297
301
 
298
302
  declare function getQuery(event: H3Event): ufo.QueryObject;
299
303
  declare function getRouterParams(event: H3Event): H3Event["context"];
@@ -349,4 +353,4 @@ interface CreateRouterOptions {
349
353
  }
350
354
  declare function createRouter(opts?: CreateRouterOptions): Router;
351
355
 
352
- export { AddRouteShortcuts, App, AppOptions, AppUse, CacheConditions, CreateRouterOptions, DynamicEventHandler, Encoding, EventHandler, EventHandlerResponse, H3Error, H3Event, H3EventContext, H3Headers, H3Response, HTTPMethod, InputLayer, InputStack, Layer, LazyEventHandler, MIMES, Matcher, NodeEventContext, NodeListener, NodeMiddleware, NodePromisifiedHandler, ProxyOptions, RequestHeaders, Router, RouterMethod, RouterUse, Session, SessionConfig, SessionData, Stack, appendHeader, appendHeaders, appendResponseHeader, appendResponseHeaders, assertMethod, callNodeListener, clearSession, createApp, createAppEventHandler, createError, createEvent, createRouter, defaultContentType, defineEventHandler, defineLazyEventHandler, defineNodeListener, defineNodeMiddleware, deleteCookie, dynamicEventHandler, eventHandler, fromNodeMiddleware, getCookie, getHeader, getHeaders, getMethod, getQuery, getRequestHeader, getRequestHeaders, getResponseHeader, getResponseHeaders, getResponseStatus, getResponseStatusText, getRouterParam, getRouterParams, getSession, handleCacheHeaders, isError, isEvent, isEventHandler, isMethod, isStream, lazyEventHandler, parseCookies, promisifyNodeListener, proxyRequest, readBody, readMultipartFormData, readRawBody, send, sendError, sendNoContent, sendProxy, sendRedirect, sendStream, setCookie, setHeader, setHeaders, setResponseHeader, setResponseHeaders, setResponseStatus, toEventHandler, toNodeListener, updateSession, use, useBase, useSession, writeEarlyHints };
356
+ export { AddRouteShortcuts, App, AppOptions, AppUse, CacheConditions, CreateRouterOptions, DynamicEventHandler, Encoding, EventHandler, EventHandlerResponse, H3Error, H3Event, H3EventContext, H3Headers, H3Response, HTTPMethod, InputLayer, InputStack, Layer, LazyEventHandler, MIMES, Matcher, NodeEventContext, NodeListener, NodeMiddleware, NodePromisifiedHandler, ProxyOptions, RequestHeaders, Router, RouterMethod, RouterUse, Session, SessionConfig, SessionData, Stack, appendHeader, appendHeaders, appendResponseHeader, appendResponseHeaders, assertMethod, callNodeListener, clearSession, createApp, createAppEventHandler, createError, createEvent, createRouter, defaultContentType, defineEventHandler, defineLazyEventHandler, defineNodeListener, defineNodeMiddleware, deleteCookie, dynamicEventHandler, eventHandler, fetchWithEvent, fromNodeMiddleware, getCookie, getHeader, getHeaders, getMethod, getProxyRequestHeaders, getQuery, getRequestHeader, getRequestHeaders, getResponseHeader, getResponseHeaders, getResponseStatus, getResponseStatusText, getRouterParam, getRouterParams, getSession, handleCacheHeaders, isError, isEvent, isEventHandler, isMethod, isStream, lazyEventHandler, parseCookies, promisifyNodeListener, proxyRequest, readBody, readMultipartFormData, readRawBody, send, sendError, sendNoContent, sendProxy, sendRedirect, sendStream, setCookie, setHeader, setHeaders, setResponseHeader, setResponseHeaders, setResponseStatus, toEventHandler, toNodeListener, updateSession, use, useBase, useSession, writeEarlyHints };
package/dist/index.mjs CHANGED
@@ -2,8 +2,8 @@ import { withoutTrailingSlash, withoutBase, getQuery as getQuery$1 } from 'ufo';
2
2
  import { createRouter as createRouter$1 } from 'radix3';
3
3
  import destr from 'destr';
4
4
  import { parse as parse$1, serialize } from 'cookie-es';
5
- import { unseal, defaults, seal } from 'iron-webcrypto';
6
5
  import crypto from 'uncrypto';
6
+ import { unseal, defaults, seal } from 'iron-webcrypto';
7
7
 
8
8
  function useBase(base, handler) {
9
9
  base = withoutTrailingSlash(base);
@@ -393,13 +393,7 @@ async function proxyRequest(event, target, opts = {}) {
393
393
  if (PayloadMethods.has(method)) {
394
394
  body = await readRawBody(event).catch(() => void 0);
395
395
  }
396
- const headers = /* @__PURE__ */ Object.create(null);
397
- const reqHeaders = getRequestHeaders(event);
398
- for (const name in reqHeaders) {
399
- if (!ignoredHeaders.has(name)) {
400
- headers[name] = reqHeaders[name];
401
- }
402
- }
396
+ const headers = getProxyRequestHeaders(event);
403
397
  if (opts.fetchOptions?.headers) {
404
398
  Object.assign(headers, opts.fetchOptions.headers);
405
399
  }
@@ -417,13 +411,7 @@ async function proxyRequest(event, target, opts = {}) {
417
411
  });
418
412
  }
419
413
  async function sendProxy(event, target, opts = {}) {
420
- const _fetch = opts.fetch || globalThis.fetch;
421
- if (!_fetch) {
422
- throw new Error(
423
- "fetch is not available. Try importing `node-fetch-native/polyfill` for Node.js."
424
- );
425
- }
426
- const response = await _fetch(target, {
414
+ const response = await _getFetch(opts.fetch)(target, {
427
415
  headers: opts.headers,
428
416
  ...opts.fetchOptions
429
417
  });
@@ -438,22 +426,49 @@ async function sendProxy(event, target, opts = {}) {
438
426
  }
439
427
  event.node.res.setHeader(key, value);
440
428
  }
441
- try {
442
- if (response.body) {
443
- if (opts.sendStream === false) {
444
- const data = new Uint8Array(await response.arrayBuffer());
445
- event.node.res.end(data);
446
- } else {
447
- for await (const chunk of response.body) {
448
- event.node.res.write(chunk);
449
- }
450
- event.node.res.end();
451
- }
429
+ if (response._data !== void 0) {
430
+ return response._data;
431
+ }
432
+ if (opts.sendStream === false) {
433
+ const data = new Uint8Array(await response.arrayBuffer());
434
+ return event.node.res.end(data);
435
+ }
436
+ for await (const chunk of response.body) {
437
+ event.node.res.write(chunk);
438
+ }
439
+ return event.node.res.end();
440
+ }
441
+ function getProxyRequestHeaders(event) {
442
+ const headers = /* @__PURE__ */ Object.create(null);
443
+ const reqHeaders = getRequestHeaders(event);
444
+ for (const name in reqHeaders) {
445
+ if (!ignoredHeaders.has(name)) {
446
+ headers[name] = reqHeaders[name];
452
447
  }
453
- } catch (error) {
454
- event.node.res.end();
455
- throw error;
456
448
  }
449
+ return headers;
450
+ }
451
+ function fetchWithEvent(event, req, init, options) {
452
+ return _getFetch(options?.fetch)(req, {
453
+ ...init,
454
+ // @ts-ignore (context is used for unenv and local fetch)
455
+ context: init.context || event.context,
456
+ headers: {
457
+ ...getProxyRequestHeaders(event),
458
+ ...init?.headers
459
+ }
460
+ });
461
+ }
462
+ function _getFetch(_fetch) {
463
+ if (_fetch) {
464
+ return _fetch;
465
+ }
466
+ if (globalThis.fetch) {
467
+ return globalThis.fetch;
468
+ }
469
+ throw new Error(
470
+ "fetch is not available. Try importing `node-fetch-native/polyfill` for Node.js."
471
+ );
457
472
  }
458
473
 
459
474
  const defer = typeof setImmediate !== "undefined" ? setImmediate : (fn) => fn();
@@ -1115,4 +1130,4 @@ function createRouter(opts = {}) {
1115
1130
  return router;
1116
1131
  }
1117
1132
 
1118
- export { H3Error, H3Event, H3Headers, H3Response, MIMES, appendHeader, appendHeaders, appendResponseHeader, appendResponseHeaders, assertMethod, callNodeListener, clearSession, createApp, createAppEventHandler, createError, createEvent, createRouter, defaultContentType, defineEventHandler, defineLazyEventHandler, defineNodeListener, defineNodeMiddleware, deleteCookie, dynamicEventHandler, eventHandler, fromNodeMiddleware, getCookie, getHeader, getHeaders, getMethod, getQuery, getRequestHeader, getRequestHeaders, getResponseHeader, getResponseHeaders, getResponseStatus, getResponseStatusText, getRouterParam, getRouterParams, getSession, handleCacheHeaders, isError, isEvent, isEventHandler, isMethod, isStream, lazyEventHandler, parseCookies, promisifyNodeListener, proxyRequest, readBody, readMultipartFormData, readRawBody, send, sendError, sendNoContent, sendProxy, sendRedirect, sendStream, setCookie, setHeader, setHeaders, setResponseHeader, setResponseHeaders, setResponseStatus, toEventHandler, toNodeListener, updateSession, use, useBase, useSession, writeEarlyHints };
1133
+ export { H3Error, H3Event, H3Headers, H3Response, MIMES, appendHeader, appendHeaders, appendResponseHeader, appendResponseHeaders, assertMethod, callNodeListener, clearSession, createApp, createAppEventHandler, createError, createEvent, createRouter, defaultContentType, defineEventHandler, defineLazyEventHandler, defineNodeListener, defineNodeMiddleware, deleteCookie, dynamicEventHandler, eventHandler, fetchWithEvent, fromNodeMiddleware, getCookie, getHeader, getHeaders, getMethod, getProxyRequestHeaders, getQuery, getRequestHeader, getRequestHeaders, getResponseHeader, getResponseHeaders, getResponseStatus, getResponseStatusText, getRouterParam, getRouterParams, getSession, handleCacheHeaders, isError, isEvent, isEventHandler, isMethod, isStream, lazyEventHandler, parseCookies, promisifyNodeListener, proxyRequest, readBody, readMultipartFormData, readRawBody, send, sendError, sendNoContent, sendProxy, sendRedirect, sendStream, setCookie, setHeader, setHeaders, setResponseHeader, setResponseHeaders, setResponseStatus, toEventHandler, toNodeListener, updateSession, use, useBase, useSession, writeEarlyHints };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "h3",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Tiny JavaScript Server",
5
5
  "repository": "unjs/h3",
6
6
  "license": "MIT",
@@ -22,17 +22,17 @@
22
22
  "dependencies": {
23
23
  "cookie-es": "^0.5.0",
24
24
  "destr": "^1.2.2",
25
- "iron-webcrypto": "^0.2.7",
25
+ "iron-webcrypto": "^0.4.0",
26
26
  "radix3": "^1.0.0",
27
27
  "ufo": "^1.0.1",
28
28
  "uncrypto": "^0.1.2"
29
29
  },
30
30
  "devDependencies": {
31
31
  "0x": "^5.4.1",
32
- "@types/express": "^4.17.16",
33
- "@types/node": "^18.11.18",
32
+ "@types/express": "^4.17.17",
33
+ "@types/node": "^18.13.0",
34
34
  "@types/supertest": "^2.0.12",
35
- "@vitest/coverage-c8": "^0.28.3",
35
+ "@vitest/coverage-c8": "^0.28.4",
36
36
  "autocannon": "^7.10.0",
37
37
  "changelogen": "^0.4.1",
38
38
  "connect": "^3.7.0",
@@ -43,11 +43,11 @@
43
43
  "jiti": "^1.16.2",
44
44
  "listhen": "^1.0.2",
45
45
  "node-fetch-native": "^1.0.1",
46
- "prettier": "^2.8.3",
46
+ "prettier": "^2.8.4",
47
47
  "supertest": "^6.3.3",
48
48
  "typescript": "^4.9.5",
49
49
  "unbuild": "^1.1.1",
50
- "vitest": "^0.28.3"
50
+ "vitest": "^0.28.4"
51
51
  },
52
52
  "packageManager": "pnpm@7.26.3",
53
53
  "scripts": {