h3 0.8.3 → 0.8.5

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
@@ -101,7 +101,7 @@ app.use('/1', eventHandler(() => '<h1>Hello world!</h1>'))
101
101
  .use('/2', eventHandler(() => '<h1>Goodbye!</h1>'))
102
102
 
103
103
  // Legacy middleware with 3rd argument are automatically promisified
104
- app.use(fromNodeMiddleware((req, res, next) => { req.setHeader('X-Foo', 'bar'); next() }))
104
+ app.use(fromNodeMiddleware((req, res, next) => { req.setHeader('x-foo', 'bar'); next() }))
105
105
 
106
106
  // Lazy loaded routes using { lazy: true }
107
107
  app.use('/big', () => import('./big-handler'), { lazy: true })
package/dist/index.cjs CHANGED
@@ -88,7 +88,7 @@ function sendError(event, error, debug) {
88
88
  if (h3Error.statusMessage) {
89
89
  event.res.statusMessage = h3Error.statusMessage;
90
90
  }
91
- event.res.setHeader("Content-Type", MIMES.json);
91
+ event.res.setHeader("content-type", MIMES.json);
92
92
  event.res.end(JSON.stringify(responseBody, null, 2));
93
93
  }
94
94
  function isError(input) {
@@ -133,7 +133,12 @@ function assertMethod(event, expected, allowHead) {
133
133
  }
134
134
  }
135
135
  function getRequestHeaders(event) {
136
- return event.req.headers;
136
+ const _headers = {};
137
+ for (const key in event.req.headers) {
138
+ const val = event.req.headers[key];
139
+ _headers[key] = Array.isArray(val) ? val.filter(Boolean).join(", ") : val;
140
+ }
141
+ return _headers;
137
142
  }
138
143
  const getHeaders = getRequestHeaders;
