@hono/node-server 1.5.0 → 1.7.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 +34 -0
- package/dist/globals.js +0 -89
- package/dist/globals.mjs +0 -89
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +58 -17
- package/dist/index.mjs +58 -17
- package/dist/listener.d.mts +4 -2
- package/dist/listener.d.ts +4 -2
- package/dist/listener.js +58 -17
- package/dist/listener.mjs +58 -17
- package/dist/request.d.mts +8 -1
- package/dist/request.d.ts +8 -1
- package/dist/request.js +21 -2
- package/dist/request.mjs +19 -2
- package/dist/serve-static.js +4 -2
- package/dist/serve-static.mjs +4 -2
- package/dist/server.js +58 -17
- package/dist/server.mjs +58 -17
- package/dist/types.d.mts +13 -4
- package/dist/types.d.ts +13 -4
- package/dist/utils.js +2 -1
- package/dist/utils.mjs +2 -1
- package/dist/vercel.d.mts +1 -1
- package/dist/vercel.d.ts +1 -1
- package/dist/vercel.js +58 -17
- package/dist/vercel.mjs +58 -17
- package/package.json +6 -3
package/README.md
CHANGED
|
@@ -178,6 +178,40 @@ app.use(
|
|
|
178
178
|
)
|
|
179
179
|
```
|
|
180
180
|
|
|
181
|
+
## Accessing Node.js API
|
|
182
|
+
|
|
183
|
+
You can access the Node.js API from `c.env` in Node.js. For example, if you want to specify a type, you can write the following.
|
|
184
|
+
|
|
185
|
+
```ts
|
|
186
|
+
import { serve } from '@hono/node-server'
|
|
187
|
+
import type { HttpBindings } from '@hono/node-server'
|
|
188
|
+
import { Hono } from 'hono'
|
|
189
|
+
|
|
190
|
+
const app = new Hono<{ Bindings: HttpBindings }>()
|
|
191
|
+
|
|
192
|
+
app.get('/', (c) => {
|
|
193
|
+
return c.json({
|
|
194
|
+
remoteAddress: c.env.incoming.socket.remoteAddress,
|
|
195
|
+
})
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
serve(app)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
The APIs that you can get from `c.env` are as follows.
|
|
202
|
+
|
|
203
|
+
```ts
|
|
204
|
+
type HttpBindings = {
|
|
205
|
+
incoming: IncomingMessage
|
|
206
|
+
outgoing: ServerResponse
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
type Http2Bindings = {
|
|
210
|
+
incoming: Http2ServerRequest
|
|
211
|
+
outgoing: Http2ServerResponse
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
181
215
|
## Related projects
|
|
182
216
|
|
|
183
217
|
- Hono - <https://hono.dev>
|
package/dist/globals.js
CHANGED
|
@@ -24,95 +24,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
|
|
25
25
|
// src/globals.ts
|
|
26
26
|
var import_node_crypto = __toESM(require("crypto"));
|
|
27
|
-
|
|
28
|
-
// src/utils.ts
|
|
29
|
-
var buildOutgoingHttpHeaders = (headers) => {
|
|
30
|
-
const res = {};
|
|
31
|
-
const cookies = [];
|
|
32
|
-
for (const [k, v] of headers) {
|
|
33
|
-
if (k === "set-cookie") {
|
|
34
|
-
cookies.push(v);
|
|
35
|
-
} else {
|
|
36
|
-
res[k] = v;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
if (cookies.length > 0) {
|
|
40
|
-
res["set-cookie"] = cookies;
|
|
41
|
-
}
|
|
42
|
-
res["content-type"] ??= "text/plain;charset=UTF-8";
|
|
43
|
-
return res;
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
// src/response.ts
|
|
47
|
-
var responseCache = Symbol("responseCache");
|
|
48
|
-
var cacheKey = Symbol("cache");
|
|
49
|
-
var GlobalResponse = global.Response;
|
|
50
|
-
var Response = class _Response {
|
|
51
|
-
#body;
|
|
52
|
-
#init;
|
|
53
|
-
get cache() {
|
|
54
|
-
delete this[cacheKey];
|
|
55
|
-
return this[responseCache] ||= new GlobalResponse(this.#body, this.#init);
|
|
56
|
-
}
|
|
57
|
-
constructor(body, init) {
|
|
58
|
-
this.#body = body;
|
|
59
|
-
if (init instanceof _Response) {
|
|
60
|
-
const cachedGlobalResponse = init[responseCache];
|
|
61
|
-
if (cachedGlobalResponse) {
|
|
62
|
-
this.#init = cachedGlobalResponse;
|
|
63
|
-
this.cache;
|
|
64
|
-
return;
|
|
65
|
-
} else {
|
|
66
|
-
this.#init = init.#init;
|
|
67
|
-
}
|
|
68
|
-
} else {
|
|
69
|
-
this.#init = init;
|
|
70
|
-
}
|
|
71
|
-
if (typeof body === "string" || body instanceof ReadableStream) {
|
|
72
|
-
let headers = init?.headers || { "content-type": "text/plain;charset=UTF-8" };
|
|
73
|
-
if (headers instanceof Headers) {
|
|
74
|
-
headers = buildOutgoingHttpHeaders(headers);
|
|
75
|
-
}
|
|
76
|
-
;
|
|
77
|
-
this[cacheKey] = [init?.status || 200, body, headers];
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
[
|
|
82
|
-
"body",
|
|
83
|
-
"bodyUsed",
|
|
84
|
-
"headers",
|
|
85
|
-
"ok",
|
|
86
|
-
"redirected",
|
|
87
|
-
"status",
|
|
88
|
-
"statusText",
|
|
89
|
-
"trailers",
|
|
90
|
-
"type",
|
|
91
|
-
"url"
|
|
92
|
-
].forEach((k) => {
|
|
93
|
-
Object.defineProperty(Response.prototype, k, {
|
|
94
|
-
get() {
|
|
95
|
-
return this.cache[k];
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
["arrayBuffer", "blob", "clone", "formData", "json", "text"].forEach((k) => {
|
|
100
|
-
Object.defineProperty(Response.prototype, k, {
|
|
101
|
-
value: function() {
|
|
102
|
-
return this.cache[k]();
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
Object.setPrototypeOf(Response, GlobalResponse);
|
|
107
|
-
Object.setPrototypeOf(Response.prototype, GlobalResponse.prototype);
|
|
108
|
-
Object.defineProperty(global, "Response", {
|
|
109
|
-
value: Response
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
// src/globals.ts
|
|
113
|
-
Object.defineProperty(global, "Response", {
|
|
114
|
-
value: Response
|
|
115
|
-
});
|
|
116
27
|
var webFetch = global.fetch;
|
|
117
28
|
if (typeof global.crypto === "undefined") {
|
|
118
29
|
global.crypto = import_node_crypto.default;
|
package/dist/globals.mjs
CHANGED
|
@@ -1,94 +1,5 @@
|
|
|
1
1
|
// src/globals.ts
|
|
2
2
|
import crypto from "crypto";
|
|
3
|
-
|
|
4
|
-
// src/utils.ts
|
|
5
|
-
var buildOutgoingHttpHeaders = (headers) => {
|
|
6
|
-
const res = {};
|
|
7
|
-
const cookies = [];
|
|
8
|
-
for (const [k, v] of headers) {
|
|
9
|
-
if (k === "set-cookie") {
|
|
10
|
-
cookies.push(v);
|
|
11
|
-
} else {
|
|
12
|
-
res[k] = v;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
if (cookies.length > 0) {
|
|
16
|
-
res["set-cookie"] = cookies;
|
|
17
|
-
}
|
|
18
|
-
res["content-type"] ??= "text/plain;charset=UTF-8";
|
|
19
|
-
return res;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
// src/response.ts
|
|
23
|
-
var responseCache = Symbol("responseCache");
|
|
24
|
-
var cacheKey = Symbol("cache");
|
|
25
|
-
var GlobalResponse = global.Response;
|
|
26
|
-
var Response = class _Response {
|
|
27
|
-
#body;
|
|
28
|
-
#init;
|
|
29
|
-
get cache() {
|
|
30
|
-
delete this[cacheKey];
|
|
31
|
-
return this[responseCache] ||= new GlobalResponse(this.#body, this.#init);
|
|
32
|
-
}
|
|
33
|
-
constructor(body, init) {
|
|
34
|
-
this.#body = body;
|
|
35
|
-
if (init instanceof _Response) {
|
|
36
|
-
const cachedGlobalResponse = init[responseCache];
|
|
37
|
-
if (cachedGlobalResponse) {
|
|
38
|
-
this.#init = cachedGlobalResponse;
|
|
39
|
-
this.cache;
|
|
40
|
-
return;
|
|
41
|
-
} else {
|
|
42
|
-
this.#init = init.#init;
|
|
43
|
-
}
|
|
44
|
-
} else {
|
|
45
|
-
this.#init = init;
|
|
46
|
-
}
|
|
47
|
-
if (typeof body === "string" || body instanceof ReadableStream) {
|
|
48
|
-
let headers = init?.headers || { "content-type": "text/plain;charset=UTF-8" };
|
|
49
|
-
if (headers instanceof Headers) {
|
|
50
|
-
headers = buildOutgoingHttpHeaders(headers);
|
|
51
|
-
}
|
|
52
|
-
;
|
|
53
|
-
this[cacheKey] = [init?.status || 200, body, headers];
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
[
|
|
58
|
-
"body",
|
|
59
|
-
"bodyUsed",
|
|
60
|
-
"headers",
|
|
61
|
-
"ok",
|
|
62
|
-
"redirected",
|
|
63
|
-
"status",
|
|
64
|
-
"statusText",
|
|
65
|
-
"trailers",
|
|
66
|
-
"type",
|
|
67
|
-
"url"
|
|
68
|
-
].forEach((k) => {
|
|
69
|
-
Object.defineProperty(Response.prototype, k, {
|
|
70
|
-
get() {
|
|
71
|
-
return this.cache[k];
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
["arrayBuffer", "blob", "clone", "formData", "json", "text"].forEach((k) => {
|
|
76
|
-
Object.defineProperty(Response.prototype, k, {
|
|
77
|
-
value: function() {
|
|
78
|
-
return this.cache[k]();
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
Object.setPrototypeOf(Response, GlobalResponse);
|
|
83
|
-
Object.setPrototypeOf(Response.prototype, GlobalResponse.prototype);
|
|
84
|
-
Object.defineProperty(global, "Response", {
|
|
85
|
-
value: Response
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
// src/globals.ts
|
|
89
|
-
Object.defineProperty(global, "Response", {
|
|
90
|
-
value: Response
|
|
91
|
-
});
|
|
92
3
|
var webFetch = global.fetch;
|
|
93
4
|
if (typeof global.crypto === "undefined") {
|
|
94
5
|
global.crypto = crypto;
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { createAdaptorServer, serve } from './server.mjs';
|
|
2
2
|
export { getRequestListener } from './listener.mjs';
|
|
3
|
+
export { Http2Bindings, HttpBindings } from './types.mjs';
|
|
3
4
|
import 'node:net';
|
|
4
|
-
import './types.mjs';
|
|
5
5
|
import 'node:http';
|
|
6
6
|
import 'node:http2';
|
|
7
7
|
import 'node:https';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { createAdaptorServer, serve } from './server.js';
|
|
2
2
|
export { getRequestListener } from './listener.js';
|
|
3
|
+
export { Http2Bindings, HttpBindings } from './types.js';
|
|
3
4
|
import 'node:net';
|
|
4
|
-
import './types.js';
|
|
5
5
|
import 'node:http';
|
|
6
6
|
import 'node:http2';
|
|
7
7
|
import 'node:https';
|
package/dist/index.js
CHANGED
|
@@ -42,6 +42,22 @@ var import_node_http = require("http");
|
|
|
42
42
|
// src/request.ts
|
|
43
43
|
var import_node_http2 = require("http2");
|
|
44
44
|
var import_node_stream = require("stream");
|
|
45
|
+
var GlobalRequest = global.Request;
|
|
46
|
+
var Request = class extends GlobalRequest {
|
|
47
|
+
constructor(input, options) {
|
|
48
|
+
if (typeof input === "object" && getRequestCache in input) {
|
|
49
|
+
input = input[getRequestCache]();
|
|
50
|
+
}
|
|
51
|
+
if (options?.body instanceof ReadableStream) {
|
|
52
|
+
;
|
|
53
|
+
options.duplex = "half";
|
|
54
|
+
}
|
|
55
|
+
super(input, options);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
Object.defineProperty(global, "Request", {
|
|
59
|
+
value: Request
|
|
60
|
+
});
|
|
45
61
|
var newRequestFromIncoming = (method, url, incoming) => {
|
|
46
62
|
const headerRecord = [];
|
|
47
63
|
const rawHeaders = incoming.rawHeaders;
|
|
@@ -58,7 +74,6 @@ var newRequestFromIncoming = (method, url, incoming) => {
|
|
|
58
74
|
};
|
|
59
75
|
if (!(method === "GET" || method === "HEAD")) {
|
|
60
76
|
init.body = import_node_stream.Readable.toWeb(incoming);
|
|
61
|
-
init.duplex = "half";
|
|
62
77
|
}
|
|
63
78
|
return new Request(url, init);
|
|
64
79
|
};
|
|
@@ -108,7 +123,7 @@ var requestPrototype = {
|
|
|
108
123
|
}
|
|
109
124
|
});
|
|
110
125
|
});
|
|
111
|
-
Object.setPrototypeOf(requestPrototype,
|
|
126
|
+
Object.setPrototypeOf(requestPrototype, Request.prototype);
|
|
112
127
|
var newRequest = (incoming) => {
|
|
113
128
|
const req = Object.create(requestPrototype);
|
|
114
129
|
req[incomingKey] = incoming;
|
|
@@ -137,8 +152,9 @@ function writeFromReadableStream(stream, writable) {
|
|
|
137
152
|
function cancel(error) {
|
|
138
153
|
reader.cancel(error).catch(() => {
|
|
139
154
|
});
|
|
140
|
-
if (error)
|
|
155
|
+
if (error) {
|
|
141
156
|
writable.destroy(error);
|
|
157
|
+
}
|
|
142
158
|
}
|
|
143
159
|
function onDrain() {
|
|
144
160
|
reader.read().then(flow, cancel);
|
|
@@ -242,9 +258,6 @@ Object.defineProperty(global, "Response", {
|
|
|
242
258
|
|
|
243
259
|
// src/globals.ts
|
|
244
260
|
var import_node_crypto = __toESM(require("crypto"));
|
|
245
|
-
Object.defineProperty(global, "Response", {
|
|
246
|
-
value: Response2
|
|
247
|
-
});
|
|
248
261
|
var webFetch = global.fetch;
|
|
249
262
|
if (typeof global.crypto === "undefined") {
|
|
250
263
|
global.crypto = import_node_crypto.default;
|
|
@@ -271,8 +284,9 @@ var handleResponseError = (e, outgoing) => {
|
|
|
271
284
|
console.info("The user aborted a request.");
|
|
272
285
|
} else {
|
|
273
286
|
console.error(e);
|
|
274
|
-
if (!outgoing.headersSent)
|
|
287
|
+
if (!outgoing.headersSent) {
|
|
275
288
|
outgoing.writeHead(500, { "Content-Type": "text/plain" });
|
|
289
|
+
}
|
|
276
290
|
outgoing.end(`Error: ${err.message}`);
|
|
277
291
|
outgoing.destroy(err);
|
|
278
292
|
}
|
|
@@ -290,12 +304,25 @@ var responseViaCache = (res, outgoing) => {
|
|
|
290
304
|
);
|
|
291
305
|
}
|
|
292
306
|
};
|
|
293
|
-
var responseViaResponseObject = async (res, outgoing) => {
|
|
307
|
+
var responseViaResponseObject = async (res, outgoing, options = {}) => {
|
|
294
308
|
if (res instanceof Promise) {
|
|
295
|
-
|
|
309
|
+
if (options.errorHandler) {
|
|
310
|
+
try {
|
|
311
|
+
res = await res;
|
|
312
|
+
} catch (err) {
|
|
313
|
+
const errRes = await options.errorHandler(err);
|
|
314
|
+
if (!errRes) {
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
res = errRes;
|
|
318
|
+
}
|
|
319
|
+
} else {
|
|
320
|
+
res = await res.catch(handleFetchError);
|
|
321
|
+
}
|
|
296
322
|
}
|
|
297
323
|
try {
|
|
298
|
-
|
|
324
|
+
const isCached = cacheKey in res;
|
|
325
|
+
if (isCached) {
|
|
299
326
|
return responseViaCache(res, outgoing);
|
|
300
327
|
}
|
|
301
328
|
} catch (e) {
|
|
@@ -304,8 +331,15 @@ var responseViaResponseObject = async (res, outgoing) => {
|
|
|
304
331
|
const resHeaderRecord = buildOutgoingHttpHeaders(res.headers);
|
|
305
332
|
if (res.body) {
|
|
306
333
|
try {
|
|
307
|
-
|
|
308
|
-
|
|
334
|
+
const {
|
|
335
|
+
"transfer-encoding": transferEncoding,
|
|
336
|
+
"content-encoding": contentEncoding,
|
|
337
|
+
"content-length": contentLength,
|
|
338
|
+
"x-accel-buffering": accelBuffering,
|
|
339
|
+
"content-type": contentType
|
|
340
|
+
} = resHeaderRecord;
|
|
341
|
+
if (transferEncoding || contentEncoding || contentLength || // nginx buffering variant
|
|
342
|
+
accelBuffering && regBuffer.test(accelBuffering) || !regContentType.test(contentType)) {
|
|
309
343
|
outgoing.writeHead(res.status, resHeaderRecord);
|
|
310
344
|
await writeFromReadableStream(res.body, outgoing);
|
|
311
345
|
} else {
|
|
@@ -322,23 +356,30 @@ var responseViaResponseObject = async (res, outgoing) => {
|
|
|
322
356
|
outgoing.end();
|
|
323
357
|
}
|
|
324
358
|
};
|
|
325
|
-
var getRequestListener = (fetchCallback) => {
|
|
326
|
-
return (incoming, outgoing) => {
|
|
359
|
+
var getRequestListener = (fetchCallback, options = {}) => {
|
|
360
|
+
return async (incoming, outgoing) => {
|
|
327
361
|
let res;
|
|
328
362
|
const req = newRequest(incoming);
|
|
329
363
|
try {
|
|
330
|
-
res = fetchCallback(req);
|
|
364
|
+
res = fetchCallback(req, { incoming, outgoing });
|
|
331
365
|
if (cacheKey in res) {
|
|
332
366
|
return responseViaCache(res, outgoing);
|
|
333
367
|
}
|
|
334
368
|
} catch (e) {
|
|
335
369
|
if (!res) {
|
|
336
|
-
|
|
370
|
+
if (options.errorHandler) {
|
|
371
|
+
res = await options.errorHandler(e);
|
|
372
|
+
if (!res) {
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
} else {
|
|
376
|
+
res = handleFetchError(e);
|
|
377
|
+
}
|
|
337
378
|
} else {
|
|
338
379
|
return handleResponseError(e, outgoing);
|
|
339
380
|
}
|
|
340
381
|
}
|
|
341
|
-
return responseViaResponseObject(res, outgoing);
|
|
382
|
+
return responseViaResponseObject(res, outgoing, options);
|
|
342
383
|
};
|
|
343
384
|
};
|
|
344
385
|
|
package/dist/index.mjs
CHANGED
|
@@ -4,6 +4,22 @@ import { createServer as createServerHTTP } from "http";
|
|
|
4
4
|
// src/request.ts
|
|
5
5
|
import { Http2ServerRequest } from "http2";
|
|
6
6
|
import { Readable } from "stream";
|
|
7
|
+
var GlobalRequest = global.Request;
|
|
8
|
+
var Request = class extends GlobalRequest {
|
|
9
|
+
constructor(input, options) {
|
|
10
|
+
if (typeof input === "object" && getRequestCache in input) {
|
|
11
|
+
input = input[getRequestCache]();
|
|
12
|
+
}
|
|
13
|
+
if (options?.body instanceof ReadableStream) {
|
|
14
|
+
;
|
|
15
|
+
options.duplex = "half";
|
|
16
|
+
}
|
|
17
|
+
super(input, options);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
Object.defineProperty(global, "Request", {
|
|
21
|
+
value: Request
|
|
22
|
+
});
|
|
7
23
|
var newRequestFromIncoming = (method, url, incoming) => {
|
|
8
24
|
const headerRecord = [];
|
|
9
25
|
const rawHeaders = incoming.rawHeaders;
|
|
@@ -20,7 +36,6 @@ var newRequestFromIncoming = (method, url, incoming) => {
|
|
|
20
36
|
};
|
|
21
37
|
if (!(method === "GET" || method === "HEAD")) {
|
|
22
38
|
init.body = Readable.toWeb(incoming);
|
|
23
|
-
init.duplex = "half";
|
|
24
39
|
}
|
|
25
40
|
return new Request(url, init);
|
|
26
41
|
};
|
|
@@ -70,7 +85,7 @@ var requestPrototype = {
|
|
|
70
85
|
}
|
|
71
86
|
});
|
|
72
87
|
});
|
|
73
|
-
Object.setPrototypeOf(requestPrototype,
|
|
88
|
+
Object.setPrototypeOf(requestPrototype, Request.prototype);
|
|
74
89
|
var newRequest = (incoming) => {
|
|
75
90
|
const req = Object.create(requestPrototype);
|
|
76
91
|
req[incomingKey] = incoming;
|
|
@@ -99,8 +114,9 @@ function writeFromReadableStream(stream, writable) {
|
|
|
99
114
|
function cancel(error) {
|
|
100
115
|
reader.cancel(error).catch(() => {
|
|
101
116
|
});
|
|
102
|
-
if (error)
|
|
117
|
+
if (error) {
|
|
103
118
|
writable.destroy(error);
|
|
119
|
+
}
|
|
104
120
|
}
|
|
105
121
|
function onDrain() {
|
|
106
122
|
reader.read().then(flow, cancel);
|
|
@@ -204,9 +220,6 @@ Object.defineProperty(global, "Response", {
|
|
|
204
220
|
|
|
205
221
|
// src/globals.ts
|
|
206
222
|
import crypto from "crypto";
|
|
207
|
-
Object.defineProperty(global, "Response", {
|
|
208
|
-
value: Response2
|
|
209
|
-
});
|
|
210
223
|
var webFetch = global.fetch;
|
|
211
224
|
if (typeof global.crypto === "undefined") {
|
|
212
225
|
global.crypto = crypto;
|
|
@@ -233,8 +246,9 @@ var handleResponseError = (e, outgoing) => {
|
|
|
233
246
|
console.info("The user aborted a request.");
|
|
234
247
|
} else {
|
|
235
248
|
console.error(e);
|
|
236
|
-
if (!outgoing.headersSent)
|
|
249
|
+
if (!outgoing.headersSent) {
|
|
237
250
|
outgoing.writeHead(500, { "Content-Type": "text/plain" });
|
|
251
|
+
}
|
|
238
252
|
outgoing.end(`Error: ${err.message}`);
|
|
239
253
|
outgoing.destroy(err);
|
|
240
254
|
}
|
|
@@ -252,12 +266,25 @@ var responseViaCache = (res, outgoing) => {
|
|
|
252
266
|
);
|
|
253
267
|
}
|
|
254
268
|
};
|
|
255
|
-
var responseViaResponseObject = async (res, outgoing) => {
|
|
269
|
+
var responseViaResponseObject = async (res, outgoing, options = {}) => {
|
|
256
270
|
if (res instanceof Promise) {
|
|
257
|
-
|
|
271
|
+
if (options.errorHandler) {
|
|
272
|
+
try {
|
|
273
|
+
res = await res;
|
|
274
|
+
} catch (err) {
|
|
275
|
+
const errRes = await options.errorHandler(err);
|
|
276
|
+
if (!errRes) {
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
res = errRes;
|
|
280
|
+
}
|
|
281
|
+
} else {
|
|
282
|
+
res = await res.catch(handleFetchError);
|
|
283
|
+
}
|
|
258
284
|
}
|
|
259
285
|
try {
|
|
260
|
-
|
|
286
|
+
const isCached = cacheKey in res;
|
|
287
|
+
if (isCached) {
|
|
261
288
|
return responseViaCache(res, outgoing);
|
|
262
289
|
}
|
|
263
290
|
} catch (e) {
|
|
@@ -266,8 +293,15 @@ var responseViaResponseObject = async (res, outgoing) => {
|
|
|
266
293
|
const resHeaderRecord = buildOutgoingHttpHeaders(res.headers);
|
|
267
294
|
if (res.body) {
|
|
268
295
|
try {
|
|
269
|
-
|
|
270
|
-
|
|
296
|
+
const {
|
|
297
|
+
"transfer-encoding": transferEncoding,
|
|
298
|
+
"content-encoding": contentEncoding,
|
|
299
|
+
"content-length": contentLength,
|
|
300
|
+
"x-accel-buffering": accelBuffering,
|
|
301
|
+
"content-type": contentType
|
|
302
|
+
} = resHeaderRecord;
|
|
303
|
+
if (transferEncoding || contentEncoding || contentLength || // nginx buffering variant
|
|
304
|
+
accelBuffering && regBuffer.test(accelBuffering) || !regContentType.test(contentType)) {
|
|
271
305
|
outgoing.writeHead(res.status, resHeaderRecord);
|
|
272
306
|
await writeFromReadableStream(res.body, outgoing);
|
|
273
307
|
} else {
|
|
@@ -284,23 +318,30 @@ var responseViaResponseObject = async (res, outgoing) => {
|
|
|
284
318
|
outgoing.end();
|
|
285
319
|
}
|
|
286
320
|
};
|
|
287
|
-
var getRequestListener = (fetchCallback) => {
|
|
288
|
-
return (incoming, outgoing) => {
|
|
321
|
+
var getRequestListener = (fetchCallback, options = {}) => {
|
|
322
|
+
return async (incoming, outgoing) => {
|
|
289
323
|
let res;
|
|
290
324
|
const req = newRequest(incoming);
|
|
291
325
|
try {
|
|
292
|
-
res = fetchCallback(req);
|
|
326
|
+
res = fetchCallback(req, { incoming, outgoing });
|
|
293
327
|
if (cacheKey in res) {
|
|
294
328
|
return responseViaCache(res, outgoing);
|
|
295
329
|
}
|
|
296
330
|
} catch (e) {
|
|
297
331
|
if (!res) {
|
|
298
|
-
|
|
332
|
+
if (options.errorHandler) {
|
|
333
|
+
res = await options.errorHandler(e);
|
|
334
|
+
if (!res) {
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
} else {
|
|
338
|
+
res = handleFetchError(e);
|
|
339
|
+
}
|
|
299
340
|
} else {
|
|
300
341
|
return handleResponseError(e, outgoing);
|
|
301
342
|
}
|
|
302
343
|
}
|
|
303
|
-
return responseViaResponseObject(res, outgoing);
|
|
344
|
+
return responseViaResponseObject(res, outgoing, options);
|
|
304
345
|
};
|
|
305
346
|
};
|
|
306
347
|
|
package/dist/listener.d.mts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
2
|
import { Http2ServerRequest, Http2ServerResponse } from 'node:http2';
|
|
3
|
-
import { FetchCallback } from './types.mjs';
|
|
3
|
+
import { FetchCallback, CustomErrorHandler } from './types.mjs';
|
|
4
4
|
import 'node:https';
|
|
5
5
|
|
|
6
|
-
declare const getRequestListener: (fetchCallback: FetchCallback
|
|
6
|
+
declare const getRequestListener: (fetchCallback: FetchCallback, options?: {
|
|
7
|
+
errorHandler?: CustomErrorHandler;
|
|
8
|
+
}) => (incoming: IncomingMessage | Http2ServerRequest, outgoing: ServerResponse | Http2ServerResponse) => Promise<void>;
|
|
7
9
|
|
|
8
10
|
export { getRequestListener };
|
package/dist/listener.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
2
|
import { Http2ServerRequest, Http2ServerResponse } from 'node:http2';
|
|
3
|
-
import { FetchCallback } from './types.js';
|
|
3
|
+
import { FetchCallback, CustomErrorHandler } from './types.js';
|
|
4
4
|
import 'node:https';
|
|
5
5
|
|
|
6
|
-
declare const getRequestListener: (fetchCallback: FetchCallback
|
|
6
|
+
declare const getRequestListener: (fetchCallback: FetchCallback, options?: {
|
|
7
|
+
errorHandler?: CustomErrorHandler;
|
|
8
|
+
}) => (incoming: IncomingMessage | Http2ServerRequest, outgoing: ServerResponse | Http2ServerResponse) => Promise<void>;
|
|
7
9
|
|
|
8
10
|
export { getRequestListener };
|