webhoster 0.3.2 → 0.3.4
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/.github/workflows/publish.yml +29 -0
- package/.test/index.js +1 -1
- package/README.md +4 -4
- package/data/CookieObject.js +1 -1
- package/{types/index.js → data/custom-types.js} +1 -1
- package/{types/typings.d.ts → data/middleware.d.ts} +1 -1
- package/helpers/HttpListener.js +20 -94
- package/helpers/RequestReader.js +1 -12
- package/helpers/ResponseHeaders.js +9 -10
- package/lib/HttpHandler.js +17 -7
- package/lib/HttpRequest.js +7 -4
- package/lib/HttpResponse.js +11 -5
- package/lib/HttpTransaction.js +2 -2
- package/middleware/AutoHeadersMiddleware.js +2 -2
- package/middleware/CORSMiddleware.js +3 -3
- package/middleware/CaseInsensitiveHeadersMiddleware.js +2 -2
- package/middleware/ContentDecoderMiddleware.js +12 -8
- package/middleware/ContentEncoderMiddleware.js +6 -5
- package/middleware/ContentLengthMiddleware.js +2 -2
- package/middleware/HashMiddleware.js +2 -2
- package/middleware/HeadMethodMiddleware.js +3 -3
- package/middleware/MethodMiddleware.js +3 -3
- package/middleware/PathMiddleware.js +4 -4
- package/middleware/ReadFormData.js +1 -1
- package/middleware/SendJsonMiddleware.js +4 -4
- package/middleware/SendStringMiddleware.js +3 -3
- package/package.json +20 -3
- package/templates/starter.js +2 -2
- package/tsconfig.json +18 -1
- package/utils/headers.js +1 -1
- package/errata/index.js +0 -1
- package/index.js +0 -4
- package/lib/index.js +0 -3
- package/middleware/ContentReaderMiddleware.js +0 -249
- package/middleware/ContentWriterMiddleware.js +0 -161
- package/middleware/SendHeadersMiddleware.js +0 -47
- package/middleware/index.js +0 -11
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
import { Transform } from 'node:stream';
|
|
2
|
-
|
|
3
|
-
/** @typedef {import('../types').IMiddleware} IMiddleware */
|
|
4
|
-
/** @typedef {import('../types').MiddlewareFunction} MiddlewareFunction */
|
|
5
|
-
/** @typedef {import('../types').MiddlewareFunctionParams} MiddlewareFunctionParams */
|
|
6
|
-
/** @typedef {import('../types').MiddlewareFunctionResult} MiddlewareFunctionResult */
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @typedef {Object} ContentWriterMiddlewareOptions
|
|
10
|
-
* @prop {string} [defaultCharset='utf-8']
|
|
11
|
-
* @prop {boolean} [setCharset=false]
|
|
12
|
-
* Automatically applies charset in `Content-Type`
|
|
13
|
-
* @prop {boolean} [setJSON=false]
|
|
14
|
-
* Automatically applies `application/json` mediatype in `Content-Type`
|
|
15
|
-
* @prop {boolean|string} [cache=false]
|
|
16
|
-
* Caches content in res.local.content or res.local[cacheName]
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
/** @implements {IMiddleware} */
|
|
20
|
-
export default class ContentWriterMiddleware {
|
|
21
|
-
/** @param {ContentWriterMiddlewareOptions} [options] */
|
|
22
|
-
constructor(options = {}) {
|
|
23
|
-
this.defaultCharset = options.defaultCharset || 'utf-8';
|
|
24
|
-
this.setCharset = options.setCharset === true;
|
|
25
|
-
this.setJSON = options.setJSON === true;
|
|
26
|
-
this.cache = options.cache;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* @param {string} charset
|
|
31
|
-
* @return {BufferEncoding}
|
|
32
|
-
*/
|
|
33
|
-
static charsetAsBufferEncoding(charset) {
|
|
34
|
-
switch (charset) {
|
|
35
|
-
case 'iso-8859-1':
|
|
36
|
-
case 'ascii':
|
|
37
|
-
case 'binary':
|
|
38
|
-
case 'latin1':
|
|
39
|
-
return 'latin1';
|
|
40
|
-
case 'utf-16le':
|
|
41
|
-
case 'ucs-2':
|
|
42
|
-
case 'ucs2':
|
|
43
|
-
case 'utf16le':
|
|
44
|
-
return 'utf16le';
|
|
45
|
-
case 'base64':
|
|
46
|
-
case 'hex':
|
|
47
|
-
return /** @type {BufferEncoding} */ (charset);
|
|
48
|
-
case 'utf-8':
|
|
49
|
-
case 'utf8':
|
|
50
|
-
default:
|
|
51
|
-
return 'utf-8';
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* @param {MiddlewareFunctionParams} params
|
|
57
|
-
* @return {MiddlewareFunctionResult}
|
|
58
|
-
*/
|
|
59
|
-
execute({ req, res }) {
|
|
60
|
-
if (req.method === 'HEAD') {
|
|
61
|
-
return 'continue';
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/** @type {string} */
|
|
65
|
-
let charset = null;
|
|
66
|
-
/** @type {BufferEncoding} */
|
|
67
|
-
let encoding = null;
|
|
68
|
-
let hasSetJSON = false;
|
|
69
|
-
|
|
70
|
-
/** @return {string} */
|
|
71
|
-
const parseCharset = () => {
|
|
72
|
-
if (charset) return charset;
|
|
73
|
-
/** @type {string} */
|
|
74
|
-
const contentType = (res.headers['content-type']);
|
|
75
|
-
if (contentType) {
|
|
76
|
-
contentType.split(';').some((directive) => {
|
|
77
|
-
const parameters = directive.split('=');
|
|
78
|
-
if (parameters[0].trim().toLowerCase() !== 'charset') {
|
|
79
|
-
return false;
|
|
80
|
-
}
|
|
81
|
-
charset = parameters[1]?.trim().toLowerCase();
|
|
82
|
-
const firstQuote = charset.indexOf('"');
|
|
83
|
-
const lastQuote = charset.lastIndexOf('"');
|
|
84
|
-
if (firstQuote !== -1 && lastQuote !== -1) {
|
|
85
|
-
charset = charset.substring(firstQuote + 1, lastQuote);
|
|
86
|
-
}
|
|
87
|
-
return true;
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
if (!charset) {
|
|
91
|
-
charset = this.defaultCharset || 'utf-8';
|
|
92
|
-
if (this.setCharset && !res.headersSent) {
|
|
93
|
-
res.headers['content-type'] = `${contentType || ''};charset=${charset}`;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
return charset;
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
/** @return {void} */
|
|
100
|
-
const setJSONMediaType = () => {
|
|
101
|
-
if (hasSetJSON) return;
|
|
102
|
-
/** @type {string} */
|
|
103
|
-
const contentType = (res.headers['content-type']);
|
|
104
|
-
res.headers['content-type'] = (contentType || '')
|
|
105
|
-
.split(';')
|
|
106
|
-
.map((directive) => {
|
|
107
|
-
const isKeyPair = directive.includes('=');
|
|
108
|
-
if (isKeyPair) return directive;
|
|
109
|
-
return 'application/json';
|
|
110
|
-
})
|
|
111
|
-
.join(';');
|
|
112
|
-
|
|
113
|
-
hasSetJSON = true;
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
const newWritable = new Transform({
|
|
117
|
-
writableObjectMode: true,
|
|
118
|
-
transform: (chunk, e, callback) => {
|
|
119
|
-
if (Buffer.isBuffer(chunk)) {
|
|
120
|
-
callback(null, chunk);
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
const cacheName = this.cache && (this.cache === true ? 'content' : this.cache);
|
|
124
|
-
if (typeof chunk === 'string') {
|
|
125
|
-
if (!encoding) {
|
|
126
|
-
encoding = ContentWriterMiddleware.charsetAsBufferEncoding(parseCharset());
|
|
127
|
-
}
|
|
128
|
-
if (cacheName) {
|
|
129
|
-
if (typeof res.locals[cacheName] === 'string') {
|
|
130
|
-
res.locals[cacheName] += chunk;
|
|
131
|
-
} else {
|
|
132
|
-
res.locals[cacheName] = chunk;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
const callbackData = Buffer.from(chunk, encoding);
|
|
136
|
-
callback(null, callbackData);
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
if (cacheName) {
|
|
140
|
-
res.locals[cacheName] = chunk;
|
|
141
|
-
}
|
|
142
|
-
if (typeof chunk === 'object') {
|
|
143
|
-
if (!encoding) {
|
|
144
|
-
encoding = ContentWriterMiddleware.charsetAsBufferEncoding(parseCharset());
|
|
145
|
-
}
|
|
146
|
-
if (this.setJSON && !hasSetJSON && !res.headersSent) {
|
|
147
|
-
setJSONMediaType();
|
|
148
|
-
}
|
|
149
|
-
callback(null, Buffer.from(JSON.stringify(chunk), encoding));
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
callback(null, chunk);
|
|
154
|
-
},
|
|
155
|
-
});
|
|
156
|
-
const destination = res.replaceStream(newWritable);
|
|
157
|
-
newWritable.pipe(destination);
|
|
158
|
-
|
|
159
|
-
return 'continue';
|
|
160
|
-
}
|
|
161
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { PassThrough } from 'stream';
|
|
2
|
-
|
|
3
|
-
/** @typedef {import('../types').IMiddleware} IMiddleware */
|
|
4
|
-
/** @typedef {import('../types').MiddlewareFunction} MiddlewareFunction */
|
|
5
|
-
/** @typedef {import('../types').MiddlewareFunctionParams} MiddlewareFunctionParams */
|
|
6
|
-
/** @typedef {import('../types').MiddlewareFunctionResult} MiddlewareFunctionResult */
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @typedef {Object} SendHeadersMiddlewareOptions
|
|
10
|
-
* @prop {boolean} [setStatus=false]
|
|
11
|
-
* Automatically set `200` or `204` status if not set
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
/** @implements {IMiddleware} */
|
|
15
|
-
export default class SendHeadersMiddleware {
|
|
16
|
-
/** @param {SendHeadersMiddlewareOptions} options */
|
|
17
|
-
constructor(options = {}) {
|
|
18
|
-
this.setStatus = options.setStatus === true;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @param {MiddlewareFunctionParams} params
|
|
23
|
-
* @return {MiddlewareFunctionResult}
|
|
24
|
-
*/
|
|
25
|
-
execute({ res }) {
|
|
26
|
-
const newWritable = new PassThrough();
|
|
27
|
-
const destination = res.replaceStream(newWritable);
|
|
28
|
-
newWritable.once('data', () => {
|
|
29
|
-
if (!res.headersSent) {
|
|
30
|
-
if (this.setStatus && res.status == null) {
|
|
31
|
-
res.status = 200;
|
|
32
|
-
}
|
|
33
|
-
res.sendHeaders(false);
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
newWritable.on('end', () => {
|
|
37
|
-
if (!res.headersSent) {
|
|
38
|
-
if (this.setStatus && res.status == null) {
|
|
39
|
-
res.status = 204;
|
|
40
|
-
}
|
|
41
|
-
res.sendHeaders(false);
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
newWritable.pipe(destination);
|
|
45
|
-
return 'continue';
|
|
46
|
-
}
|
|
47
|
-
}
|
package/middleware/index.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export { default as CaseInsensitiveHeadersMiddleware } from './CaseInsensitiveHeadersMiddleware.js';
|
|
2
|
-
export { default as ContentDecoderMiddleware } from './ContentDecoderMiddleware.js';
|
|
3
|
-
export { default as ContentEncoderMiddleware } from './ContentEncoderMiddleware.js';
|
|
4
|
-
export { default as ContentLengthMiddleware } from './ContentLengthMiddleware.js';
|
|
5
|
-
export { default as ContentReaderMiddleware } from './ContentReaderMiddleware.js';
|
|
6
|
-
export { default as ContentWriterMiddleware } from './ContentWriterMiddleware.js';
|
|
7
|
-
export { default as CorsMiddleware } from './CORSMiddleware.js';
|
|
8
|
-
export { default as HashMiddleware } from './HashMiddleware.js';
|
|
9
|
-
export { default as MethodMiddleware } from './MethodMiddleware.js';
|
|
10
|
-
export { default as PathMiddleware } from './PathMiddleware.js';
|
|
11
|
-
export { default as SendHeadersMiddleware } from './SendHeadersMiddleware.js';
|