h3 1.5.0 → 1.6.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
@@ -1,13 +1,13 @@
1
- [![npm downloads](https://img.shields.io/npm/dm/h3.svg?style=flat-square)](https://npmjs.com/package/h3)
2
- [![version](https://img.shields.io/npm/v/h3/latest.svg?style=flat-square)](https://npmjs.com/package/h3)
3
- [![bundlephobia](https://img.shields.io/bundlephobia/min/h3/latest.svg?style=flat-square)](https://bundlephobia.com/result?p=h3)
4
- [![build status](https://img.shields.io/github/actions/workflow/status/unjs/h3/ci.yml?branch=main&style=flat-square)](https://github.com/unjs/h3/actions)
5
- [![coverage](https://img.shields.io/codecov/c/gh/unjs/h3/main?style=flat-square)](https://codecov.io/gh/unjs/h3)
6
- [![jsDocs.io](https://img.shields.io/badge/jsDocs.io-reference-blue?style=flat-square)](https://www.jsdocs.io/package/h3)
1
+ # H3
7
2
 
8
- > H3 is a minimal h(ttp) framework built for high performance and portability
3
+ [![npm version][npm-version-src]][npm-version-href]
4
+ [![npm downloads][npm-downloads-src]][npm-downloads-href]
5
+ [![bundle][bundle-src]][bundle-href]
6
+ [![Codecov][codecov-src]][codecov-href]
7
+ [![License][license-src]][license-href]
8
+ [![JSDocs][jsdocs-src]][jsdocs-href]
9
9
 
10
- <!-- ![h3 - Tiny JavaScript Server](.github/banner.svg) -->
10
+ H3 is a minimal h(ttp) framework built for high performance and portability.
11
11
 
12
12
  ## Features
13
13
 
@@ -179,6 +179,9 @@ H3 has a concept of composable utilities that accept `event` (from `eventHandler
179
179
  - `isCorsOriginAllowed(event)`
180
180
  - `appendCorsHeaders(event, options)` (see [h3-cors](https://github.com/NozomuIkuta/h3-cors) for more detail about options)
181
181
  - `appendCorsPreflightHeaders(event, options)` (see [h3-cors](https://github.com/NozomuIkuta/h3-cors) for more detail about options)
182
+ - `getRequestHost(event)`
183
+ - `getRequestProtocol(event)`
184
+ - `getRequestURL(event)`
182
185
 
183
186
  👉 You can learn more about usage in [JSDocs Documentation](https://www.jsdocs.io/package/h3#package-functions).
184
187
 
@@ -200,3 +203,18 @@ PRs are welcome to add your packages.
200
203
  ## License
201
204
 
202
205
  MIT
206
+
207
+ <!-- Badges -->
208
+
209
+ [npm-version-src]: https://img.shields.io/npm/v/h3?style=flat&colorA=18181B&colorB=F0DB4F
210
+ [npm-version-href]: https://npmjs.com/package/h3
211
+ [npm-downloads-src]: https://img.shields.io/npm/dm/h3?style=flat&colorA=18181B&colorB=F0DB4F
212
+ [npm-downloads-href]: https://npmjs.com/package/h3
213
+ [codecov-src]: https://img.shields.io/codecov/c/gh/unjs/h3/main?style=flat&colorA=18181B&colorB=F0DB4F
214
+ [codecov-href]: https://codecov.io/gh/unjs/h3
215
+ [bundle-src]: https://img.shields.io/bundlephobia/minzip/h3?style=flat&colorA=18181B&colorB=F0DB4F
216
+ [bundle-href]: https://bundlephobia.com/result?p=h3
217
+ [license-src]: https://img.shields.io/github/license/unjs/h3.svg?style=flat&colorA=18181B&colorB=F0DB4F
218
+ [license-href]: https://github.com/unjs/h3/blob/main/LICENSE
219
+ [jsdocs-src]: https://img.shields.io/badge/jsDocs.io-reference-18181B?style=flat&colorA=18181B&colorB=F0DB4F
220
+ [jsdocs-href]: https://www.jsdocs.io/package/h3
package/dist/index.cjs CHANGED
@@ -248,6 +248,24 @@ function getRequestHeader(event, name) {
248
248
  return value;
249
249
  }
250
250
  const getHeader = getRequestHeader;
251
+ function getRequestHost(event) {
252
+ const xForwardedHost = event.node.req.headers["x-forwarded-host"];
253
+ if (xForwardedHost) {
254
+ return xForwardedHost;
255
+ }
256
+ return event.node.req.headers.host || "localhost";
257
+ }
258
+ function getRequestProtocol(event) {
259
+ if (event.node.req.headers["x-forwarded-proto"] === "https") {
260
+ return "https";
261
+ }
262
+ return event.node.req.connection.encrypted ? "https" : "http";
263
+ }
264
+ function getRequestURL(event) {
265
+ const host = getRequestHost(event);
266
+ const protocol = getRequestProtocol(event);
267
+ return new URL(event.path || "/", `${protocol}://${host}`);
268
+ }
251
269
 
252
270
  const RawBodySymbol = Symbol.for("h3RawBody");
253
271
  const ParsedBodySymbol = Symbol.for("h3ParsedBody");
@@ -380,7 +398,6 @@ function deleteCookie(event, name, serializeOptions) {
380
398
  maxAge: 0
381
399
  });
382
400
  }
383
-
384
401
  function splitCookiesString(cookiesString) {
385
402
  if (typeof cookiesString !== "string") {
386
403
  return [];
@@ -528,8 +545,7 @@ function getProxyRequestHeaders(event) {
528
545
  function fetchWithEvent(event, req, init, options) {
529
546
  return _getFetch(options?.fetch)(req, {
530
547
  ...init,
531
- // @ts-ignore (context is used for unenv and local fetch)
532
- context: init.context || event.context,
548
+ context: init?.context || event.context,
533
549
  headers: {
534
550
  ...getProxyRequestHeaders(event),
535
551
  ...init?.headers
@@ -1422,6 +1438,9 @@ exports.getProxyRequestHeaders = getProxyRequestHeaders;
1422
1438
  exports.getQuery = getQuery;
1423
1439
  exports.getRequestHeader = getRequestHeader;
1424
1440
  exports.getRequestHeaders = getRequestHeaders;
1441
+ exports.getRequestHost = getRequestHost;
1442
+ exports.getRequestProtocol = getRequestProtocol;
1443
+ exports.getRequestURL = getRequestURL;
1425
1444
  exports.getResponseHeader = getResponseHeader;
1426
1445
  exports.getResponseHeaders = getResponseHeaders;
1427
1446
  exports.getResponseStatus = getResponseStatus;
@@ -1458,6 +1477,7 @@ exports.setHeaders = setHeaders;
1458
1477
  exports.setResponseHeader = setResponseHeader;
1459
1478
  exports.setResponseHeaders = setResponseHeaders;
1460
1479
  exports.setResponseStatus = setResponseStatus;
1480
+ exports.splitCookiesString = splitCookiesString;
1461
1481
  exports.toEventHandler = toEventHandler;
1462
1482
  exports.toNodeListener = toNodeListener;
1463
1483
  exports.unsealSession = unsealSession;
package/dist/index.d.ts CHANGED
@@ -27,7 +27,7 @@ interface SessionConfig {
27
27
  }
28
28
  declare function useSession<T extends SessionDataT = SessionDataT>(event: H3Event, config: SessionConfig): Promise<{
29
29
  readonly id: string | undefined;
30
- readonly data: SessionDataT;
30
+ readonly data: T;
31
31
  update: (update: SessionUpdate<T>) => Promise<any>;
32
32
  clear: () => Promise<any>;
33
33
  }>;
@@ -36,7 +36,7 @@ type SessionUpdate<T extends SessionDataT = SessionDataT> = Partial<SessionData<
36
36
  declare function updateSession<T extends SessionDataT = SessionDataT>(event: H3Event, config: SessionConfig, update?: SessionUpdate<T>): Promise<Session<T>>;
37
37
  declare function sealSession<T extends SessionDataT = SessionDataT>(event: H3Event, config: SessionConfig): Promise<string>;
38
38
  declare function unsealSession(_event: H3Event, config: SessionConfig, sealed: string): Promise<Partial<Session<SessionDataT>>>;
39
- declare function clearSession(event: H3Event, config: SessionConfig): Promise<void>;
39
+ declare function clearSession(event: H3Event, config: Partial<SessionConfig>): Promise<void>;
40
40
 
41
41
  type HTTPMethod = "GET" | "HEAD" | "PATCH" | "POST" | "PUT" | "DELETE" | "CONNECT" | "OPTIONS" | "TRACE";
42
42
  type Encoding = false | "ascii" | "utf8" | "utf-8" | "utf16le" | "ucs2" | "ucs-2" | "base64" | "latin1" | "binary" | "hex";
@@ -231,7 +231,7 @@ declare function readRawBody<E extends Encoding = "utf8">(event: H3Event, encodi
231
231
  * @return {*} The `Object`, `Array`, `String`, `Number`, `Boolean`, or `null` value corresponding to the request JSON body
232
232
  *
233
233
  * ```ts
234
- * const body = await useBody(req)
234
+ * const body = await readBody(req)
235
235
  * ```
236
236
  */
237
237
  declare function readBody<T = any>(event: H3Event): Promise<T>;
@@ -270,7 +270,7 @@ declare function parseCookies(event: H3Event): Record<string, string>;
270
270
  * @param name Name of the cookie to get
271
271
  * @returns {*} Value of the cookie (String or undefined)
272
272
  * ```ts
273
- * const authorization = useCookie(request, 'Authorization')
273
+ * const authorization = getCookie(request, 'Authorization')
274
274
  * ```
275
275
  */
276
276
  declare function getCookie(event: H3Event, name: string): string | undefined;
@@ -295,6 +295,16 @@ declare function setCookie(event: H3Event, name: string, value: string, serializ
295
295
  * ```
296
296
  */
297
297
  declare function deleteCookie(event: H3Event, name: string, serializeOptions?: CookieSerializeOptions): void;
298
+ /**
299
+ * Set-Cookie header field-values are sometimes comma joined in one string. This splits them without choking on commas
300
+ * that are within a single set-cookie field-value, such as in the Expires portion.
301
+ * This is uncommon, but explicitly allowed - see https://tools.ietf.org/html/rfc2616#section-4.2
302
+ * Node.js does this for every header *except* set-cookie - see https://github.com/nodejs/node/blob/d5e363b77ebaf1caf67cd7528224b651c86815c1/lib/_http_incoming.js#L128
303
+ * Based on: https://github.com/google/j2objc/commit/16820fdbc8f76ca0c33472810ce0cb03d20efe25
304
+ * Credits to: https://github.com/tomball for original and https://github.com/chrusart for JavaScript implementation
305
+ * @source https://github.com/nfriedly/set-cookie-parser/blob/3eab8b7d5d12c8ed87832532861c1a35520cf5b3/lib/set-cookie.js#L144
306
+ */
307
+ declare function splitCookiesString(cookiesString: string): string[];
298
308
 
299
309
  interface ProxyOptions {
300
310
  headers?: RequestHeaders | HeadersInit;
@@ -307,7 +317,9 @@ interface ProxyOptions {
307
317
  declare function proxyRequest(event: H3Event, target: string, opts?: ProxyOptions): Promise<any>;
308
318
  declare function sendProxy(event: H3Event, target: string, opts?: ProxyOptions): Promise<any>;
309
319
  declare function getProxyRequestHeaders(event: H3Event): any;
310
- declare function fetchWithEvent(event: H3Event, req: RequestInfo | URL, init?: RequestInit, options?: {
320
+ declare function fetchWithEvent(event: H3Event, req: RequestInfo | URL, init?: RequestInit & {
321
+ context?: H3EventContext;
322
+ }, options?: {
311
323
  fetch: typeof fetch;
312
324
  }): Promise<Response>;
313
325
 
@@ -321,6 +333,9 @@ declare function getRequestHeaders(event: H3Event): RequestHeaders;
321
333
  declare const getHeaders: typeof getRequestHeaders;
322
334
  declare function getRequestHeader(event: H3Event, name: string): RequestHeaders[string];
323
335
  declare const getHeader: typeof getRequestHeader;
336
+ declare function getRequestHost(event: H3Event): string;
337
+ declare function getRequestProtocol(event: H3Event): "https" | "http";
338
+ declare function getRequestURL(event: H3Event): URL;
324
339
 
325
340
  declare function send(event: H3Event, data?: any, type?: string): Promise<void>;
326
341
  /**
@@ -384,4 +399,4 @@ interface CreateRouterOptions {
384
399
  }
385
400
  declare function createRouter(opts?: CreateRouterOptions): Router;
386
401
 
387
- export { AddRouteShortcuts, App, AppOptions, AppUse, CacheConditions, CreateRouterOptions, DynamicEventHandler, Encoding, EventHandler, EventHandlerResponse, H3CorsOptions, H3Error, H3Event, H3EventContext, H3Headers, H3Response, HTTPMethod, InputLayer, InputStack, Layer, LazyEventHandler, MIMES, Matcher, MultiPartData, NodeEventContext, NodeListener, NodeMiddleware, NodePromisifiedHandler, ProxyOptions, RequestHeaders, Router, RouterMethod, RouterUse, Session, SessionConfig, SessionData, Stack, appendCorsHeaders, appendCorsPreflightHeaders, 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, handleCors, isCorsOriginAllowed, isError, isEvent, isEventHandler, isMethod, isPreflightRequest, isStream, lazyEventHandler, parseCookies, promisifyNodeListener, proxyRequest, readBody, readMultipartFormData, readRawBody, sealSession, send, sendError, sendNoContent, sendProxy, sendRedirect, sendStream, setCookie, setHeader, setHeaders, setResponseHeader, setResponseHeaders, setResponseStatus, toEventHandler, toNodeListener, unsealSession, updateSession, use, useBase, useSession, writeEarlyHints };
402
+ export { AddRouteShortcuts, App, AppOptions, AppUse, CacheConditions, CreateRouterOptions, DynamicEventHandler, Encoding, EventHandler, EventHandlerResponse, H3CorsOptions, H3Error, H3Event, H3EventContext, H3Headers, H3Response, HTTPMethod, InputLayer, InputStack, Layer, LazyEventHandler, MIMES, Matcher, MultiPartData, NodeEventContext, NodeListener, NodeMiddleware, NodePromisifiedHandler, ProxyOptions, RequestHeaders, Router, RouterMethod, RouterUse, Session, SessionConfig, SessionData, Stack, appendCorsHeaders, appendCorsPreflightHeaders, 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, getRequestHost, getRequestProtocol, getRequestURL, getResponseHeader, getResponseHeaders, getResponseStatus, getResponseStatusText, getRouterParam, getRouterParams, getSession, handleCacheHeaders, handleCors, isCorsOriginAllowed, isError, isEvent, isEventHandler, isMethod, isPreflightRequest, isStream, lazyEventHandler, parseCookies, promisifyNodeListener, proxyRequest, readBody, readMultipartFormData, readRawBody, sealSession, send, sendError, sendNoContent, sendProxy, sendRedirect, sendStream, setCookie, setHeader, setHeaders, setResponseHeader, setResponseHeaders, setResponseStatus, splitCookiesString, toEventHandler, toNodeListener, unsealSession, updateSession, use, useBase, useSession, writeEarlyHints };
package/dist/index.mjs CHANGED
@@ -246,6 +246,24 @@ function getRequestHeader(event, name) {
246
246
  return value;
247
247
  }
248
248
  const getHeader = getRequestHeader;
249
+ function getRequestHost(event) {
250
+ const xForwardedHost = event.node.req.headers["x-forwarded-host"];
251
+ if (xForwardedHost) {
252
+ return xForwardedHost;
253
+ }
254
+ return event.node.req.headers.host || "localhost";
255
+ }
256
+ function getRequestProtocol(event) {
257
+ if (event.node.req.headers["x-forwarded-proto"] === "https") {
258
+ return "https";
259
+ }
260
+ return event.node.req.connection.encrypted ? "https" : "http";
261
+ }
262
+ function getRequestURL(event) {
263
+ const host = getRequestHost(event);
264
+ const protocol = getRequestProtocol(event);
265
+ return new URL(event.path || "/", `${protocol}://${host}`);
266
+ }
249
267
 
250
268
  const RawBodySymbol = Symbol.for("h3RawBody");
251
269
  const ParsedBodySymbol = Symbol.for("h3ParsedBody");
@@ -378,7 +396,6 @@ function deleteCookie(event, name, serializeOptions) {
378
396
  maxAge: 0
379
397
  });
380
398
  }
381
-
382
399
  function splitCookiesString(cookiesString) {
383
400
  if (typeof cookiesString !== "string") {
384
401
  return [];
@@ -526,8 +543,7 @@ function getProxyRequestHeaders(event) {
526
543
  function fetchWithEvent(event, req, init, options) {
527
544
  return _getFetch(options?.fetch)(req, {
528
545
  ...init,
529
- // @ts-ignore (context is used for unenv and local fetch)
530
- context: init.context || event.context,
546
+ context: init?.context || event.context,
531
547
  headers: {
532
548
  ...getProxyRequestHeaders(event),
533
549
  ...init?.headers
@@ -1383,4 +1399,4 @@ function createRouter(opts = {}) {
1383
1399
  return router;
1384
1400
  }
1385
1401
 
1386
- export { H3Error, H3Event, H3Headers, H3Response, MIMES, appendCorsHeaders, appendCorsPreflightHeaders, 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, handleCors, isCorsOriginAllowed, isError, isEvent, isEventHandler, isMethod, isPreflightRequest, isStream, lazyEventHandler, parseCookies, promisifyNodeListener, proxyRequest, readBody, readMultipartFormData, readRawBody, sealSession, send, sendError, sendNoContent, sendProxy, sendRedirect, sendStream, setCookie, setHeader, setHeaders, setResponseHeader, setResponseHeaders, setResponseStatus, toEventHandler, toNodeListener, unsealSession, updateSession, use, useBase, useSession, writeEarlyHints };
1402
+ export { H3Error, H3Event, H3Headers, H3Response, MIMES, appendCorsHeaders, appendCorsPreflightHeaders, 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, getRequestHost, getRequestProtocol, getRequestURL, getResponseHeader, getResponseHeaders, getResponseStatus, getResponseStatusText, getRouterParam, getRouterParams, getSession, handleCacheHeaders, handleCors, isCorsOriginAllowed, isError, isEvent, isEventHandler, isMethod, isPreflightRequest, isStream, lazyEventHandler, parseCookies, promisifyNodeListener, proxyRequest, readBody, readMultipartFormData, readRawBody, sealSession, send, sendError, sendNoContent, sendProxy, sendRedirect, sendStream, setCookie, setHeader, setHeaders, setResponseHeader, setResponseHeaders, setResponseStatus, splitCookiesString, toEventHandler, toNodeListener, unsealSession, updateSession, use, useBase, useSession, writeEarlyHints };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "h3",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "Tiny JavaScript Server",
5
5
  "repository": "unjs/h3",
6
6
  "license": "MIT",
@@ -25,32 +25,32 @@
25
25
  "destr": "^1.2.2",
26
26
  "iron-webcrypto": "^0.5.0",
27
27
  "radix3": "^1.0.0",
28
- "ufo": "^1.1.0",
28
+ "ufo": "^1.1.1",
29
29
  "uncrypto": "^0.1.2"
30
30
  },
31
31
  "devDependencies": {
32
- "0x": "^5.4.1",
32
+ "0x": "^5.5.0",
33
33
  "@types/express": "^4.17.17",
34
- "@types/node": "^18.13.0",
34
+ "@types/node": "^18.15.0",
35
35
  "@types/supertest": "^2.0.12",
36
- "@vitest/coverage-c8": "^0.28.5",
36
+ "@vitest/coverage-c8": "^0.29.2",
37
37
  "autocannon": "^7.10.0",
38
- "changelogen": "^0.4.1",
38
+ "changelogen": "^0.5.1",
39
39
  "connect": "^3.7.0",
40
- "eslint": "^8.34.0",
40
+ "eslint": "^8.35.0",
41
41
  "eslint-config-unjs": "^0.1.0",
42
42
  "express": "^4.18.2",
43
43
  "get-port": "^6.1.2",
44
- "jiti": "^1.17.0",
45
- "listhen": "^1.0.2",
44
+ "jiti": "^1.17.2",
45
+ "listhen": "^1.0.3",
46
46
  "node-fetch-native": "^1.0.2",
47
47
  "prettier": "^2.8.4",
48
48
  "supertest": "^6.3.3",
49
49
  "typescript": "^4.9.5",
50
- "unbuild": "^1.1.1",
51
- "vitest": "^0.28.5"
50
+ "unbuild": "^1.1.2",
51
+ "vitest": "^0.29.2"
52
52
  },
53
- "packageManager": "pnpm@7.27.0",
53
+ "packageManager": "pnpm@7.29.0",
54
54
  "scripts": {
55
55
  "build": "unbuild",
56
56
  "dev": "vitest",