139
144
  function getRequestHeader(event, name) {
@@ -195,7 +200,7 @@ function handleCacheHeaders(event, opts) {
195
200
  if (opts.modifiedTime) {
196
201
  const modifiedTime = new Date(opts.modifiedTime);
197
202
  const ifModifiedSince = event.req.headers["if-modified-since"];
198
- event.res.setHeader("Last-Modified", modifiedTime.toUTCString());
203
+ event.res.setHeader("last-modified", modifiedTime.toUTCString());
199
204
  if (ifModifiedSince) {
200
205
  if (new Date(ifModifiedSince) >= opts.modifiedTime) {
201
206
  cacheMatched = true;
@@ -203,16 +208,16 @@ function handleCacheHeaders(event, opts) {
203
208
  }
204
209
  }
205
210
  if (opts.etag) {
206
- event.res.setHeader("Etag", opts.etag);
211
+ event.res.setHeader("etag", opts.etag);
207
212
  const ifNonMatch = event.req.headers["if-none-match"];
208
213
  if (ifNonMatch === opts.etag) {
209
214
  cacheMatched = true;
210
215
  }
211
216
  }
212
- event.res.setHeader("Cache-Control", cacheControls.join(", "));
217
+ event.res.setHeader("cache-control", cacheControls.join(", "));
213
218
  if (cacheMatched) {
214
219
  event.res.statusCode = 304;
215
- event.res.end("");
220
+ event.res.end();
216
221
  return true;
217
222
  }
218
223
  return false;
@@ -236,13 +241,13 @@ function send(event, data, type) {
236
241
  });
237
242
  }
238
243
  function defaultContentType(event, type) {
239
- if (type && !event.res.getHeader("Content-Type")) {
240
- event.res.setHeader("Content-Type", type);
244
+ if (type && !event.res.getHeader("content-type")) {
245
+ event.res.setHeader("content-type", type);
241
246
  }
242
247
  }
243
248
  function sendRedirect(event, location, code = 302) {
244
249
  event.res.statusCode = code;
245
- event.res.setHeader("Location", location);
250
+ event.res.setHeader("location", location);
246
251
  const encodedLoc = location.replace(/"/g, "%22");
247
252
  const html = `<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0; url=${encodedLoc}"></head></html>`;
248
253
  return send(event, html, MIMES.html);
@@ -290,7 +295,7 @@ function sendStream(event, data) {
290
295
  const noop = () => {
291
296
  };
292
297
  function writeEarlyHints(event, hints, cb = noop) {
293
- if (!event.res.socket && !("writeEarlyHints" in event.res)) {
298
+ if (!event.res.socket) {
294
299
  cb();
295
300
  return;
296
301
  }
@@ -299,10 +304,6 @@ function writeEarlyHints(event, hints, cb = noop) {
299
304
  }
300
305
  if (hints.link) {
301
306
  hints.link = Array.isArray(hints.link) ? hints.link : hints.link.split(",");
302
- hints.link = hints.link.map((l) => l.trim().replace(/; crossorigin/g, ""));
303
- }
304
- if ("writeEarlyHints" in event.res) {
305
- return event.res.writeEarlyHints(hints, cb);
306
307
  }
307
308
  const headers = Object.entries(hints).map((e) => [e[0].toLowerCase(), e[1]]);
308
309
  if (!headers.length) {
@@ -441,7 +442,7 @@ class H3Event {
441
442
  this.res.statusMessage = response.statusText;
442
443
  }
443
444
  if (response.redirected) {
444
- this.res.setHeader("Location", response.url);
445
+ this.res.setHeader("location", response.url);
445
446
  }
446
447
  if (!response._body) {
447
448
  return this.res.end();
package/dist/index.d.ts CHANGED
@@ -13,6 +13,9 @@ interface EventHandler<T = any> {
13
13
  (event: H3Event): EventHandlerResponse<T>;
14
14
  }
15
15
  declare type LazyEventHandler = () => EventHandler | Promise<EventHandler>;
16
+ declare type RequestHeaders = {
17
+ [name: string]: string | undefined;
18
+ };
16
19
 
17
20
  declare type NodeListener = (req: IncomingMessage, res: ServerResponse) => void;
18
21
  declare type NodePromisifiedHandler = (req: IncomingMessage, res: ServerResponse) => Promise<any>;
@@ -250,9 +253,9 @@ declare function getMethod(event: H3Event, defaultMethod?: HTTPMethod): HTTPMeth
250
253
  declare const useMethod: typeof getMethod;
251
254
  declare function isMethod(event: H3Event, expected: HTTPMethod | HTTPMethod[], allowHead?: boolean): boolean;
252
255
  declare function assertMethod(event: H3Event, expected: HTTPMethod | HTTPMethod[], allowHead?: boolean): void;
253
- declare function getRequestHeaders(event: H3Event): H3Event['req']['headers'];
256
+ declare function getRequestHeaders(event: H3Event): RequestHeaders;
254
257
  declare const getHeaders: typeof getRequestHeaders;
255
- declare function getRequestHeader(event: H3Event, name: string): H3Event['req']['headers'][string];
258
+ declare function getRequestHeader(event: H3Event, name: string): RequestHeaders[string];
256
259
  declare const getHeader: typeof getRequestHeader;
257
260
 
258
261
  declare function send(event: H3Event, data?: any, type?: string): Promise<void>;
@@ -285,4 +288,4 @@ interface CreateRouterOptions {
285
288
  }
286
289
  declare function createRouter(opts?: CreateRouterOptions): Router;
287
290
 
288
- 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, 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 };
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 };
package/dist/index.mjs CHANGED
@@ -86,7 +86,7 @@ function sendError(event, error, debug) {
86
86
  if (h3Error.statusMessage) {
87
87
  event.res.statusMessage = h3Error.statusMessage;
88
88
  }
89
- event.res.setHeader("Content-Type", MIMES.json);
89
+ event.res.setHeader("content-type", MIMES.json);
90
90
  event.res.end(JSON.stringify(responseBody, null, 2));
91
91
  }
92
92
  function isError(input) {
@@ -131,7 +131,12 @@ function assertMethod(event, expected, allowHead) {
131
131
  }
132
132
  }
133
133
  function getRequestHeaders(event) {
134
- return event.req.headers;
134
+ const _headers = {};
135
+ for (const key in event.req.headers) {
136
+ const val = event.req.headers[key];
137
+ _headers[key] = Array.isArray(val) ? val.filter(Boolean).join(", ") : val;
138
+ }
139
+ return _headers;
135
140
  }
136
141
  const getHeaders = getRequestHeaders;
137
142
  function getRequestHeader(event, name) {
@@ -193,7 +198,7 @@ function handleCacheHeaders(event, opts) {
193
198
  if (opts.modifiedTime) {
194
199
  const modifiedTime = new Date(opts.modifiedTime);
195
200
  const ifModifiedSince = event.req.headers["if-modified-since"];
196
- event.res.setHeader("Last-Modified", modifiedTime.toUTCString());
201
+ event.res.setHeader("last-modified", modifiedTime.toUTCString());
197
202
  if (ifModifiedSince) {
198
203
  if (new Date(ifModifiedSince) >= opts.modifiedTime) {
199
204
  cacheMatched = true;
@@ -201,16 +206,16 @@ function handleCacheHeaders(event, opts) {
201
206
  }
202
207
  }
203
208
  if (opts.etag) {
204
- event.res.setHeader("Etag", opts.etag);
209
+ event.res.setHeader("etag", opts.etag);
205
210
  const ifNonMatch = event.req.headers["if-none-match"];
206
211
  if (ifNonMatch === opts.etag) {
207
212
  cacheMatched = true;
208
213
  }
209
214
  }
210
- event.res.setHeader("Cache-Control", cacheControls.join(", "));
215
+ event.res.setHeader("cache-control", cacheControls.join(", "));
211
216
  if (cacheMatched) {
212
217
  event.res.statusCode = 304;
213
- event.res.end("");
218
+ event.res.end();
214
219
  return true;
215
220
  }
216
221
  return false;
@@ -234,13 +239,13 @@ function send(event, data, type) {
234
239
  });
235
240
  }
236
241
  function defaultContentType(event, type) {
237
- if (type && !event.res.getHeader("Content-Type")) {
238
- event.res.setHeader("Content-Type", type);
242
+ if (type && !event.res.getHeader("content-type")) {
243
+ event.res.setHeader("content-type", type);
239
244
  }
240
245
  }
241
246
  function sendRedirect(event, location, code = 302) {
242
247
  event.res.statusCode = code;
243
- event.res.setHeader("Location", location);
248
+ event.res.setHeader("location", location);
244
249
  const encodedLoc = location.replace(/"/g, "%22");
245
250
  const html = `<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0; url=${encodedLoc}"></head></html>`;
246
251
  return send(event, html, MIMES.html);
@@ -288,7 +293,7 @@ function sendStream(event, data) {
288
293
  const noop = () => {
289
294
  };
290
295
  function writeEarlyHints(event, hints, cb = noop) {
291
- if (!event.res.socket && !("writeEarlyHints" in event.res)) {
296
+ if (!event.res.socket) {
292
297
  cb();
293
298
  return;
294
299
  }
@@ -297,10 +302,6 @@ function writeEarlyHints(event, hints, cb = noop) {
297
302
  }
298
303
  if (hints.link) {
299
304
  hints.link = Array.isArray(hints.link) ? hints.link : hints.link.split(",");
300
- hints.link = hints.link.map((l) => l.trim().replace(/; crossorigin/g, ""));
301
- }
302
- if ("writeEarlyHints" in event.res) {
303
- return event.res.writeEarlyHints(hints, cb);
304
305
  }
305
306
  const headers = Object.entries(hints).map((e) => [e[0].toLowerCase(), e[1]]);
306
307
  if (!headers.length) {
@@ -439,7 +440,7 @@ class H3Event {
439
440
  this.res.statusMessage = response.statusText;
440
441
  }
441
442
  if (response.redirected) {
442
- this.res.setHeader("Location", response.url);
443
+ this.res.setHeader("location", response.url);
443
444
  }
444
445
  if (!response._body) {
445
446
  return this.res.end();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "h3",
3
- "version": "0.8.3",
3
+ "version": "0.8.5",
4
4
  "description": "Tiny JavaScript Server",
5
5
  "repository": "unjs/h3",
6
6
  "license": "MIT",
@@ -21,7 +21,7 @@
21
21
  ],
22
22
  "dependencies": {
23
23
  "cookie-es": "^0.5.0",
24
- "destr": "^1.1.1",
24
+ "destr": "^1.2.0",
25
25
  "radix3": "^0.2.1",
26
26
  "ufo": "^0.8.6"
27
27
  },
@@ -52,7 +52,7 @@
52
52
  "lint": "eslint --ext ts,mjs,cjs .",
53
53
  "play": "jiti ./playground/index.ts",
54
54
  "profile": "0x -o -D .profile -P 'autocannon -c 100 -p 10 -d 40 http://localhost:$PORT' ./playground/server.cjs",
55
- "release": "pnpm test && pnpm test && pnpm build && changelogen --release && pnpm publish && git push --follow-tags",
55
+ "release": "pnpm test && pnpm build && changelogen --release && pnpm publish && git push --follow-tags",
56
56
  "test": "pnpm lint && vitest run --coverage"
57
57
  }
58
58
  }