@hono/node-server 0.3.0 → 0.5.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 +18 -2
- package/dist/globals.js +15 -5
- package/dist/listener.js +38 -8
- package/dist/serve-static.d.ts +1 -0
- package/dist/serve-static.js +2 -1
- package/dist/stream.d.ts +0 -4
- package/dist/stream.js +15 -17
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -77,7 +77,7 @@ app.get('/', (c) => c.json({ 'Hono meets': 'Node.js' }))
|
|
|
77
77
|
serve(app)
|
|
78
78
|
```
|
|
79
79
|
|
|
80
|
-
|
|
80
|
+
## Serve Static Middleware
|
|
81
81
|
|
|
82
82
|
Use Serve Static Middleware that has been created for Node.js.
|
|
83
83
|
|
|
@@ -89,7 +89,23 @@ import { serveStatic } from '@hono/node-server/serve-static'
|
|
|
89
89
|
app.use('/static/*', serveStatic({ root: './' }))
|
|
90
90
|
```
|
|
91
91
|
|
|
92
|
-
Note that `root` must be
|
|
92
|
+
Note that `root` must be _relative_ to the current working directory - absolute paths are not supported.
|
|
93
|
+
|
|
94
|
+
### Options
|
|
95
|
+
|
|
96
|
+
#### `rewriteRequestPath`
|
|
97
|
+
|
|
98
|
+
If you want to serve files in `./.foojs` with the request path `/__foo/*`, you can write like the following.
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
app.use(
|
|
102
|
+
'/__foo/*',
|
|
103
|
+
serveStatic({
|
|
104
|
+
root: './.foojs/',
|
|
105
|
+
rewriteRequestPath: (path: string) => path.replace(/^\/__foo/, ''),
|
|
106
|
+
})
|
|
107
|
+
)
|
|
108
|
+
```
|
|
93
109
|
|
|
94
110
|
## Related projects
|
|
95
111
|
|
package/dist/globals.js
CHANGED
|
@@ -9,9 +9,12 @@ const web_stream_1 = require("@remix-run/web-stream");
|
|
|
9
9
|
const base64_1 = require("./base64");
|
|
10
10
|
const fetch_1 = require("./fetch");
|
|
11
11
|
function installGlobals() {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
if (typeof base64_1.atob === 'undefined')
|
|
13
|
+
global.atob = base64_1.atob;
|
|
14
|
+
if (typeof base64_1.btoa === 'undefined')
|
|
15
|
+
global.btoa = base64_1.btoa;
|
|
16
|
+
if (typeof Blob === 'undefined')
|
|
17
|
+
global.Blob = fetch_1.Blob;
|
|
15
18
|
global.File = fetch_1.File;
|
|
16
19
|
global.Headers = fetch_1.Headers;
|
|
17
20
|
global.Request = fetch_1.Request;
|
|
@@ -20,8 +23,15 @@ function installGlobals() {
|
|
|
20
23
|
global.FormData = fetch_1.FormData;
|
|
21
24
|
global.ReadableStream = web_stream_1.ReadableStream;
|
|
22
25
|
global.WritableStream = web_stream_1.WritableStream;
|
|
23
|
-
if (typeof global.crypto ===
|
|
24
|
-
|
|
26
|
+
if (typeof global.crypto === 'undefined') {
|
|
27
|
+
// If crypto.subtle is undefined, we're in a Node.js v16 environment
|
|
28
|
+
if (typeof node_crypto_1.default.subtle === 'undefined') {
|
|
29
|
+
// We can use the webcrypto polyfill
|
|
30
|
+
global.crypto = require('crypto').webcrypto;
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
global.crypto = node_crypto_1.default;
|
|
34
|
+
}
|
|
25
35
|
}
|
|
26
36
|
}
|
|
27
37
|
exports.installGlobals = installGlobals;
|
package/dist/listener.js
CHANGED
|
@@ -34,11 +34,21 @@ const getRequestListener = (fetchCallback) => {
|
|
|
34
34
|
try {
|
|
35
35
|
res = (await fetchCallback(new Request(url.toString(), init)));
|
|
36
36
|
}
|
|
37
|
-
catch {
|
|
37
|
+
catch (e) {
|
|
38
38
|
res = new fetch_1.Response(null, { status: 500 });
|
|
39
|
+
if (e instanceof Error) {
|
|
40
|
+
// timeout error emits 504 timeout
|
|
41
|
+
if (e.name === 'TimeoutError' || e.constructor.name === 'TimeoutError') {
|
|
42
|
+
res = new fetch_1.Response(null, { status: 504 });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
39
45
|
}
|
|
40
46
|
const contentType = res.headers.get('content-type') || '';
|
|
47
|
+
// nginx buffering variant
|
|
48
|
+
const buffering = res.headers.get('x-accel-buffering') || '';
|
|
41
49
|
const contentEncoding = res.headers.get('content-encoding');
|
|
50
|
+
const contentLength = res.headers.get('content-length');
|
|
51
|
+
const transferEncoding = res.headers.get('transfer-encoding');
|
|
42
52
|
for (const [k, v] of res.headers) {
|
|
43
53
|
if (k === 'set-cookie') {
|
|
44
54
|
outgoing.setHeader(k, res.headers.getAll(k));
|
|
@@ -49,14 +59,34 @@ const getRequestListener = (fetchCallback) => {
|
|
|
49
59
|
}
|
|
50
60
|
outgoing.statusCode = res.status;
|
|
51
61
|
if (res.body) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
62
|
+
try {
|
|
63
|
+
/**
|
|
64
|
+
* If content-encoding is set, we assume that the response should be not decoded.
|
|
65
|
+
* Else if transfer-encoding is set, we assume that the response should be streamed.
|
|
66
|
+
* Else if content-length is set, we assume that the response content has been taken care of.
|
|
67
|
+
* Else if x-accel-buffering is set to no, we assume that the response should be streamed.
|
|
68
|
+
* Else if content-type is not application/json nor text/* but can be text/event-stream,
|
|
69
|
+
* we assume that the response should be streamed.
|
|
70
|
+
*/
|
|
71
|
+
if (contentEncoding ||
|
|
72
|
+
transferEncoding ||
|
|
73
|
+
contentLength ||
|
|
74
|
+
/^no$/i.test(buffering) ||
|
|
75
|
+
!/^(application\/json\b|text\/(?!event-stream\b))/i.test(contentType)) {
|
|
76
|
+
await (0, stream_1.writeReadableStreamToWritable)(res.body, outgoing);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
const text = await res.text();
|
|
80
|
+
outgoing.setHeader('Content-Length', Buffer.byteLength(text));
|
|
81
|
+
outgoing.end(text);
|
|
82
|
+
}
|
|
57
83
|
}
|
|
58
|
-
|
|
59
|
-
|
|
84
|
+
catch (e) {
|
|
85
|
+
// try to catch any error, to avoid crash
|
|
86
|
+
console.error(e);
|
|
87
|
+
const err = e instanceof Error ? e : new Error('unknown error', { cause: e });
|
|
88
|
+
// destroy error must accept an instance of Error
|
|
89
|
+
outgoing.destroy(err);
|
|
60
90
|
}
|
|
61
91
|
}
|
|
62
92
|
else {
|
package/dist/serve-static.d.ts
CHANGED
|
@@ -7,5 +7,6 @@ export declare type ServeStaticOptions = {
|
|
|
7
7
|
root?: string;
|
|
8
8
|
path?: string;
|
|
9
9
|
index?: string;
|
|
10
|
+
rewriteRequestPath?: (path: string) => string;
|
|
10
11
|
};
|
|
11
12
|
export declare const serveStatic: (options?: ServeStaticOptions) => (c: Context, next: Next) => Promise<Response | undefined>;
|
package/dist/serve-static.js
CHANGED
|
@@ -11,8 +11,9 @@ const serveStatic = (options = { root: '' }) => {
|
|
|
11
11
|
await next();
|
|
12
12
|
}
|
|
13
13
|
const url = new URL(c.req.url);
|
|
14
|
+
const filename = options.path ?? url.pathname;
|
|
14
15
|
let path = (0, filepath_1.getFilePath)({
|
|
15
|
-
filename: options.
|
|
16
|
+
filename: options.rewriteRequestPath ? options.rewriteRequestPath(filename) : filename,
|
|
16
17
|
root: options.root,
|
|
17
18
|
defaultDocument: options.index ?? 'index.html',
|
|
18
19
|
});
|
package/dist/stream.d.ts
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import type { Writable } from 'node:stream';
|
|
3
3
|
export declare function writeReadableStreamToWritable(stream: ReadableStream, writable: Writable): Promise<void>;
|
|
4
|
-
/**
|
|
5
|
-
* Credits:
|
|
6
|
-
* - https://github.com/remix-run/remix/blob/e77e2eb/packages/remix-node/stream.ts
|
|
7
|
-
*/
|
package/dist/stream.js
CHANGED
|
@@ -2,26 +2,24 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.writeReadableStreamToWritable = void 0;
|
|
4
4
|
async function writeReadableStreamToWritable(stream, writable) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
if (done) {
|
|
9
|
-
writable.end();
|
|
10
|
-
return;
|
|
11
|
-
}
|
|
12
|
-
writable.write(value);
|
|
13
|
-
await read();
|
|
5
|
+
const reader = stream.getReader();
|
|
6
|
+
function onClose() {
|
|
7
|
+
reader.cancel(new Error('Response writer closed'));
|
|
14
8
|
}
|
|
9
|
+
writable.once('close', onClose);
|
|
15
10
|
try {
|
|
16
|
-
|
|
11
|
+
while (true) {
|
|
12
|
+
const { done, value } = await reader.read();
|
|
13
|
+
if (done) {
|
|
14
|
+
writable.end();
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
writable.write(value);
|
|
18
|
+
}
|
|
17
19
|
}
|
|
18
|
-
|
|
19
|
-
writable.
|
|
20
|
-
|
|
20
|
+
finally {
|
|
21
|
+
writable.off('close', onClose);
|
|
22
|
+
reader.releaseLock();
|
|
21
23
|
}
|
|
22
24
|
}
|
|
23
25
|
exports.writeReadableStreamToWritable = writeReadableStreamToWritable;
|
|
24
|
-
/**
|
|
25
|
-
* Credits:
|
|
26
|
-
* - https://github.com/remix-run/remix/blob/e77e2eb/packages/remix-node/stream.ts
|
|
27
|
-
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hono/node-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "HTTP Server for Hono on Node.js",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"@types/jest": "^29.0.1",
|
|
49
49
|
"@types/node": "^18.7.16",
|
|
50
50
|
"@types/supertest": "^2.0.12",
|
|
51
|
-
"hono": "^
|
|
51
|
+
"hono": "^3.1.5",
|
|
52
52
|
"jest": "^29.0.3",
|
|
53
53
|
"next": "13.1.6",
|
|
54
54
|
"np": "^7.6.2",
|