h3 0.8.6 → 1.0.1
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/LICENSE +1 -1
- package/README.md +5 -2
- package/dist/index.cjs +153 -109
- package/dist/index.d.ts +26 -30
- package/dist/index.mjs +153 -104
- package/package.json +23 -23
package/dist/index.mjs
CHANGED
|
@@ -9,8 +9,8 @@ function useBase(base, handler) {
|
|
|
9
9
|
return handler;
|
|
10
10
|
}
|
|
11
11
|
return eventHandler((event) => {
|
|
12
|
-
event.req.originalUrl = event.req.originalUrl || event.req.url || "/";
|
|
13
|
-
event.req.url = withoutBase(event.req.url || "/", base);
|
|
12
|
+
event.node.req.originalUrl = event.node.req.originalUrl || event.node.req.url || "/";
|
|
13
|
+
event.node.req.url = withoutBase(event.node.req.url || "/", base);
|
|
14
14
|
return handler(event);
|
|
15
15
|
});
|
|
16
16
|
}
|
|
@@ -80,7 +80,7 @@ function createError(input) {
|
|
|
80
80
|
return err;
|
|
81
81
|
}
|
|
82
82
|
function sendError(event, error, debug) {
|
|
83
|
-
if (event.res.writableEnded) {
|
|
83
|
+
if (event.node.res.writableEnded) {
|
|
84
84
|
return;
|
|
85
85
|
}
|
|
86
86
|
const h3Error = isError(error) ? error : createError(error);
|
|
@@ -93,27 +93,26 @@ function sendError(event, error, debug) {
|
|
|
93
93
|
if (debug) {
|
|
94
94
|
responseBody.stack = (h3Error.stack || "").split("\n").map((l) => l.trim());
|
|
95
95
|
}
|
|
96
|
-
if (event.res.writableEnded) {
|
|
96
|
+
if (event.node.res.writableEnded) {
|
|
97
97
|
return;
|
|
98
98
|
}
|
|
99
|
-
const _code = parseInt(h3Error.statusCode);
|
|
99
|
+
const _code = Number.parseInt(h3Error.statusCode);
|
|
100
100
|
if (_code) {
|
|
101
|
-
event.res.statusCode = _code;
|
|
101
|
+
event.node.res.statusCode = _code;
|
|
102
102
|
}
|
|
103
103
|
if (h3Error.statusMessage) {
|
|
104
|
-
event.res.statusMessage = h3Error.statusMessage;
|
|
104
|
+
event.node.res.statusMessage = h3Error.statusMessage;
|
|
105
105
|
}
|
|
106
|
-
event.res.setHeader("content-type", MIMES.json);
|
|
107
|
-
event.res.end(JSON.stringify(responseBody,
|
|
106
|
+
event.node.res.setHeader("content-type", MIMES.json);
|
|
107
|
+
event.node.res.end(JSON.stringify(responseBody, void 0, 2));
|
|
108
108
|
}
|
|
109
109
|
function isError(input) {
|
|
110
110
|
return input?.constructor?.__h3_error__ === true;
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
function getQuery(event) {
|
|
114
|
-
return getQuery$1(event.req.url || "");
|
|
114
|
+
return getQuery$1(event.node.req.url || "");
|
|
115
115
|
}
|
|
116
|
-
const useQuery = getQuery;
|
|
117
116
|
function getRouterParams(event) {
|
|
118
117
|
return event.context.params || {};
|
|
119
118
|
}
|
|
@@ -122,9 +121,8 @@ function getRouterParam(event, name) {
|
|
|
122
121
|
return params[name];
|
|
123
122
|
}
|
|
124
123
|
function getMethod(event, defaultMethod = "GET") {
|
|
125
|
-
return (event.req.method || defaultMethod).toUpperCase();
|
|
124
|
+
return (event.node.req.method || defaultMethod).toUpperCase();
|
|
126
125
|
}
|
|
127
|
-
const useMethod = getMethod;
|
|
128
126
|
function isMethod(event, expected, allowHead) {
|
|
129
127
|
const method = getMethod(event);
|
|
130
128
|
if (allowHead && method === "HEAD") {
|
|
@@ -149,8 +147,8 @@ function assertMethod(event, expected, allowHead) {
|
|
|
149
147
|
}
|
|
150
148
|
function getRequestHeaders(event) {
|
|
151
149
|
const _headers = {};
|
|
152
|
-
for (const key in event.req.headers) {
|
|
153
|
-
const val = event.req.headers[key];
|
|
150
|
+
for (const key in event.node.req.headers) {
|
|
151
|
+
const val = event.node.req.headers[key];
|
|
154
152
|
_headers[key] = Array.isArray(val) ? val.filter(Boolean).join(", ") : val;
|
|
155
153
|
}
|
|
156
154
|
return _headers;
|
|
@@ -165,22 +163,22 @@ const getHeader = getRequestHeader;
|
|
|
165
163
|
|
|
166
164
|
const RawBodySymbol = Symbol.for("h3RawBody");
|
|
167
165
|
const ParsedBodySymbol = Symbol.for("h3ParsedBody");
|
|
168
|
-
const PayloadMethods = ["PATCH", "POST", "PUT", "DELETE"];
|
|
169
|
-
function readRawBody(event, encoding = "
|
|
170
|
-
assertMethod(event, PayloadMethods);
|
|
171
|
-
if (RawBodySymbol in event.req) {
|
|
172
|
-
const promise2 = Promise.resolve(event.req[RawBodySymbol]);
|
|
166
|
+
const PayloadMethods$1 = ["PATCH", "POST", "PUT", "DELETE"];
|
|
167
|
+
function readRawBody(event, encoding = "utf8") {
|
|
168
|
+
assertMethod(event, PayloadMethods$1);
|
|
169
|
+
if (RawBodySymbol in event.node.req) {
|
|
170
|
+
const promise2 = Promise.resolve(event.node.req[RawBodySymbol]);
|
|
173
171
|
return encoding ? promise2.then((buff) => buff.toString(encoding)) : promise2;
|
|
174
172
|
}
|
|
175
|
-
if ("body" in event.req) {
|
|
176
|
-
return Promise.resolve(event.req.body);
|
|
173
|
+
if ("body" in event.node.req) {
|
|
174
|
+
return Promise.resolve(event.node.req.body);
|
|
177
175
|
}
|
|
178
|
-
if (!parseInt(event.req.headers["content-length"] || "")) {
|
|
176
|
+
if (!Number.parseInt(event.node.req.headers["content-length"] || "")) {
|
|
179
177
|
return Promise.resolve(void 0);
|
|
180
178
|
}
|
|
181
|
-
const promise = event.req[RawBodySymbol] = new Promise((resolve, reject) => {
|
|
179
|
+
const promise = event.node.req[RawBodySymbol] = new Promise((resolve, reject) => {
|
|
182
180
|
const bodyData = [];
|
|
183
|
-
event.req.on("error", (err) => {
|
|
181
|
+
event.node.req.on("error", (err) => {
|
|
184
182
|
reject(err);
|
|
185
183
|
}).on("data", (chunk) => {
|
|
186
184
|
bodyData.push(chunk);
|
|
@@ -190,49 +188,45 @@ function readRawBody(event, encoding = "utf-8") {
|
|
|
190
188
|
});
|
|
191
189
|
return encoding ? promise.then((buff) => buff.toString(encoding)) : promise;
|
|
192
190
|
}
|
|
193
|
-
const useRawBody = readRawBody;
|
|
194
191
|
async function readBody(event) {
|
|
195
|
-
if (ParsedBodySymbol in event.req) {
|
|
196
|
-
return event.req[ParsedBodySymbol];
|
|
192
|
+
if (ParsedBodySymbol in event.node.req) {
|
|
193
|
+
return event.node.req[ParsedBodySymbol];
|
|
197
194
|
}
|
|
198
195
|
const body = await readRawBody(event);
|
|
199
|
-
if (event.req.headers["content-type"] === "application/x-www-form-urlencoded") {
|
|
196
|
+
if (event.node.req.headers["content-type"] === "application/x-www-form-urlencoded") {
|
|
200
197
|
const parsedForm = Object.fromEntries(new URLSearchParams(body));
|
|
201
198
|
return parsedForm;
|
|
202
199
|
}
|
|
203
200
|
const json = destr(body);
|
|
204
|
-
event.req[ParsedBodySymbol] = json;
|
|
201
|
+
event.node.req[ParsedBodySymbol] = json;
|
|
205
202
|
return json;
|
|
206
203
|
}
|
|
207
|
-
const useBody = readBody;
|
|
208
204
|
|
|
209
205
|
function handleCacheHeaders(event, opts) {
|
|
210
|
-
const cacheControls = ["public"
|
|
206
|
+
const cacheControls = ["public", ...opts.cacheControls || []];
|
|
211
207
|
let cacheMatched = false;
|
|
212
208
|
if (opts.maxAge !== void 0) {
|
|
213
209
|
cacheControls.push(`max-age=${+opts.maxAge}`, `s-maxage=${+opts.maxAge}`);
|
|
214
210
|
}
|
|
215
211
|
if (opts.modifiedTime) {
|
|
216
212
|
const modifiedTime = new Date(opts.modifiedTime);
|
|
217
|
-
const ifModifiedSince = event.req.headers["if-modified-since"];
|
|
218
|
-
event.res.setHeader("last-modified", modifiedTime.toUTCString());
|
|
219
|
-
if (ifModifiedSince) {
|
|
220
|
-
|
|
221
|
-
cacheMatched = true;
|
|
222
|
-
}
|
|
213
|
+
const ifModifiedSince = event.node.req.headers["if-modified-since"];
|
|
214
|
+
event.node.res.setHeader("last-modified", modifiedTime.toUTCString());
|
|
215
|
+
if (ifModifiedSince && new Date(ifModifiedSince) >= opts.modifiedTime) {
|
|
216
|
+
cacheMatched = true;
|
|
223
217
|
}
|
|
224
218
|
}
|
|
225
219
|
if (opts.etag) {
|
|
226
|
-
event.res.setHeader("etag", opts.etag);
|
|
227
|
-
const ifNonMatch = event.req.headers["if-none-match"];
|
|
220
|
+
event.node.res.setHeader("etag", opts.etag);
|
|
221
|
+
const ifNonMatch = event.node.req.headers["if-none-match"];
|
|
228
222
|
if (ifNonMatch === opts.etag) {
|
|
229
223
|
cacheMatched = true;
|
|
230
224
|
}
|
|
231
225
|
}
|
|
232
|
-
event.res.setHeader("cache-control", cacheControls.join(", "));
|
|
226
|
+
event.node.res.setHeader("cache-control", cacheControls.join(", "));
|
|
233
227
|
if (cacheMatched) {
|
|
234
|
-
event.res.statusCode = 304;
|
|
235
|
-
event.res.end();
|
|
228
|
+
event.node.res.statusCode = 304;
|
|
229
|
+
event.node.res.end();
|
|
236
230
|
return true;
|
|
237
231
|
}
|
|
238
232
|
return false;
|
|
@@ -250,51 +244,55 @@ function send(event, data, type) {
|
|
|
250
244
|
}
|
|
251
245
|
return new Promise((resolve) => {
|
|
252
246
|
defer(() => {
|
|
253
|
-
event.res.end(data);
|
|
254
|
-
resolve(
|
|
247
|
+
event.node.res.end(data);
|
|
248
|
+
resolve();
|
|
255
249
|
});
|
|
256
250
|
});
|
|
257
251
|
}
|
|
258
252
|
function defaultContentType(event, type) {
|
|
259
|
-
if (type && !event.res.getHeader("content-type")) {
|
|
260
|
-
event.res.setHeader("content-type", type);
|
|
253
|
+
if (type && !event.node.res.getHeader("content-type")) {
|
|
254
|
+
event.node.res.setHeader("content-type", type);
|
|
261
255
|
}
|
|
262
256
|
}
|
|
263
257
|
function sendRedirect(event, location, code = 302) {
|
|
264
|
-
event.res.statusCode = code;
|
|
265
|
-
event.res.setHeader("location", location);
|
|
258
|
+
event.node.res.statusCode = code;
|
|
259
|
+
event.node.res.setHeader("location", location);
|
|
266
260
|
const encodedLoc = location.replace(/"/g, "%22");
|
|
267
261
|
const html = `<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0; url=${encodedLoc}"></head></html>`;
|
|
268
262
|
return send(event, html, MIMES.html);
|
|
269
263
|
}
|
|
270
264
|
function getResponseHeaders(event) {
|
|
271
|
-
return event.res.getHeaders();
|
|
265
|
+
return event.node.res.getHeaders();
|
|
272
266
|
}
|
|
273
267
|
function getResponseHeader(event, name) {
|
|
274
|
-
return event.res.getHeader(name);
|
|
268
|
+
return event.node.res.getHeader(name);
|
|
275
269
|
}
|
|
276
270
|
function setResponseHeaders(event, headers) {
|
|
277
|
-
|
|
271
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
272
|
+
event.node.res.setHeader(name, value);
|
|
273
|
+
}
|
|
278
274
|
}
|
|
279
275
|
const setHeaders = setResponseHeaders;
|
|
280
276
|
function setResponseHeader(event, name, value) {
|
|
281
|
-
event.res.setHeader(name, value);
|
|
277
|
+
event.node.res.setHeader(name, value);
|
|
282
278
|
}
|
|
283
279
|
const setHeader = setResponseHeader;
|
|
284
280
|
function appendResponseHeaders(event, headers) {
|
|
285
|
-
|
|
281
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
282
|
+
appendResponseHeader(event, name, value);
|
|
283
|
+
}
|
|
286
284
|
}
|
|
287
285
|
const appendHeaders = appendResponseHeaders;
|
|
288
286
|
function appendResponseHeader(event, name, value) {
|
|
289
|
-
let current = event.res.getHeader(name);
|
|
287
|
+
let current = event.node.res.getHeader(name);
|
|
290
288
|
if (!current) {
|
|
291
|
-
event.res.setHeader(name, value);
|
|
289
|
+
event.node.res.setHeader(name, value);
|
|
292
290
|
return;
|
|
293
291
|
}
|
|
294
292
|
if (!Array.isArray(current)) {
|
|
295
293
|
current = [current.toString()];
|
|
296
294
|
}
|
|
297
|
-
event.res.setHeader(name, current
|
|
295
|
+
event.node.res.setHeader(name, [...current, value]);
|
|
298
296
|
}
|
|
299
297
|
const appendHeader = appendResponseHeader;
|
|
300
298
|
function isStream(data) {
|
|
@@ -302,15 +300,15 @@ function isStream(data) {
|
|
|
302
300
|
}
|
|
303
301
|
function sendStream(event, data) {
|
|
304
302
|
return new Promise((resolve, reject) => {
|
|
305
|
-
data.pipe(event.res);
|
|
306
|
-
data.on("end", () => resolve(
|
|
303
|
+
data.pipe(event.node.res);
|
|
304
|
+
data.on("end", () => resolve());
|
|
307
305
|
data.on("error", (error) => reject(createError(error)));
|
|
308
306
|
});
|
|
309
307
|
}
|
|
310
308
|
const noop = () => {
|
|
311
309
|
};
|
|
312
310
|
function writeEarlyHints(event, hints, cb = noop) {
|
|
313
|
-
if (!event.res.socket) {
|
|
311
|
+
if (!event.node.res.socket) {
|
|
314
312
|
cb();
|
|
315
313
|
return;
|
|
316
314
|
}
|
|
@@ -321,7 +319,7 @@ function writeEarlyHints(event, hints, cb = noop) {
|
|
|
321
319
|
hints.link = Array.isArray(hints.link) ? hints.link : hints.link.split(",");
|
|
322
320
|
}
|
|
323
321
|
const headers = Object.entries(hints).map((e) => [e[0].toLowerCase(), e[1]]);
|
|
324
|
-
if (
|
|
322
|
+
if (headers.length === 0) {
|
|
325
323
|
cb();
|
|
326
324
|
return;
|
|
327
325
|
}
|
|
@@ -337,19 +335,17 @@ Link: ${hints.link.join(", ")}`;
|
|
|
337
335
|
hint += `\r
|
|
338
336
|
${header}: ${value}`;
|
|
339
337
|
}
|
|
340
|
-
event.res.socket.write(`${hint}\r
|
|
338
|
+
event.node.res.socket.write(`${hint}\r
|
|
341
339
|
\r
|
|
342
|
-
`, "
|
|
340
|
+
`, "utf8", cb);
|
|
343
341
|
}
|
|
344
342
|
|
|
345
343
|
function parseCookies(event) {
|
|
346
|
-
return parse(event.req.headers.cookie || "");
|
|
344
|
+
return parse(event.node.req.headers.cookie || "");
|
|
347
345
|
}
|
|
348
|
-
const useCookies = parseCookies;
|
|
349
346
|
function getCookie(event, name) {
|
|
350
347
|
return parseCookies(event)[name];
|
|
351
348
|
}
|
|
352
|
-
const useCookie = getCookie;
|
|
353
349
|
function setCookie(event, name, value, serializeOptions) {
|
|
354
350
|
const cookieStr = serialize(name, value, {
|
|
355
351
|
path: "/",
|
|
@@ -364,6 +360,43 @@ function deleteCookie(event, name, serializeOptions) {
|
|
|
364
360
|
});
|
|
365
361
|
}
|
|
366
362
|
|
|
363
|
+
const PayloadMethods = /* @__PURE__ */ new Set(["PATCH", "POST", "PUT", "DELETE"]);
|
|
364
|
+
const ignoredHeaders = /* @__PURE__ */ new Set([
|
|
365
|
+
"transfer-encoding",
|
|
366
|
+
"connection",
|
|
367
|
+
"keep-alive",
|
|
368
|
+
"upgrade",
|
|
369
|
+
"expect"
|
|
370
|
+
]);
|
|
371
|
+
async function proxyRequest(event, target, opts = {}) {
|
|
372
|
+
const method = getMethod(event);
|
|
373
|
+
let body;
|
|
374
|
+
if (PayloadMethods.has(method)) {
|
|
375
|
+
body = await readRawBody(event).catch(() => void 0);
|
|
376
|
+
}
|
|
377
|
+
const headers = /* @__PURE__ */ Object.create(null);
|
|
378
|
+
const reqHeaders = getRequestHeaders(event);
|
|
379
|
+
for (const name in reqHeaders) {
|
|
380
|
+
if (!ignoredHeaders.has(name)) {
|
|
381
|
+
headers[name] = reqHeaders[name];
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
if (opts.fetchOptions?.headers) {
|
|
385
|
+
Object.assign(headers, opts.fetchOptions.headers);
|
|
386
|
+
}
|
|
387
|
+
if (opts.headers) {
|
|
388
|
+
Object.assign(headers, opts.headers);
|
|
389
|
+
}
|
|
390
|
+
return sendProxy(event, target, {
|
|
391
|
+
...opts,
|
|
392
|
+
fetchOptions: {
|
|
393
|
+
headers,
|
|
394
|
+
method,
|
|
395
|
+
body,
|
|
396
|
+
...opts.fetchOptions
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
}
|
|
367
400
|
async function sendProxy(event, target, opts = {}) {
|
|
368
401
|
const _fetch = opts.fetch || globalThis.fetch;
|
|
369
402
|
if (!_fetch) {
|
|
@@ -373,8 +406,8 @@ async function sendProxy(event, target, opts = {}) {
|
|
|
373
406
|
headers: opts.headers,
|
|
374
407
|
...opts.fetchOptions
|
|
375
408
|
});
|
|
376
|
-
event.res.statusCode = response.status;
|
|
377
|
-
event.res.statusMessage = response.statusText;
|
|
409
|
+
event.node.res.statusCode = response.status;
|
|
410
|
+
event.node.res.statusMessage = response.statusText;
|
|
378
411
|
for (const [key, value] of response.headers.entries()) {
|
|
379
412
|
if (key === "content-encoding") {
|
|
380
413
|
continue;
|
|
@@ -382,23 +415,23 @@ async function sendProxy(event, target, opts = {}) {
|
|
|
382
415
|
if (key === "content-length") {
|
|
383
416
|
continue;
|
|
384
417
|
}
|
|
385
|
-
event.res.setHeader(key, value);
|
|
418
|
+
event.node.res.setHeader(key, value);
|
|
386
419
|
}
|
|
387
420
|
try {
|
|
388
421
|
if (response.body) {
|
|
389
422
|
if (opts.sendStream === false) {
|
|
390
423
|
const data = new Uint8Array(await response.arrayBuffer());
|
|
391
|
-
event.res.end(data);
|
|
424
|
+
event.node.res.end(data);
|
|
392
425
|
} else {
|
|
393
426
|
for await (const chunk of response.body) {
|
|
394
|
-
event.res.write(chunk);
|
|
427
|
+
event.node.res.write(chunk);
|
|
395
428
|
}
|
|
396
|
-
event.res.end();
|
|
429
|
+
event.node.res.end();
|
|
397
430
|
}
|
|
398
431
|
}
|
|
399
|
-
} catch (
|
|
400
|
-
event.res.end();
|
|
401
|
-
throw
|
|
432
|
+
} catch (error) {
|
|
433
|
+
event.node.res.end();
|
|
434
|
+
throw error;
|
|
402
435
|
}
|
|
403
436
|
}
|
|
404
437
|
|
|
@@ -409,7 +442,7 @@ class H3Headers {
|
|
|
409
442
|
} else if (Array.isArray(init)) {
|
|
410
443
|
this._headers = Object.fromEntries(init.map(([key, value]) => [key.toLowerCase(), value]));
|
|
411
444
|
} else if (init && "append" in init) {
|
|
412
|
-
this._headers = Object.fromEntries(
|
|
445
|
+
this._headers = Object.fromEntries(init.entries());
|
|
413
446
|
} else {
|
|
414
447
|
this._headers = Object.fromEntries(Object.entries(init).map(([key, value]) => [key.toLowerCase(), value]));
|
|
415
448
|
}
|
|
@@ -443,7 +476,9 @@ class H3Headers {
|
|
|
443
476
|
this._headers[name.toLowerCase()] = String(value);
|
|
444
477
|
}
|
|
445
478
|
forEach(callbackfn) {
|
|
446
|
-
|
|
479
|
+
for (const [key, value] of Object.entries(this._headers)) {
|
|
480
|
+
callbackfn(value, key, this);
|
|
481
|
+
}
|
|
447
482
|
}
|
|
448
483
|
}
|
|
449
484
|
|
|
@@ -488,8 +523,16 @@ class H3Event {
|
|
|
488
523
|
constructor(req, res) {
|
|
489
524
|
this["__is_event__"] = true;
|
|
490
525
|
this.context = {};
|
|
491
|
-
this.
|
|
492
|
-
|
|
526
|
+
this.node = { req, res };
|
|
527
|
+
}
|
|
528
|
+
get path() {
|
|
529
|
+
return this.req.url;
|
|
530
|
+
}
|
|
531
|
+
get req() {
|
|
532
|
+
return this.node.req;
|
|
533
|
+
}
|
|
534
|
+
get res() {
|
|
535
|
+
return this.node.res;
|
|
493
536
|
}
|
|
494
537
|
respondWith(r) {
|
|
495
538
|
Promise.resolve(r).then((_response) => {
|
|
@@ -497,9 +540,9 @@ class H3Event {
|
|
|
497
540
|
return;
|
|
498
541
|
}
|
|
499
542
|
const response = _response instanceof H3Response ? _response : new H3Response(_response);
|
|
500
|
-
response.headers.
|
|
543
|
+
for (const [key, value] of response.headers.entries()) {
|
|
501
544
|
this.res.setHeader(key, value);
|
|
502
|
-
}
|
|
545
|
+
}
|
|
503
546
|
if (response.status) {
|
|
504
547
|
this.res.statusCode = response.status;
|
|
505
548
|
}
|
|
@@ -602,9 +645,13 @@ function createApp(options = {}) {
|
|
|
602
645
|
}
|
|
603
646
|
function use(app, arg1, arg2, arg3) {
|
|
604
647
|
if (Array.isArray(arg1)) {
|
|
605
|
-
|
|
648
|
+
for (const i of arg1) {
|
|
649
|
+
use(app, i, arg2, arg3);
|
|
650
|
+
}
|
|
606
651
|
} else if (Array.isArray(arg2)) {
|
|
607
|
-
|
|
652
|
+
for (const i of arg2) {
|
|
653
|
+
use(app, arg1, i, arg3);
|
|
654
|
+
}
|
|
608
655
|
} else if (typeof arg1 === "string") {
|
|
609
656
|
app.stack.push(normalizeLayer({ ...arg3, route: arg1, handler: arg2 }));
|
|
610
657
|
} else if (typeof arg1 === "function") {
|
|
@@ -617,22 +664,22 @@ function use(app, arg1, arg2, arg3) {
|
|
|
617
664
|
function createAppEventHandler(stack, options) {
|
|
618
665
|
const spacing = options.debug ? 2 : void 0;
|
|
619
666
|
return eventHandler(async (event) => {
|
|
620
|
-
event.req.originalUrl = event.req.originalUrl || event.req.url || "/";
|
|
621
|
-
const reqUrl = event.req.url || "/";
|
|
667
|
+
event.node.req.originalUrl = event.node.req.originalUrl || event.node.req.url || "/";
|
|
668
|
+
const reqUrl = event.node.req.url || "/";
|
|
622
669
|
for (const layer of stack) {
|
|
623
670
|
if (layer.route.length > 1) {
|
|
624
671
|
if (!reqUrl.startsWith(layer.route)) {
|
|
625
672
|
continue;
|
|
626
673
|
}
|
|
627
|
-
event.req.url = reqUrl.slice(layer.route.length) || "/";
|
|
674
|
+
event.node.req.url = reqUrl.slice(layer.route.length) || "/";
|
|
628
675
|
} else {
|
|
629
|
-
event.req.url = reqUrl;
|
|
676
|
+
event.node.req.url = reqUrl;
|
|
630
677
|
}
|
|
631
|
-
if (layer.match && !layer.match(event.req.url, event)) {
|
|
678
|
+
if (layer.match && !layer.match(event.node.req.url, event)) {
|
|
632
679
|
continue;
|
|
633
680
|
}
|
|
634
681
|
const val = await layer.handler(event);
|
|
635
|
-
if (event.res.writableEnded) {
|
|
682
|
+
if (event.node.res.writableEnded) {
|
|
636
683
|
return;
|
|
637
684
|
}
|
|
638
685
|
const type = typeof val;
|
|
@@ -641,7 +688,7 @@ function createAppEventHandler(stack, options) {
|
|
|
641
688
|
} else if (isStream(val)) {
|
|
642
689
|
return sendStream(event, val);
|
|
643
690
|
} else if (val === null) {
|
|
644
|
-
event.res.statusCode = 204;
|
|
691
|
+
event.node.res.statusCode = 204;
|
|
645
692
|
return send(event);
|
|
646
693
|
} else if (type === "object" || type === "boolean" || type === "number") {
|
|
647
694
|
if (val.buffer) {
|
|
@@ -649,14 +696,14 @@ function createAppEventHandler(stack, options) {
|
|
|
649
696
|
} else if (val instanceof Error) {
|
|
650
697
|
throw createError(val);
|
|
651
698
|
} else {
|
|
652
|
-
return send(event, JSON.stringify(val,
|
|
699
|
+
return send(event, JSON.stringify(val, void 0, spacing), MIMES.json);
|
|
653
700
|
}
|
|
654
701
|
}
|
|
655
702
|
}
|
|
656
|
-
if (!event.res.writableEnded) {
|
|
703
|
+
if (!event.node.res.writableEnded) {
|
|
657
704
|
throw createError({
|
|
658
705
|
statusCode: 404,
|
|
659
|
-
statusMessage: `Cannot find any route matching ${event.req.url || "/"}.`
|
|
706
|
+
statusMessage: `Cannot find any route matching ${event.node.req.url || "/"}.`
|
|
660
707
|
});
|
|
661
708
|
}
|
|
662
709
|
});
|
|
@@ -669,7 +716,7 @@ function normalizeLayer(input) {
|
|
|
669
716
|
if (input.lazy) {
|
|
670
717
|
handler = lazyEventHandler(handler);
|
|
671
718
|
} else if (!isEventHandler(handler)) {
|
|
672
|
-
handler = toEventHandler(handler,
|
|
719
|
+
handler = toEventHandler(handler, void 0, input.route);
|
|
673
720
|
}
|
|
674
721
|
return {
|
|
675
722
|
route: withoutTrailingSlash(input.route),
|
|
@@ -688,7 +735,7 @@ function fromNodeMiddleware(handler) {
|
|
|
688
735
|
throw new TypeError("Invalid handler. It should be a function:", handler);
|
|
689
736
|
}
|
|
690
737
|
return eventHandler((event) => {
|
|
691
|
-
return callNodeListener(handler, event.req, event.res);
|
|
738
|
+
return callNodeListener(handler, event.node.req, event.node.res);
|
|
692
739
|
});
|
|
693
740
|
}
|
|
694
741
|
function toNodeListener(app) {
|
|
@@ -736,8 +783,8 @@ function callNodeListener(handler, req, res) {
|
|
|
736
783
|
} else {
|
|
737
784
|
resolve(returned);
|
|
738
785
|
}
|
|
739
|
-
} catch (
|
|
740
|
-
next(
|
|
786
|
+
} catch (error) {
|
|
787
|
+
next(error);
|
|
741
788
|
}
|
|
742
789
|
});
|
|
743
790
|
}
|
|
@@ -754,9 +801,11 @@ function createRouter(opts = {}) {
|
|
|
754
801
|
_router.insert(path, route);
|
|
755
802
|
}
|
|
756
803
|
if (Array.isArray(method)) {
|
|
757
|
-
|
|
804
|
+
for (const m of method) {
|
|
805
|
+
addRoute(path, handler, m);
|
|
806
|
+
}
|
|
758
807
|
} else {
|
|
759
|
-
route.handlers[method] = toEventHandler(handler,
|
|
808
|
+
route.handlers[method] = toEventHandler(handler, void 0, path);
|
|
760
809
|
}
|
|
761
810
|
return router;
|
|
762
811
|
};
|
|
@@ -765,10 +814,10 @@ function createRouter(opts = {}) {
|
|
|
765
814
|
router[method] = (path, handle) => router.add(path, handle, method);
|
|
766
815
|
}
|
|
767
816
|
router.handler = eventHandler((event) => {
|
|
768
|
-
let path = event.req.url || "/";
|
|
817
|
+
let path = event.node.req.url || "/";
|
|
769
818
|
const qIndex = path.indexOf("?");
|
|
770
819
|
if (qIndex !== -1) {
|
|
771
|
-
path = path.
|
|
820
|
+
path = path.slice(0, Math.max(0, qIndex));
|
|
772
821
|
}
|
|
773
822
|
const matched = _router.lookup(path);
|
|
774
823
|
if (!matched) {
|
|
@@ -776,13 +825,13 @@ function createRouter(opts = {}) {
|
|
|
776
825
|
throw createError({
|
|
777
826
|
statusCode: 404,
|
|
778
827
|
name: "Not Found",
|
|
779
|
-
statusMessage: `Cannot find any route matching ${event.req.url || "/"}.`
|
|
828
|
+
statusMessage: `Cannot find any route matching ${event.node.req.url || "/"}.`
|
|
780
829
|
});
|
|
781
830
|
} else {
|
|
782
831
|
return;
|
|
783
832
|
}
|
|
784
833
|
}
|
|
785
|
-
const method = (event.req.method || "get").toLowerCase();
|
|
834
|
+
const method = (event.node.req.method || "get").toLowerCase();
|
|
786
835
|
const handler = matched.handlers[method] || matched.handlers.all;
|
|
787
836
|
if (!handler) {
|
|
788
837
|
throw createError({
|
|
@@ -798,4 +847,4 @@ function createRouter(opts = {}) {
|
|
|
798
847
|
return router;
|
|
799
848
|
}
|
|
800
849
|
|
|
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,
|
|
850
|
+
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, proxyRequest, readBody, readRawBody, send, sendError, sendProxy, sendRedirect, sendStream, setCookie, setHeader, setHeaders, setResponseHeader, setResponseHeaders, toEventHandler, toNodeListener, use, useBase, writeEarlyHints };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "h3",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Tiny JavaScript Server",
|
|
5
5
|
"repository": "unjs/h3",
|
|
6
6
|
"license": "MIT",
|
|
@@ -19,41 +19,41 @@
|
|
|
19
19
|
"files": [
|
|
20
20
|
"dist"
|
|
21
21
|
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "unbuild",
|
|
24
|
+
"dev": "vitest",
|
|
25
|
+
"lint": "eslint --ext ts,mjs,cjs .",
|
|
26
|
+
"play": "jiti ./playground/index.ts",
|
|
27
|
+
"profile": "0x -o -D .profile -P 'autocannon -c 100 -p 10 -d 40 http://localhost:$PORT' ./playground/server.cjs",
|
|
28
|
+
"release": "pnpm test && pnpm build && changelogen --release && pnpm publish && git push --follow-tags",
|
|
29
|
+
"test": "pnpm lint && vitest run --coverage"
|
|
30
|
+
},
|
|
22
31
|
"dependencies": {
|
|
23
32
|
"cookie-es": "^0.5.0",
|
|
24
|
-
"destr": "^1.2.
|
|
25
|
-
"radix3": "^0.
|
|
26
|
-
"ufo": "^0.
|
|
33
|
+
"destr": "^1.2.1",
|
|
34
|
+
"radix3": "^1.0.0",
|
|
35
|
+
"ufo": "^1.0.0"
|
|
27
36
|
},
|
|
28
37
|
"devDependencies": {
|
|
29
38
|
"0x": "^5.4.1",
|
|
30
|
-
"@nuxtjs/eslint-config-typescript": "^11.0.0",
|
|
31
39
|
"@types/express": "^4.17.14",
|
|
32
|
-
"@types/node": "^18.11.
|
|
40
|
+
"@types/node": "^18.11.9",
|
|
33
41
|
"@types/supertest": "^2.0.12",
|
|
34
|
-
"@vitest/coverage-c8": "^0.
|
|
42
|
+
"@vitest/coverage-c8": "^0.25.2",
|
|
35
43
|
"autocannon": "^7.10.0",
|
|
36
|
-
"changelogen": "^0.
|
|
44
|
+
"changelogen": "^0.4.0",
|
|
37
45
|
"connect": "^3.7.0",
|
|
38
|
-
"eslint": "^8.
|
|
46
|
+
"eslint": "^8.27.0",
|
|
47
|
+
"eslint-config-unjs": "^0.0.2",
|
|
39
48
|
"express": "^4.18.2",
|
|
40
49
|
"get-port": "^6.1.2",
|
|
41
50
|
"jiti": "^1.16.0",
|
|
42
|
-
"listhen": "^0.
|
|
43
|
-
"node-fetch-native": "^0.1
|
|
51
|
+
"listhen": "^1.0.0",
|
|
52
|
+
"node-fetch-native": "^1.0.1",
|
|
44
53
|
"supertest": "^6.3.1",
|
|
45
54
|
"typescript": "^4.8.4",
|
|
46
55
|
"unbuild": "^0.9.4",
|
|
47
|
-
"vitest": "^0.
|
|
56
|
+
"vitest": "^0.25.2"
|
|
48
57
|
},
|
|
49
|
-
"packageManager": "pnpm@7.
|
|
50
|
-
|
|
51
|
-
"build": "unbuild",
|
|
52
|
-
"dev": "vitest",
|
|
53
|
-
"lint": "eslint --ext ts,mjs,cjs .",
|
|
54
|
-
"play": "jiti ./playground/index.ts",
|
|
55
|
-
"profile": "0x -o -D .profile -P 'autocannon -c 100 -p 10 -d 40 http://localhost:$PORT' ./playground/server.cjs",
|
|
56
|
-
"release": "pnpm test && pnpm build && changelogen --release && pnpm publish && git push --follow-tags",
|
|
57
|
-
"test": "pnpm lint && vitest run --coverage"
|
|
58
|
-
}
|
|
59
|
-
}
|
|
58
|
+
"packageManager": "pnpm@7.16.0"
|
|
59
|
+
}
|