@wooksjs/event-http 0.4.9 → 0.4.11
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/dist/index.cjs +1009 -1055
- package/dist/index.mjs +1009 -1055
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -6,1102 +6,1056 @@ var stream = require('stream');
|
|
|
6
6
|
var wooks = require('wooks');
|
|
7
7
|
var http = require('http');
|
|
8
8
|
|
|
9
|
-
function createHttpContext(data, options) {
|
|
10
|
-
return eventCore.createEventContext({
|
|
11
|
-
event:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
9
|
+
function createHttpContext(data, options) {
|
|
10
|
+
return eventCore.createEventContext({
|
|
11
|
+
event: {
|
|
12
|
+
...data,
|
|
13
|
+
type: 'HTTP',
|
|
14
|
+
},
|
|
15
|
+
options,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Wrapper on useEventContext with HTTP event types
|
|
20
|
+
* @returns set of hooks { getCtx, restoreCtx, clearCtx, hookStore, getStore, setStore }
|
|
21
|
+
*/
|
|
22
|
+
function useHttpContext() {
|
|
23
|
+
return eventCore.useEventContext('HTTP');
|
|
21
24
|
}
|
|
22
25
|
|
|
23
|
-
const xForwardedFor = 'x-forwarded-for';
|
|
24
|
-
function useRequest() {
|
|
25
|
-
const { store } = useHttpContext();
|
|
26
|
-
const { init } = store('request');
|
|
27
|
-
const event = store('event');
|
|
28
|
-
const { req } = event.value;
|
|
29
|
-
const rawBody = () => init('rawBody', () => {
|
|
30
|
-
return new Promise((resolve, reject) => {
|
|
31
|
-
let body = Buffer.from('');
|
|
32
|
-
req.on('data', function (chunk) {
|
|
33
|
-
body = Buffer.concat([body, chunk]);
|
|
34
|
-
});
|
|
35
|
-
req.on('error', function (err) {
|
|
36
|
-
reject(err);
|
|
37
|
-
});
|
|
38
|
-
req.on('end', function () {
|
|
39
|
-
resolve(body);
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
const reqId = eventCore.useEventId().getId;
|
|
44
|
-
const forwardedIp = () => init('forwardedIp', () => {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
req.headers[xForwardedFor]
|
|
48
|
-
|
|
49
|
-
.
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
else {
|
|
53
|
-
return '';
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
const remoteIp = () => init('remoteIp', () =>
|
|
57
|
-
function getIp(options) {
|
|
58
|
-
if (options
|
|
59
|
-
return forwardedIp() || getIp();
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
return remoteIp();
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
const getIpList = () => init('ipList', () => {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
};
|
|
26
|
+
const xForwardedFor = 'x-forwarded-for';
|
|
27
|
+
function useRequest() {
|
|
28
|
+
const { store } = useHttpContext();
|
|
29
|
+
const { init } = store('request');
|
|
30
|
+
const event = store('event');
|
|
31
|
+
const { req } = event.value;
|
|
32
|
+
const rawBody = () => init('rawBody', () => {
|
|
33
|
+
return new Promise((resolve, reject) => {
|
|
34
|
+
let body = Buffer.from('');
|
|
35
|
+
req.on('data', function (chunk) {
|
|
36
|
+
body = Buffer.concat([body, chunk]);
|
|
37
|
+
});
|
|
38
|
+
req.on('error', function (err) {
|
|
39
|
+
reject(err);
|
|
40
|
+
});
|
|
41
|
+
req.on('end', function () {
|
|
42
|
+
resolve(body);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
const reqId = eventCore.useEventId().getId;
|
|
47
|
+
const forwardedIp = () => init('forwardedIp', () => {
|
|
48
|
+
if (typeof req.headers[xForwardedFor] === 'string' &&
|
|
49
|
+
req.headers[xForwardedFor]) {
|
|
50
|
+
return req.headers[xForwardedFor]
|
|
51
|
+
.split(',')
|
|
52
|
+
.shift()
|
|
53
|
+
?.trim();
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
return '';
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
const remoteIp = () => init('remoteIp', () => req.socket?.remoteAddress || req.connection?.remoteAddress || '');
|
|
60
|
+
function getIp(options) {
|
|
61
|
+
if (options?.trustProxy) {
|
|
62
|
+
return forwardedIp() || getIp();
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
return remoteIp();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const getIpList = () => init('ipList', () => {
|
|
69
|
+
return {
|
|
70
|
+
remoteIp: req.socket?.remoteAddress ||
|
|
71
|
+
req.connection?.remoteAddress ||
|
|
72
|
+
'',
|
|
73
|
+
forwarded: (req.headers[xForwardedFor] || '')
|
|
74
|
+
.split(',')
|
|
75
|
+
.map((s) => s.trim()),
|
|
76
|
+
};
|
|
77
|
+
});
|
|
78
|
+
return {
|
|
79
|
+
rawRequest: req,
|
|
80
|
+
url: req.url,
|
|
81
|
+
method: req.method,
|
|
82
|
+
headers: req.headers,
|
|
83
|
+
rawBody,
|
|
84
|
+
reqId,
|
|
85
|
+
getIp,
|
|
86
|
+
getIpList,
|
|
87
|
+
};
|
|
86
88
|
}
|
|
87
89
|
|
|
88
|
-
function useHeaders() {
|
|
89
|
-
return useRequest().headers;
|
|
90
|
-
}
|
|
91
|
-
function useSetHeaders() {
|
|
92
|
-
const { store } = useHttpContext();
|
|
93
|
-
const setHeaderStore = store('setHeader');
|
|
94
|
-
function setHeader(name, value) {
|
|
95
|
-
setHeaderStore.set(name, value.toString());
|
|
96
|
-
}
|
|
97
|
-
function setContentType(value) {
|
|
98
|
-
setHeader('content-type', value);
|
|
99
|
-
}
|
|
100
|
-
function enableCors(origin = '*') {
|
|
101
|
-
setHeader('access-control-allow-origin', origin);
|
|
102
|
-
}
|
|
103
|
-
return {
|
|
104
|
-
setHeader,
|
|
105
|
-
getHeader: setHeaderStore.get,
|
|
106
|
-
removeHeader: setHeaderStore.del,
|
|
107
|
-
setContentType,
|
|
108
|
-
headers: () => setHeaderStore.value || {},
|
|
109
|
-
enableCors,
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
function useSetHeader(name) {
|
|
113
|
-
const { store } = useHttpContext();
|
|
114
|
-
const { hook } = store('setHeader');
|
|
115
|
-
return hook(name);
|
|
90
|
+
function useHeaders() {
|
|
91
|
+
return useRequest().headers;
|
|
92
|
+
}
|
|
93
|
+
function useSetHeaders() {
|
|
94
|
+
const { store } = useHttpContext();
|
|
95
|
+
const setHeaderStore = store('setHeader');
|
|
96
|
+
function setHeader(name, value) {
|
|
97
|
+
setHeaderStore.set(name, value.toString());
|
|
98
|
+
}
|
|
99
|
+
function setContentType(value) {
|
|
100
|
+
setHeader('content-type', value);
|
|
101
|
+
}
|
|
102
|
+
function enableCors(origin = '*') {
|
|
103
|
+
setHeader('access-control-allow-origin', origin);
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
setHeader,
|
|
107
|
+
getHeader: setHeaderStore.get,
|
|
108
|
+
removeHeader: setHeaderStore.del,
|
|
109
|
+
setContentType,
|
|
110
|
+
headers: () => setHeaderStore.value || {},
|
|
111
|
+
enableCors,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function useSetHeader(name) {
|
|
115
|
+
const { store } = useHttpContext();
|
|
116
|
+
const { hook } = store('setHeader');
|
|
117
|
+
return hook(name);
|
|
116
118
|
}
|
|
117
119
|
|
|
118
|
-
function useAccept() {
|
|
119
|
-
const { store } = useHttpContext();
|
|
120
|
-
const { accept } = useHeaders();
|
|
121
|
-
const accepts = (mime) => {
|
|
122
|
-
const { set, get, has } = store('accept');
|
|
123
|
-
if (!has(mime)) {
|
|
124
|
-
return set(mime, !!(accept && (accept === '*/*' || accept.indexOf(mime) >= 0)));
|
|
125
|
-
}
|
|
126
|
-
return get(mime);
|
|
127
|
-
};
|
|
128
|
-
return {
|
|
129
|
-
accept,
|
|
130
|
-
accepts,
|
|
131
|
-
acceptsJson: () => accepts('application/json'),
|
|
132
|
-
acceptsXml: () => accepts('application/xml'),
|
|
133
|
-
acceptsText: () => accepts('text/plain'),
|
|
134
|
-
acceptsHtml: () => accepts('text/html'),
|
|
135
|
-
};
|
|
120
|
+
function useAccept() {
|
|
121
|
+
const { store } = useHttpContext();
|
|
122
|
+
const { accept } = useHeaders();
|
|
123
|
+
const accepts = (mime) => {
|
|
124
|
+
const { set, get, has } = store('accept');
|
|
125
|
+
if (!has(mime)) {
|
|
126
|
+
return set(mime, !!(accept && (accept === '*/*' || accept.indexOf(mime) >= 0)));
|
|
127
|
+
}
|
|
128
|
+
return get(mime);
|
|
129
|
+
};
|
|
130
|
+
return {
|
|
131
|
+
accept,
|
|
132
|
+
accepts,
|
|
133
|
+
acceptsJson: () => accepts('application/json'),
|
|
134
|
+
acceptsXml: () => accepts('application/xml'),
|
|
135
|
+
acceptsText: () => accepts('text/plain'),
|
|
136
|
+
acceptsHtml: () => accepts('text/html'),
|
|
137
|
+
};
|
|
136
138
|
}
|
|
137
139
|
|
|
138
|
-
function useAuthorization() {
|
|
139
|
-
const { store } = useHttpContext();
|
|
140
|
-
const { authorization } = useHeaders();
|
|
141
|
-
const { init } = store('authorization');
|
|
142
|
-
const authType = () => init('type', () => {
|
|
143
|
-
if (authorization) {
|
|
144
|
-
const space = authorization.indexOf(' ');
|
|
145
|
-
return authorization.slice(0, space);
|
|
146
|
-
}
|
|
147
|
-
return null;
|
|
148
|
-
});
|
|
149
|
-
const authRawCredentials = () => init('credentials', () => {
|
|
150
|
-
if (authorization) {
|
|
151
|
-
const space = authorization.indexOf(' ');
|
|
152
|
-
return authorization.slice(space + 1);
|
|
153
|
-
}
|
|
154
|
-
return null;
|
|
155
|
-
});
|
|
156
|
-
return {
|
|
157
|
-
authorization,
|
|
158
|
-
authType,
|
|
159
|
-
authRawCredentials,
|
|
160
|
-
isBasic: () =>
|
|
161
|
-
isBearer: () =>
|
|
162
|
-
basicCredentials: () => init('basicCredentials', () => {
|
|
163
|
-
if (authorization) {
|
|
164
|
-
const type = authType();
|
|
165
|
-
if (
|
|
166
|
-
const creds = Buffer.from(authRawCredentials() || '', 'base64').toString('ascii');
|
|
167
|
-
const [username, password] = creds.split(':');
|
|
168
|
-
return { username, password };
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
return null;
|
|
172
|
-
}),
|
|
173
|
-
};
|
|
140
|
+
function useAuthorization() {
|
|
141
|
+
const { store } = useHttpContext();
|
|
142
|
+
const { authorization } = useHeaders();
|
|
143
|
+
const { init } = store('authorization');
|
|
144
|
+
const authType = () => init('type', () => {
|
|
145
|
+
if (authorization) {
|
|
146
|
+
const space = authorization.indexOf(' ');
|
|
147
|
+
return authorization.slice(0, space);
|
|
148
|
+
}
|
|
149
|
+
return null;
|
|
150
|
+
});
|
|
151
|
+
const authRawCredentials = () => init('credentials', () => {
|
|
152
|
+
if (authorization) {
|
|
153
|
+
const space = authorization.indexOf(' ');
|
|
154
|
+
return authorization.slice(space + 1);
|
|
155
|
+
}
|
|
156
|
+
return null;
|
|
157
|
+
});
|
|
158
|
+
return {
|
|
159
|
+
authorization,
|
|
160
|
+
authType,
|
|
161
|
+
authRawCredentials,
|
|
162
|
+
isBasic: () => authType()?.toLocaleLowerCase() === 'basic',
|
|
163
|
+
isBearer: () => authType()?.toLocaleLowerCase() === 'bearer',
|
|
164
|
+
basicCredentials: () => init('basicCredentials', () => {
|
|
165
|
+
if (authorization) {
|
|
166
|
+
const type = authType();
|
|
167
|
+
if (type?.toLocaleLowerCase() === 'basic') {
|
|
168
|
+
const creds = Buffer.from(authRawCredentials() || '', 'base64').toString('ascii');
|
|
169
|
+
const [username, password] = creds.split(':');
|
|
170
|
+
return { username, password };
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return null;
|
|
174
|
+
}),
|
|
175
|
+
};
|
|
174
176
|
}
|
|
175
177
|
|
|
176
|
-
function convertTime(time, unit = 'ms') {
|
|
177
|
-
if (typeof time === 'number')
|
|
178
|
-
return time / units[unit];
|
|
179
|
-
const rg = /(\d+)(\w+)/g;
|
|
180
|
-
let t = 0;
|
|
181
|
-
let r;
|
|
182
|
-
while ((r = rg.exec(time))) {
|
|
183
|
-
t += Number(r[1]) * (units[r[2]] || 0);
|
|
184
|
-
}
|
|
185
|
-
return t / units[unit];
|
|
186
|
-
}
|
|
187
|
-
const units = {
|
|
188
|
-
ms: 1,
|
|
189
|
-
s: 1000,
|
|
190
|
-
m: 1000 * 60,
|
|
191
|
-
h: 1000 * 60 * 60,
|
|
192
|
-
d: 1000 * 60 * 60 * 24,
|
|
193
|
-
w: 1000 * 60 * 60 * 24 * 7,
|
|
194
|
-
M: 1000 * 60 * 60 * 24 * 30,
|
|
195
|
-
Y: 1000 * 60 * 60 * 24 * 365,
|
|
178
|
+
function convertTime(time, unit = 'ms') {
|
|
179
|
+
if (typeof time === 'number')
|
|
180
|
+
return time / units[unit];
|
|
181
|
+
const rg = /(\d+)(\w+)/g;
|
|
182
|
+
let t = 0;
|
|
183
|
+
let r;
|
|
184
|
+
while ((r = rg.exec(time))) {
|
|
185
|
+
t += Number(r[1]) * (units[r[2]] || 0);
|
|
186
|
+
}
|
|
187
|
+
return t / units[unit];
|
|
188
|
+
}
|
|
189
|
+
const units = {
|
|
190
|
+
ms: 1,
|
|
191
|
+
s: 1000,
|
|
192
|
+
m: 1000 * 60,
|
|
193
|
+
h: 1000 * 60 * 60,
|
|
194
|
+
d: 1000 * 60 * 60 * 24,
|
|
195
|
+
w: 1000 * 60 * 60 * 24 * 7,
|
|
196
|
+
M: 1000 * 60 * 60 * 24 * 30,
|
|
197
|
+
Y: 1000 * 60 * 60 * 24 * 365,
|
|
196
198
|
};
|
|
197
199
|
|
|
198
|
-
function renderCacheControl(data) {
|
|
199
|
-
let attrs = '';
|
|
200
|
-
for (const [a, v] of Object.entries(data)) {
|
|
201
|
-
if (typeof v === 'undefined')
|
|
202
|
-
continue;
|
|
203
|
-
const func = cacheControlFunc[a];
|
|
204
|
-
if (typeof func === 'function') {
|
|
205
|
-
const val = func(v);
|
|
206
|
-
if (val) {
|
|
207
|
-
attrs += attrs ? ', ' + val : val;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
else {
|
|
211
|
-
throw new Error('Unknown Cache-Control attribute ' + a);
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
return attrs;
|
|
215
|
-
}
|
|
216
|
-
// rfc7234#section-5.2.2
|
|
217
|
-
const cacheControlFunc = {
|
|
218
|
-
mustRevalidate: (v) => v ? 'must-revalidate' : '',
|
|
219
|
-
noCache: (v) => v ? (typeof v === 'string' ? `no-cache="${v}"` : 'no-cache') : '',
|
|
220
|
-
noStore: (v) => (v ? 'no-store' : ''),
|
|
221
|
-
noTransform: (v) => (v ? 'no-transform' : ''),
|
|
222
|
-
public: (v) => (v ? 'public' : ''),
|
|
223
|
-
private: (v) => v ? (typeof v === 'string' ? `private="${v}"` : 'private') : '',
|
|
224
|
-
proxyRevalidate: (v) => v ? 'proxy-revalidate' : '',
|
|
225
|
-
maxAge: (v) => 'max-age=' + convertTime(v, 's').toString(),
|
|
226
|
-
sMaxage: (v) => 's-maxage=' + convertTime(v, 's').toString(),
|
|
200
|
+
function renderCacheControl(data) {
|
|
201
|
+
let attrs = '';
|
|
202
|
+
for (const [a, v] of Object.entries(data)) {
|
|
203
|
+
if (typeof v === 'undefined')
|
|
204
|
+
continue;
|
|
205
|
+
const func = cacheControlFunc[a];
|
|
206
|
+
if (typeof func === 'function') {
|
|
207
|
+
const val = func(v);
|
|
208
|
+
if (val) {
|
|
209
|
+
attrs += attrs ? ', ' + val : val;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
throw new Error('Unknown Cache-Control attribute ' + a);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return attrs;
|
|
217
|
+
}
|
|
218
|
+
// rfc7234#section-5.2.2
|
|
219
|
+
const cacheControlFunc = {
|
|
220
|
+
mustRevalidate: (v) => v ? 'must-revalidate' : '',
|
|
221
|
+
noCache: (v) => v ? (typeof v === 'string' ? `no-cache="${v}"` : 'no-cache') : '',
|
|
222
|
+
noStore: (v) => (v ? 'no-store' : ''),
|
|
223
|
+
noTransform: (v) => (v ? 'no-transform' : ''),
|
|
224
|
+
public: (v) => (v ? 'public' : ''),
|
|
225
|
+
private: (v) => v ? (typeof v === 'string' ? `private="${v}"` : 'private') : '',
|
|
226
|
+
proxyRevalidate: (v) => v ? 'proxy-revalidate' : '',
|
|
227
|
+
maxAge: (v) => 'max-age=' + convertTime(v, 's').toString(),
|
|
228
|
+
sMaxage: (v) => 's-maxage=' + convertTime(v, 's').toString(),
|
|
227
229
|
};
|
|
228
230
|
|
|
229
|
-
const renderAge = (v) => convertTime(v, 's').toString();
|
|
230
|
-
const renderExpires = (v) => typeof v === 'string' || typeof v === 'number'
|
|
231
|
-
? new Date(v).toUTCString()
|
|
232
|
-
: v.toUTCString();
|
|
233
|
-
const renderPragmaNoCache = (v) => (v ? 'no-cache' : '');
|
|
234
|
-
// rfc7234#section-5.2.2
|
|
235
|
-
function useSetCacheControl() {
|
|
236
|
-
const { setHeader } = useSetHeaders();
|
|
237
|
-
const setAge = (value) => {
|
|
238
|
-
setHeader('age', renderAge(value));
|
|
239
|
-
};
|
|
240
|
-
const setExpires = (value) => {
|
|
241
|
-
setHeader('expires', renderExpires(value));
|
|
242
|
-
};
|
|
243
|
-
const setPragmaNoCache = (value = true) => {
|
|
244
|
-
setHeader('pragma', renderPragmaNoCache(value));
|
|
245
|
-
};
|
|
246
|
-
const setCacheControl = (data) => {
|
|
247
|
-
setHeader('cache-control', renderCacheControl(data));
|
|
248
|
-
};
|
|
249
|
-
return {
|
|
250
|
-
setExpires,
|
|
251
|
-
setAge,
|
|
252
|
-
setPragmaNoCache,
|
|
253
|
-
setCacheControl,
|
|
254
|
-
};
|
|
231
|
+
const renderAge = (v) => convertTime(v, 's').toString();
|
|
232
|
+
const renderExpires = (v) => typeof v === 'string' || typeof v === 'number'
|
|
233
|
+
? new Date(v).toUTCString()
|
|
234
|
+
: v.toUTCString();
|
|
235
|
+
const renderPragmaNoCache = (v) => (v ? 'no-cache' : '');
|
|
236
|
+
// rfc7234#section-5.2.2
|
|
237
|
+
function useSetCacheControl() {
|
|
238
|
+
const { setHeader } = useSetHeaders();
|
|
239
|
+
const setAge = (value) => {
|
|
240
|
+
setHeader('age', renderAge(value));
|
|
241
|
+
};
|
|
242
|
+
const setExpires = (value) => {
|
|
243
|
+
setHeader('expires', renderExpires(value));
|
|
244
|
+
};
|
|
245
|
+
const setPragmaNoCache = (value = true) => {
|
|
246
|
+
setHeader('pragma', renderPragmaNoCache(value));
|
|
247
|
+
};
|
|
248
|
+
const setCacheControl = (data) => {
|
|
249
|
+
setHeader('cache-control', renderCacheControl(data));
|
|
250
|
+
};
|
|
251
|
+
return {
|
|
252
|
+
setExpires,
|
|
253
|
+
setAge,
|
|
254
|
+
setPragmaNoCache,
|
|
255
|
+
setCacheControl,
|
|
256
|
+
};
|
|
255
257
|
}
|
|
256
258
|
|
|
257
|
-
function useResponse() {
|
|
258
|
-
const { store } = useHttpContext();
|
|
259
|
-
const event = store('event');
|
|
260
|
-
const { res } = event.value;
|
|
261
|
-
const responded = store('response').hook('responded');
|
|
262
|
-
const statusCode = store('status').hook('code');
|
|
263
|
-
function status(code) {
|
|
264
|
-
return (statusCode.value = code ? code : statusCode.value);
|
|
265
|
-
}
|
|
266
|
-
const rawResponse = (options) => {
|
|
267
|
-
if (!options || !options.passthrough)
|
|
268
|
-
responded.value = true;
|
|
269
|
-
return res;
|
|
270
|
-
};
|
|
271
|
-
return {
|
|
272
|
-
rawResponse,
|
|
273
|
-
hasResponded: () => responded.value || !res.writable || res.writableEnded,
|
|
274
|
-
status: eventCore.attachHook(status, {
|
|
275
|
-
get: () => statusCode.value,
|
|
276
|
-
set: (code) => (statusCode.value = code),
|
|
277
|
-
}),
|
|
278
|
-
};
|
|
279
|
-
}
|
|
280
|
-
function useStatus() {
|
|
281
|
-
const { store } = useHttpContext();
|
|
282
|
-
return store('status').hook('code');
|
|
259
|
+
function useResponse() {
|
|
260
|
+
const { store } = useHttpContext();
|
|
261
|
+
const event = store('event');
|
|
262
|
+
const { res } = event.value;
|
|
263
|
+
const responded = store('response').hook('responded');
|
|
264
|
+
const statusCode = store('status').hook('code');
|
|
265
|
+
function status(code) {
|
|
266
|
+
return (statusCode.value = code ? code : statusCode.value);
|
|
267
|
+
}
|
|
268
|
+
const rawResponse = (options) => {
|
|
269
|
+
if (!options || !options.passthrough)
|
|
270
|
+
responded.value = true;
|
|
271
|
+
return res;
|
|
272
|
+
};
|
|
273
|
+
return {
|
|
274
|
+
rawResponse,
|
|
275
|
+
hasResponded: () => responded.value || !res.writable || res.writableEnded,
|
|
276
|
+
status: eventCore.attachHook(status, {
|
|
277
|
+
get: () => statusCode.value,
|
|
278
|
+
set: (code) => (statusCode.value = code),
|
|
279
|
+
}),
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
function useStatus() {
|
|
283
|
+
const { store } = useHttpContext();
|
|
284
|
+
return store('status').hook('code');
|
|
283
285
|
}
|
|
284
286
|
|
|
285
|
-
function renderCookie(key, data) {
|
|
286
|
-
let attrs = '';
|
|
287
|
-
for (const [a, v] of Object.entries(data.attrs)) {
|
|
288
|
-
const func = cookieAttrFunc[a];
|
|
289
|
-
if (typeof func === 'function') {
|
|
290
|
-
const val = func(v);
|
|
291
|
-
attrs += val ? '; ' + val : '';
|
|
292
|
-
}
|
|
293
|
-
else {
|
|
294
|
-
throw new Error('Unknown Set-Cookie attribute ' + a);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
return `${key}=${encodeURIComponent(data.value)}${attrs}`;
|
|
298
|
-
}
|
|
299
|
-
const cookieAttrFunc = {
|
|
300
|
-
expires: (v) => 'Expires=' +
|
|
301
|
-
(typeof v === 'string' || typeof v === 'number'
|
|
302
|
-
? new Date(v).toUTCString()
|
|
303
|
-
: v.toUTCString()),
|
|
304
|
-
maxAge: (v) => 'Max-Age=' + convertTime(v, 's').toString(),
|
|
305
|
-
domain: (v) => 'Domain=' + v,
|
|
306
|
-
path: (v) => 'Path=' + v,
|
|
307
|
-
secure: (v) => (v ? 'Secure' : ''),
|
|
308
|
-
httpOnly: (v) => (v ? 'HttpOnly' : ''),
|
|
309
|
-
sameSite: (v) => v ? 'SameSite=' + (typeof v === 'string' ? v : 'Strict') : '',
|
|
287
|
+
function renderCookie(key, data) {
|
|
288
|
+
let attrs = '';
|
|
289
|
+
for (const [a, v] of Object.entries(data.attrs)) {
|
|
290
|
+
const func = cookieAttrFunc[a];
|
|
291
|
+
if (typeof func === 'function') {
|
|
292
|
+
const val = func(v);
|
|
293
|
+
attrs += val ? '; ' + val : '';
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
throw new Error('Unknown Set-Cookie attribute ' + a);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
return `${key}=${encodeURIComponent(data.value)}${attrs}`;
|
|
300
|
+
}
|
|
301
|
+
const cookieAttrFunc = {
|
|
302
|
+
expires: (v) => 'Expires=' +
|
|
303
|
+
(typeof v === 'string' || typeof v === 'number'
|
|
304
|
+
? new Date(v).toUTCString()
|
|
305
|
+
: v.toUTCString()),
|
|
306
|
+
maxAge: (v) => 'Max-Age=' + convertTime(v, 's').toString(),
|
|
307
|
+
domain: (v) => 'Domain=' + v,
|
|
308
|
+
path: (v) => 'Path=' + v,
|
|
309
|
+
secure: (v) => (v ? 'Secure' : ''),
|
|
310
|
+
httpOnly: (v) => (v ? 'HttpOnly' : ''),
|
|
311
|
+
sameSite: (v) => v ? 'SameSite=' + (typeof v === 'string' ? v : 'Strict') : '',
|
|
310
312
|
};
|
|
311
313
|
|
|
312
|
-
function escapeRegex(s) {
|
|
313
|
-
return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
|
|
314
|
-
}
|
|
315
|
-
function safeDecode(f, v) {
|
|
316
|
-
try {
|
|
317
|
-
return f(v);
|
|
318
|
-
}
|
|
319
|
-
catch (e) {
|
|
320
|
-
return v;
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
function safeDecodeURIComponent(uri) {
|
|
324
|
-
if (uri.indexOf('%') < 0)
|
|
325
|
-
return uri;
|
|
326
|
-
return safeDecode(decodeURIComponent, uri);
|
|
314
|
+
function escapeRegex(s) {
|
|
315
|
+
return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
|
|
327
316
|
}
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
else {
|
|
341
|
-
return null;
|
|
342
|
-
}
|
|
343
|
-
});
|
|
344
|
-
return {
|
|
345
|
-
rawCookies: cookie,
|
|
346
|
-
getCookie,
|
|
347
|
-
};
|
|
348
|
-
}
|
|
349
|
-
function useSetCookies() {
|
|
350
|
-
const { store } = useHttpContext();
|
|
351
|
-
const cookiesStore = store('setCookies');
|
|
352
|
-
function setCookie(name, value, attrs) {
|
|
353
|
-
cookiesStore.set(name, {
|
|
354
|
-
value,
|
|
355
|
-
attrs: attrs || {},
|
|
356
|
-
});
|
|
357
|
-
}
|
|
358
|
-
function cookies() {
|
|
359
|
-
return cookiesStore
|
|
360
|
-
.entries()
|
|
361
|
-
.filter((a) => !!a[1])
|
|
362
|
-
.map(([key, value]) => renderCookie(key, value));
|
|
363
|
-
}
|
|
364
|
-
return {
|
|
365
|
-
setCookie,
|
|
366
|
-
getCookie: cookiesStore.get,
|
|
367
|
-
removeCookie: cookiesStore.del,
|
|
368
|
-
clearCookies: cookiesStore.clear,
|
|
369
|
-
cookies,
|
|
370
|
-
};
|
|
371
|
-
}
|
|
372
|
-
function useSetCookie(name) {
|
|
373
|
-
const { setCookie, getCookie } = useSetCookies();
|
|
374
|
-
const valueHook = eventCore.attachHook({
|
|
375
|
-
name,
|
|
376
|
-
type: 'cookie',
|
|
377
|
-
}, {
|
|
378
|
-
get: () => { var _a; return (_a = getCookie(name)) === null || _a === void 0 ? void 0 : _a.value; },
|
|
379
|
-
set: (value) => { var _a; return setCookie(name, value, (_a = getCookie(name)) === null || _a === void 0 ? void 0 : _a.attrs); },
|
|
380
|
-
});
|
|
381
|
-
return eventCore.attachHook(valueHook, {
|
|
382
|
-
get: () => { var _a; return (_a = getCookie(name)) === null || _a === void 0 ? void 0 : _a.attrs; },
|
|
383
|
-
set: (attrs) => { var _a; return setCookie(name, ((_a = getCookie(name)) === null || _a === void 0 ? void 0 : _a.value) || '', attrs); },
|
|
384
|
-
}, 'attrs');
|
|
317
|
+
function safeDecode(f, v) {
|
|
318
|
+
try {
|
|
319
|
+
return f(v);
|
|
320
|
+
}
|
|
321
|
+
catch (e) {
|
|
322
|
+
return v;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
function safeDecodeURIComponent(uri) {
|
|
326
|
+
if (uri.indexOf('%') < 0)
|
|
327
|
+
return uri;
|
|
328
|
+
return safeDecode(decodeURIComponent, uri);
|
|
385
329
|
}
|
|
386
330
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
|
|
331
|
+
function useCookies() {
|
|
332
|
+
const { store } = useHttpContext();
|
|
333
|
+
const { cookie } = useHeaders();
|
|
334
|
+
const { init } = store('cookies');
|
|
335
|
+
const getCookie = (name) => init(name, () => {
|
|
336
|
+
if (cookie) {
|
|
337
|
+
const result = new RegExp(`(?:^|; )${escapeRegex(name)}=(.*?)(?:;?$|; )`, 'i').exec(cookie);
|
|
338
|
+
return result && result[1]
|
|
339
|
+
? safeDecodeURIComponent(result[1])
|
|
340
|
+
: null;
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
return null;
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
return {
|
|
347
|
+
rawCookies: cookie,
|
|
348
|
+
getCookie,
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
function useSetCookies() {
|
|
352
|
+
const { store } = useHttpContext();
|
|
353
|
+
const cookiesStore = store('setCookies');
|
|
354
|
+
function setCookie(name, value, attrs) {
|
|
355
|
+
cookiesStore.set(name, {
|
|
356
|
+
value,
|
|
357
|
+
attrs: attrs || {},
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
function cookies() {
|
|
361
|
+
return cookiesStore
|
|
362
|
+
.entries()
|
|
363
|
+
.filter((a) => !!a[1])
|
|
364
|
+
.map(([key, value]) => renderCookie(key, value));
|
|
365
|
+
}
|
|
366
|
+
return {
|
|
367
|
+
setCookie,
|
|
368
|
+
getCookie: cookiesStore.get,
|
|
369
|
+
removeCookie: cookiesStore.del,
|
|
370
|
+
clearCookies: cookiesStore.clear,
|
|
371
|
+
cookies,
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
function useSetCookie(name) {
|
|
375
|
+
const { setCookie, getCookie } = useSetCookies();
|
|
376
|
+
const valueHook = eventCore.attachHook({
|
|
377
|
+
name,
|
|
378
|
+
type: 'cookie',
|
|
379
|
+
}, {
|
|
380
|
+
get: () => getCookie(name)?.value,
|
|
381
|
+
set: (value) => setCookie(name, value, getCookie(name)?.attrs),
|
|
382
|
+
});
|
|
383
|
+
return eventCore.attachHook(valueHook, {
|
|
384
|
+
get: () => getCookie(name)?.attrs,
|
|
385
|
+
set: (attrs) => setCookie(name, getCookie(name)?.value || '', attrs),
|
|
386
|
+
}, 'attrs');
|
|
404
387
|
}
|
|
405
388
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
}
|
|
389
|
+
class WooksURLSearchParams extends url.URLSearchParams {
|
|
390
|
+
toJson() {
|
|
391
|
+
const json = {};
|
|
392
|
+
for (const [key, value] of this.entries()) {
|
|
393
|
+
if (isArrayParam(key)) {
|
|
394
|
+
const a = (json[key] = (json[key] || []));
|
|
395
|
+
a.push(value);
|
|
396
|
+
}
|
|
397
|
+
else {
|
|
398
|
+
json[key] = value;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
return json;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
function isArrayParam(name) {
|
|
405
|
+
return name.endsWith('[]');
|
|
420
406
|
}
|
|
421
407
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
function __awaiter(thisArg, _arguments, P, generator) {
|
|
438
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
439
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
440
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
441
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
442
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
443
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
444
|
-
});
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
function __values(o) {
|
|
448
|
-
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
449
|
-
if (m) return m.call(o);
|
|
450
|
-
if (o && typeof o.length === "number") return {
|
|
451
|
-
next: function () {
|
|
452
|
-
if (o && i >= o.length) o = void 0;
|
|
453
|
-
return { value: o && o[i++], done: !o };
|
|
454
|
-
}
|
|
455
|
-
};
|
|
456
|
-
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
function __asyncValues(o) {
|
|
460
|
-
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
461
|
-
var m = o[Symbol.asyncIterator], i;
|
|
462
|
-
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
|
463
|
-
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
|
464
|
-
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
408
|
+
function useSearchParams() {
|
|
409
|
+
const { store } = useHttpContext();
|
|
410
|
+
const url = useRequest().url || '';
|
|
411
|
+
const { init } = store('searchParams');
|
|
412
|
+
const rawSearchParams = () => init('raw', () => {
|
|
413
|
+
const i = url.indexOf('?');
|
|
414
|
+
return i >= 0 ? url.slice(i) : '';
|
|
415
|
+
});
|
|
416
|
+
const urlSearchParams = () => init('urlSearchParams', () => new WooksURLSearchParams(rawSearchParams()));
|
|
417
|
+
return {
|
|
418
|
+
rawSearchParams,
|
|
419
|
+
urlSearchParams,
|
|
420
|
+
jsonSearchParams: () => urlSearchParams().toJson(),
|
|
421
|
+
};
|
|
465
422
|
}
|
|
466
423
|
|
|
467
|
-
class BaseHttpResponseRenderer {
|
|
468
|
-
render(response) {
|
|
469
|
-
if (typeof response.body === 'string' ||
|
|
470
|
-
typeof response.body === 'boolean' ||
|
|
471
|
-
typeof response.body === 'number') {
|
|
472
|
-
if (!response.getContentType())
|
|
473
|
-
response.setContentType('text/plain');
|
|
474
|
-
return response.body.toString();
|
|
475
|
-
}
|
|
476
|
-
if (typeof response.body === 'undefined') {
|
|
477
|
-
return '';
|
|
478
|
-
}
|
|
479
|
-
if (response.body instanceof Uint8Array) {
|
|
480
|
-
return response.body;
|
|
481
|
-
}
|
|
482
|
-
if (typeof response.body === 'object') {
|
|
483
|
-
if (!response.getContentType())
|
|
484
|
-
response.setContentType('application/json');
|
|
485
|
-
return JSON.stringify(response.body);
|
|
486
|
-
}
|
|
487
|
-
throw new Error('Unsupported body format "' + typeof response.body + '"');
|
|
488
|
-
}
|
|
424
|
+
class BaseHttpResponseRenderer {
|
|
425
|
+
render(response) {
|
|
426
|
+
if (typeof response.body === 'string' ||
|
|
427
|
+
typeof response.body === 'boolean' ||
|
|
428
|
+
typeof response.body === 'number') {
|
|
429
|
+
if (!response.getContentType())
|
|
430
|
+
response.setContentType('text/plain');
|
|
431
|
+
return response.body.toString();
|
|
432
|
+
}
|
|
433
|
+
if (typeof response.body === 'undefined') {
|
|
434
|
+
return '';
|
|
435
|
+
}
|
|
436
|
+
if (response.body instanceof Uint8Array) {
|
|
437
|
+
return response.body;
|
|
438
|
+
}
|
|
439
|
+
if (typeof response.body === 'object') {
|
|
440
|
+
if (!response.getContentType())
|
|
441
|
+
response.setContentType('application/json');
|
|
442
|
+
return JSON.stringify(response.body);
|
|
443
|
+
}
|
|
444
|
+
throw new Error('Unsupported body format "' + typeof response.body + '"');
|
|
445
|
+
}
|
|
489
446
|
}
|
|
490
447
|
|
|
491
|
-
const httpStatusCodes = {
|
|
492
|
-
[100]: 'Continue',
|
|
493
|
-
[101]: 'Switching protocols',
|
|
494
|
-
[102]: 'Processing',
|
|
495
|
-
[103]: 'Early Hints',
|
|
496
|
-
[200]: 'OK',
|
|
497
|
-
[201]: 'Created',
|
|
498
|
-
[202]: 'Accepted',
|
|
499
|
-
[203]: 'Non-Authoritative Information',
|
|
500
|
-
[204]: 'No Content',
|
|
501
|
-
[205]: 'Reset Content',
|
|
502
|
-
[206]: 'Partial Content',
|
|
503
|
-
[207]: 'Multi-Status',
|
|
504
|
-
[208]: 'Already Reported',
|
|
505
|
-
[226]: 'IM Used',
|
|
506
|
-
[300]: 'Multiple Choices',
|
|
507
|
-
[301]: 'Moved Permanently',
|
|
508
|
-
[302]: 'Found (Previously "Moved Temporarily")',
|
|
509
|
-
[303]: 'See Other',
|
|
510
|
-
[304]: 'Not Modified',
|
|
511
|
-
[305]: 'Use Proxy',
|
|
512
|
-
[306]: 'Switch Proxy',
|
|
513
|
-
[307]: 'Temporary Redirect',
|
|
514
|
-
[308]: 'Permanent Redirect',
|
|
515
|
-
[400]: 'Bad Request',
|
|
516
|
-
[401]: 'Unauthorized',
|
|
517
|
-
[402]: 'Payment Required',
|
|
518
|
-
[403]: 'Forbidden',
|
|
519
|
-
[404]: 'Not Found',
|
|
520
|
-
[405]: 'Method Not Allowed',
|
|
521
|
-
[406]: 'Not Acceptable',
|
|
522
|
-
[407]: 'Proxy Authentication Required',
|
|
523
|
-
[408]: 'Request Timeout',
|
|
524
|
-
[409]: 'Conflict',
|
|
525
|
-
[410]: 'Gone',
|
|
526
|
-
[411]: 'Length Required',
|
|
527
|
-
[412]: 'Precondition Failed',
|
|
528
|
-
[413]: 'Payload Too Large',
|
|
529
|
-
[414]: 'URI Too Long',
|
|
530
|
-
[415]: 'Unsupported Media Type',
|
|
531
|
-
[416]: 'Range Not Satisfiable',
|
|
532
|
-
[417]: 'Expectation Failed',
|
|
533
|
-
[418]: 'I\'m a Teapot',
|
|
534
|
-
[421]: 'Misdirected Request',
|
|
535
|
-
[422]: 'Unprocessable Entity',
|
|
536
|
-
[423]: 'Locked',
|
|
537
|
-
[424]: 'Failed Dependency',
|
|
538
|
-
[425]: 'Too Early',
|
|
539
|
-
[426]: 'Upgrade Required',
|
|
540
|
-
[428]: 'Precondition Required',
|
|
541
|
-
[429]: 'Too Many Requests',
|
|
542
|
-
[431]: 'Request Header Fields Too Large',
|
|
543
|
-
[451]: 'Unavailable For Legal Reasons',
|
|
544
|
-
[500]: 'Internal Server Error',
|
|
545
|
-
[501]: 'Not Implemented',
|
|
546
|
-
[502]: 'Bad Gateway',
|
|
547
|
-
[503]: 'Service Unavailable',
|
|
548
|
-
[504]: 'Gateway Timeout',
|
|
549
|
-
[505]: 'HTTP Version Not Supported',
|
|
550
|
-
[506]: 'Variant Also Negotiates',
|
|
551
|
-
[507]: 'Insufficient Storage',
|
|
552
|
-
[508]: 'Loop Detected',
|
|
553
|
-
[510]: 'Not Extended',
|
|
554
|
-
[511]: 'Network Authentication Required',
|
|
555
|
-
};
|
|
556
|
-
exports.EHttpStatusCode = void 0;
|
|
557
|
-
(function (EHttpStatusCode) {
|
|
558
|
-
EHttpStatusCode[EHttpStatusCode["Continue"] = 100] = "Continue";
|
|
559
|
-
EHttpStatusCode[EHttpStatusCode["SwitchingProtocols"] = 101] = "SwitchingProtocols";
|
|
560
|
-
EHttpStatusCode[EHttpStatusCode["Processing"] = 102] = "Processing";
|
|
561
|
-
EHttpStatusCode[EHttpStatusCode["EarlyHints"] = 103] = "EarlyHints";
|
|
562
|
-
EHttpStatusCode[EHttpStatusCode["OK"] = 200] = "OK";
|
|
563
|
-
EHttpStatusCode[EHttpStatusCode["Created"] = 201] = "Created";
|
|
564
|
-
EHttpStatusCode[EHttpStatusCode["Accepted"] = 202] = "Accepted";
|
|
565
|
-
EHttpStatusCode[EHttpStatusCode["NonAuthoritativeInformation"] = 203] = "NonAuthoritativeInformation";
|
|
566
|
-
EHttpStatusCode[EHttpStatusCode["NoContent"] = 204] = "NoContent";
|
|
567
|
-
EHttpStatusCode[EHttpStatusCode["ResetContent"] = 205] = "ResetContent";
|
|
568
|
-
EHttpStatusCode[EHttpStatusCode["PartialContent"] = 206] = "PartialContent";
|
|
569
|
-
EHttpStatusCode[EHttpStatusCode["MultiStatus"] = 207] = "MultiStatus";
|
|
570
|
-
EHttpStatusCode[EHttpStatusCode["AlreadyReported"] = 208] = "AlreadyReported";
|
|
571
|
-
EHttpStatusCode[EHttpStatusCode["IMUsed"] = 226] = "IMUsed";
|
|
572
|
-
EHttpStatusCode[EHttpStatusCode["MultipleChoices"] = 300] = "MultipleChoices";
|
|
573
|
-
EHttpStatusCode[EHttpStatusCode["MovedPermanently"] = 301] = "MovedPermanently";
|
|
574
|
-
EHttpStatusCode[EHttpStatusCode["Found"] = 302] = "Found";
|
|
575
|
-
EHttpStatusCode[EHttpStatusCode["SeeOther"] = 303] = "SeeOther";
|
|
576
|
-
EHttpStatusCode[EHttpStatusCode["NotModified"] = 304] = "NotModified";
|
|
577
|
-
EHttpStatusCode[EHttpStatusCode["UseProxy"] = 305] = "UseProxy";
|
|
578
|
-
EHttpStatusCode[EHttpStatusCode["SwitchProxy"] = 306] = "SwitchProxy";
|
|
579
|
-
EHttpStatusCode[EHttpStatusCode["TemporaryRedirect"] = 307] = "TemporaryRedirect";
|
|
580
|
-
EHttpStatusCode[EHttpStatusCode["PermanentRedirect"] = 308] = "PermanentRedirect";
|
|
581
|
-
EHttpStatusCode[EHttpStatusCode["BadRequest"] = 400] = "BadRequest";
|
|
582
|
-
EHttpStatusCode[EHttpStatusCode["Unauthorized"] = 401] = "Unauthorized";
|
|
583
|
-
EHttpStatusCode[EHttpStatusCode["PaymentRequired"] = 402] = "PaymentRequired";
|
|
584
|
-
EHttpStatusCode[EHttpStatusCode["Forbidden"] = 403] = "Forbidden";
|
|
585
|
-
EHttpStatusCode[EHttpStatusCode["NotFound"] = 404] = "NotFound";
|
|
586
|
-
EHttpStatusCode[EHttpStatusCode["MethodNotAllowed"] = 405] = "MethodNotAllowed";
|
|
587
|
-
EHttpStatusCode[EHttpStatusCode["NotAcceptable"] = 406] = "NotAcceptable";
|
|
588
|
-
EHttpStatusCode[EHttpStatusCode["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired";
|
|
589
|
-
EHttpStatusCode[EHttpStatusCode["RequestTimeout"] = 408] = "RequestTimeout";
|
|
590
|
-
EHttpStatusCode[EHttpStatusCode["Conflict"] = 409] = "Conflict";
|
|
591
|
-
EHttpStatusCode[EHttpStatusCode["Gone"] = 410] = "Gone";
|
|
592
|
-
EHttpStatusCode[EHttpStatusCode["LengthRequired"] = 411] = "LengthRequired";
|
|
593
|
-
EHttpStatusCode[EHttpStatusCode["PreconditionFailed"] = 412] = "PreconditionFailed";
|
|
594
|
-
EHttpStatusCode[EHttpStatusCode["PayloadTooLarge"] = 413] = "PayloadTooLarge";
|
|
595
|
-
EHttpStatusCode[EHttpStatusCode["URITooLong"] = 414] = "URITooLong";
|
|
596
|
-
EHttpStatusCode[EHttpStatusCode["UnsupportedMediaType"] = 415] = "UnsupportedMediaType";
|
|
597
|
-
EHttpStatusCode[EHttpStatusCode["RangeNotSatisfiable"] = 416] = "RangeNotSatisfiable";
|
|
598
|
-
EHttpStatusCode[EHttpStatusCode["ExpectationFailed"] = 417] = "ExpectationFailed";
|
|
599
|
-
EHttpStatusCode[EHttpStatusCode["ImATeapot"] = 418] = "ImATeapot";
|
|
600
|
-
EHttpStatusCode[EHttpStatusCode["MisdirectedRequest"] = 421] = "MisdirectedRequest";
|
|
601
|
-
EHttpStatusCode[EHttpStatusCode["UnprocessableEntity"] = 422] = "UnprocessableEntity";
|
|
602
|
-
EHttpStatusCode[EHttpStatusCode["Locked"] = 423] = "Locked";
|
|
603
|
-
EHttpStatusCode[EHttpStatusCode["FailedDependency"] = 424] = "FailedDependency";
|
|
604
|
-
EHttpStatusCode[EHttpStatusCode["TooEarly"] = 425] = "TooEarly";
|
|
605
|
-
EHttpStatusCode[EHttpStatusCode["UpgradeRequired"] = 426] = "UpgradeRequired";
|
|
606
|
-
EHttpStatusCode[EHttpStatusCode["PreconditionRequired"] = 428] = "PreconditionRequired";
|
|
607
|
-
EHttpStatusCode[EHttpStatusCode["TooManyRequests"] = 429] = "TooManyRequests";
|
|
608
|
-
EHttpStatusCode[EHttpStatusCode["RequestHeaderFieldsTooLarge"] = 431] = "RequestHeaderFieldsTooLarge";
|
|
609
|
-
EHttpStatusCode[EHttpStatusCode["UnavailableForLegalReasons"] = 451] = "UnavailableForLegalReasons";
|
|
610
|
-
EHttpStatusCode[EHttpStatusCode["InternalServerError"] = 500] = "InternalServerError";
|
|
611
|
-
EHttpStatusCode[EHttpStatusCode["NotImplemented"] = 501] = "NotImplemented";
|
|
612
|
-
EHttpStatusCode[EHttpStatusCode["BadGateway"] = 502] = "BadGateway";
|
|
613
|
-
EHttpStatusCode[EHttpStatusCode["ServiceUnavailable"] = 503] = "ServiceUnavailable";
|
|
614
|
-
EHttpStatusCode[EHttpStatusCode["GatewayTimeout"] = 504] = "GatewayTimeout";
|
|
615
|
-
EHttpStatusCode[EHttpStatusCode["HTTPVersionNotSupported"] = 505] = "HTTPVersionNotSupported";
|
|
616
|
-
EHttpStatusCode[EHttpStatusCode["VariantAlsoNegotiates"] = 506] = "VariantAlsoNegotiates";
|
|
617
|
-
EHttpStatusCode[EHttpStatusCode["InsufficientStorage"] = 507] = "InsufficientStorage";
|
|
618
|
-
EHttpStatusCode[EHttpStatusCode["LoopDetected"] = 508] = "LoopDetected";
|
|
619
|
-
EHttpStatusCode[EHttpStatusCode["NotExtended"] = 510] = "NotExtended";
|
|
620
|
-
EHttpStatusCode[EHttpStatusCode["NetworkAuthenticationRequired"] = 511] = "NetworkAuthenticationRequired";
|
|
448
|
+
const httpStatusCodes = {
|
|
449
|
+
[100]: 'Continue',
|
|
450
|
+
[101]: 'Switching protocols',
|
|
451
|
+
[102]: 'Processing',
|
|
452
|
+
[103]: 'Early Hints',
|
|
453
|
+
[200]: 'OK',
|
|
454
|
+
[201]: 'Created',
|
|
455
|
+
[202]: 'Accepted',
|
|
456
|
+
[203]: 'Non-Authoritative Information',
|
|
457
|
+
[204]: 'No Content',
|
|
458
|
+
[205]: 'Reset Content',
|
|
459
|
+
[206]: 'Partial Content',
|
|
460
|
+
[207]: 'Multi-Status',
|
|
461
|
+
[208]: 'Already Reported',
|
|
462
|
+
[226]: 'IM Used',
|
|
463
|
+
[300]: 'Multiple Choices',
|
|
464
|
+
[301]: 'Moved Permanently',
|
|
465
|
+
[302]: 'Found (Previously "Moved Temporarily")',
|
|
466
|
+
[303]: 'See Other',
|
|
467
|
+
[304]: 'Not Modified',
|
|
468
|
+
[305]: 'Use Proxy',
|
|
469
|
+
[306]: 'Switch Proxy',
|
|
470
|
+
[307]: 'Temporary Redirect',
|
|
471
|
+
[308]: 'Permanent Redirect',
|
|
472
|
+
[400]: 'Bad Request',
|
|
473
|
+
[401]: 'Unauthorized',
|
|
474
|
+
[402]: 'Payment Required',
|
|
475
|
+
[403]: 'Forbidden',
|
|
476
|
+
[404]: 'Not Found',
|
|
477
|
+
[405]: 'Method Not Allowed',
|
|
478
|
+
[406]: 'Not Acceptable',
|
|
479
|
+
[407]: 'Proxy Authentication Required',
|
|
480
|
+
[408]: 'Request Timeout',
|
|
481
|
+
[409]: 'Conflict',
|
|
482
|
+
[410]: 'Gone',
|
|
483
|
+
[411]: 'Length Required',
|
|
484
|
+
[412]: 'Precondition Failed',
|
|
485
|
+
[413]: 'Payload Too Large',
|
|
486
|
+
[414]: 'URI Too Long',
|
|
487
|
+
[415]: 'Unsupported Media Type',
|
|
488
|
+
[416]: 'Range Not Satisfiable',
|
|
489
|
+
[417]: 'Expectation Failed',
|
|
490
|
+
[418]: 'I\'m a Teapot',
|
|
491
|
+
[421]: 'Misdirected Request',
|
|
492
|
+
[422]: 'Unprocessable Entity',
|
|
493
|
+
[423]: 'Locked',
|
|
494
|
+
[424]: 'Failed Dependency',
|
|
495
|
+
[425]: 'Too Early',
|
|
496
|
+
[426]: 'Upgrade Required',
|
|
497
|
+
[428]: 'Precondition Required',
|
|
498
|
+
[429]: 'Too Many Requests',
|
|
499
|
+
[431]: 'Request Header Fields Too Large',
|
|
500
|
+
[451]: 'Unavailable For Legal Reasons',
|
|
501
|
+
[500]: 'Internal Server Error',
|
|
502
|
+
[501]: 'Not Implemented',
|
|
503
|
+
[502]: 'Bad Gateway',
|
|
504
|
+
[503]: 'Service Unavailable',
|
|
505
|
+
[504]: 'Gateway Timeout',
|
|
506
|
+
[505]: 'HTTP Version Not Supported',
|
|
507
|
+
[506]: 'Variant Also Negotiates',
|
|
508
|
+
[507]: 'Insufficient Storage',
|
|
509
|
+
[508]: 'Loop Detected',
|
|
510
|
+
[510]: 'Not Extended',
|
|
511
|
+
[511]: 'Network Authentication Required',
|
|
512
|
+
};
|
|
513
|
+
exports.EHttpStatusCode = void 0;
|
|
514
|
+
(function (EHttpStatusCode) {
|
|
515
|
+
EHttpStatusCode[EHttpStatusCode["Continue"] = 100] = "Continue";
|
|
516
|
+
EHttpStatusCode[EHttpStatusCode["SwitchingProtocols"] = 101] = "SwitchingProtocols";
|
|
517
|
+
EHttpStatusCode[EHttpStatusCode["Processing"] = 102] = "Processing";
|
|
518
|
+
EHttpStatusCode[EHttpStatusCode["EarlyHints"] = 103] = "EarlyHints";
|
|
519
|
+
EHttpStatusCode[EHttpStatusCode["OK"] = 200] = "OK";
|
|
520
|
+
EHttpStatusCode[EHttpStatusCode["Created"] = 201] = "Created";
|
|
521
|
+
EHttpStatusCode[EHttpStatusCode["Accepted"] = 202] = "Accepted";
|
|
522
|
+
EHttpStatusCode[EHttpStatusCode["NonAuthoritativeInformation"] = 203] = "NonAuthoritativeInformation";
|
|
523
|
+
EHttpStatusCode[EHttpStatusCode["NoContent"] = 204] = "NoContent";
|
|
524
|
+
EHttpStatusCode[EHttpStatusCode["ResetContent"] = 205] = "ResetContent";
|
|
525
|
+
EHttpStatusCode[EHttpStatusCode["PartialContent"] = 206] = "PartialContent";
|
|
526
|
+
EHttpStatusCode[EHttpStatusCode["MultiStatus"] = 207] = "MultiStatus";
|
|
527
|
+
EHttpStatusCode[EHttpStatusCode["AlreadyReported"] = 208] = "AlreadyReported";
|
|
528
|
+
EHttpStatusCode[EHttpStatusCode["IMUsed"] = 226] = "IMUsed";
|
|
529
|
+
EHttpStatusCode[EHttpStatusCode["MultipleChoices"] = 300] = "MultipleChoices";
|
|
530
|
+
EHttpStatusCode[EHttpStatusCode["MovedPermanently"] = 301] = "MovedPermanently";
|
|
531
|
+
EHttpStatusCode[EHttpStatusCode["Found"] = 302] = "Found";
|
|
532
|
+
EHttpStatusCode[EHttpStatusCode["SeeOther"] = 303] = "SeeOther";
|
|
533
|
+
EHttpStatusCode[EHttpStatusCode["NotModified"] = 304] = "NotModified";
|
|
534
|
+
EHttpStatusCode[EHttpStatusCode["UseProxy"] = 305] = "UseProxy";
|
|
535
|
+
EHttpStatusCode[EHttpStatusCode["SwitchProxy"] = 306] = "SwitchProxy";
|
|
536
|
+
EHttpStatusCode[EHttpStatusCode["TemporaryRedirect"] = 307] = "TemporaryRedirect";
|
|
537
|
+
EHttpStatusCode[EHttpStatusCode["PermanentRedirect"] = 308] = "PermanentRedirect";
|
|
538
|
+
EHttpStatusCode[EHttpStatusCode["BadRequest"] = 400] = "BadRequest";
|
|
539
|
+
EHttpStatusCode[EHttpStatusCode["Unauthorized"] = 401] = "Unauthorized";
|
|
540
|
+
EHttpStatusCode[EHttpStatusCode["PaymentRequired"] = 402] = "PaymentRequired";
|
|
541
|
+
EHttpStatusCode[EHttpStatusCode["Forbidden"] = 403] = "Forbidden";
|
|
542
|
+
EHttpStatusCode[EHttpStatusCode["NotFound"] = 404] = "NotFound";
|
|
543
|
+
EHttpStatusCode[EHttpStatusCode["MethodNotAllowed"] = 405] = "MethodNotAllowed";
|
|
544
|
+
EHttpStatusCode[EHttpStatusCode["NotAcceptable"] = 406] = "NotAcceptable";
|
|
545
|
+
EHttpStatusCode[EHttpStatusCode["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired";
|
|
546
|
+
EHttpStatusCode[EHttpStatusCode["RequestTimeout"] = 408] = "RequestTimeout";
|
|
547
|
+
EHttpStatusCode[EHttpStatusCode["Conflict"] = 409] = "Conflict";
|
|
548
|
+
EHttpStatusCode[EHttpStatusCode["Gone"] = 410] = "Gone";
|
|
549
|
+
EHttpStatusCode[EHttpStatusCode["LengthRequired"] = 411] = "LengthRequired";
|
|
550
|
+
EHttpStatusCode[EHttpStatusCode["PreconditionFailed"] = 412] = "PreconditionFailed";
|
|
551
|
+
EHttpStatusCode[EHttpStatusCode["PayloadTooLarge"] = 413] = "PayloadTooLarge";
|
|
552
|
+
EHttpStatusCode[EHttpStatusCode["URITooLong"] = 414] = "URITooLong";
|
|
553
|
+
EHttpStatusCode[EHttpStatusCode["UnsupportedMediaType"] = 415] = "UnsupportedMediaType";
|
|
554
|
+
EHttpStatusCode[EHttpStatusCode["RangeNotSatisfiable"] = 416] = "RangeNotSatisfiable";
|
|
555
|
+
EHttpStatusCode[EHttpStatusCode["ExpectationFailed"] = 417] = "ExpectationFailed";
|
|
556
|
+
EHttpStatusCode[EHttpStatusCode["ImATeapot"] = 418] = "ImATeapot";
|
|
557
|
+
EHttpStatusCode[EHttpStatusCode["MisdirectedRequest"] = 421] = "MisdirectedRequest";
|
|
558
|
+
EHttpStatusCode[EHttpStatusCode["UnprocessableEntity"] = 422] = "UnprocessableEntity";
|
|
559
|
+
EHttpStatusCode[EHttpStatusCode["Locked"] = 423] = "Locked";
|
|
560
|
+
EHttpStatusCode[EHttpStatusCode["FailedDependency"] = 424] = "FailedDependency";
|
|
561
|
+
EHttpStatusCode[EHttpStatusCode["TooEarly"] = 425] = "TooEarly";
|
|
562
|
+
EHttpStatusCode[EHttpStatusCode["UpgradeRequired"] = 426] = "UpgradeRequired";
|
|
563
|
+
EHttpStatusCode[EHttpStatusCode["PreconditionRequired"] = 428] = "PreconditionRequired";
|
|
564
|
+
EHttpStatusCode[EHttpStatusCode["TooManyRequests"] = 429] = "TooManyRequests";
|
|
565
|
+
EHttpStatusCode[EHttpStatusCode["RequestHeaderFieldsTooLarge"] = 431] = "RequestHeaderFieldsTooLarge";
|
|
566
|
+
EHttpStatusCode[EHttpStatusCode["UnavailableForLegalReasons"] = 451] = "UnavailableForLegalReasons";
|
|
567
|
+
EHttpStatusCode[EHttpStatusCode["InternalServerError"] = 500] = "InternalServerError";
|
|
568
|
+
EHttpStatusCode[EHttpStatusCode["NotImplemented"] = 501] = "NotImplemented";
|
|
569
|
+
EHttpStatusCode[EHttpStatusCode["BadGateway"] = 502] = "BadGateway";
|
|
570
|
+
EHttpStatusCode[EHttpStatusCode["ServiceUnavailable"] = 503] = "ServiceUnavailable";
|
|
571
|
+
EHttpStatusCode[EHttpStatusCode["GatewayTimeout"] = 504] = "GatewayTimeout";
|
|
572
|
+
EHttpStatusCode[EHttpStatusCode["HTTPVersionNotSupported"] = 505] = "HTTPVersionNotSupported";
|
|
573
|
+
EHttpStatusCode[EHttpStatusCode["VariantAlsoNegotiates"] = 506] = "VariantAlsoNegotiates";
|
|
574
|
+
EHttpStatusCode[EHttpStatusCode["InsufficientStorage"] = 507] = "InsufficientStorage";
|
|
575
|
+
EHttpStatusCode[EHttpStatusCode["LoopDetected"] = 508] = "LoopDetected";
|
|
576
|
+
EHttpStatusCode[EHttpStatusCode["NotExtended"] = 510] = "NotExtended";
|
|
577
|
+
EHttpStatusCode[EHttpStatusCode["NetworkAuthenticationRequired"] = 511] = "NetworkAuthenticationRequired";
|
|
621
578
|
})(exports.EHttpStatusCode || (exports.EHttpStatusCode = {}));
|
|
622
579
|
|
|
623
|
-
const defaultStatus = {
|
|
624
|
-
GET: exports.EHttpStatusCode.OK,
|
|
625
|
-
POST: exports.EHttpStatusCode.Created,
|
|
626
|
-
PUT: exports.EHttpStatusCode.Created,
|
|
627
|
-
PATCH: exports.EHttpStatusCode.Accepted,
|
|
628
|
-
DELETE: exports.EHttpStatusCode.Accepted,
|
|
629
|
-
};
|
|
630
|
-
const baseRenderer = new BaseHttpResponseRenderer();
|
|
631
|
-
class BaseHttpResponse {
|
|
632
|
-
constructor(renderer = baseRenderer) {
|
|
633
|
-
this.renderer = renderer;
|
|
634
|
-
this._status = 0;
|
|
635
|
-
this._headers = {};
|
|
636
|
-
}
|
|
637
|
-
get status() {
|
|
638
|
-
return this._status;
|
|
639
|
-
}
|
|
640
|
-
set status(value) {
|
|
641
|
-
this._status = value;
|
|
642
|
-
}
|
|
643
|
-
get body() {
|
|
644
|
-
return this._body;
|
|
645
|
-
}
|
|
646
|
-
set body(value) {
|
|
647
|
-
this._body = value;
|
|
648
|
-
}
|
|
649
|
-
setStatus(value) {
|
|
650
|
-
this.status = value;
|
|
651
|
-
return this;
|
|
652
|
-
}
|
|
653
|
-
setBody(value) {
|
|
654
|
-
this.body = value;
|
|
655
|
-
return this;
|
|
656
|
-
}
|
|
657
|
-
getContentType() {
|
|
658
|
-
return this._headers['content-type'];
|
|
659
|
-
}
|
|
660
|
-
setContentType(value) {
|
|
661
|
-
this._headers['content-type'] = value;
|
|
662
|
-
return this;
|
|
663
|
-
}
|
|
664
|
-
enableCors(origin = '*') {
|
|
665
|
-
this._headers['Access-Control-Allow-Origin'] = origin;
|
|
666
|
-
return this;
|
|
667
|
-
}
|
|
668
|
-
setCookie(name, value, attrs) {
|
|
669
|
-
const cookies = (this._headers['set-cookie'] = (this._headers['set-cookie'] || []));
|
|
670
|
-
cookies.push(renderCookie(name, { value, attrs: attrs || {} }));
|
|
671
|
-
return this;
|
|
672
|
-
}
|
|
673
|
-
setCacheControl(data) {
|
|
674
|
-
this.setHeader('cache-control', renderCacheControl(data));
|
|
675
|
-
}
|
|
676
|
-
setCookieRaw(rawValue) {
|
|
677
|
-
const cookies = (this._headers['set-cookie'] = (this._headers['set-cookie'] || []));
|
|
678
|
-
cookies.push(rawValue);
|
|
679
|
-
return this;
|
|
680
|
-
}
|
|
681
|
-
header(name, value) {
|
|
682
|
-
this._headers[name] = value;
|
|
683
|
-
return this;
|
|
684
|
-
}
|
|
685
|
-
setHeader(name, value) {
|
|
686
|
-
return this.header(name, value);
|
|
687
|
-
}
|
|
688
|
-
getHeader(name) {
|
|
689
|
-
return this._headers[name];
|
|
690
|
-
}
|
|
691
|
-
mergeHeaders() {
|
|
692
|
-
const { headers } = useSetHeaders();
|
|
693
|
-
const { cookies, removeCookie } = useSetCookies();
|
|
694
|
-
const newCookies = this._headers['set-cookie'] || [];
|
|
695
|
-
for (const cookie of newCookies) {
|
|
696
|
-
removeCookie(cookie.slice(0, cookie.indexOf('=')));
|
|
697
|
-
}
|
|
698
|
-
this._headers =
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
this.
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
stream.
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
|
|
808
|
-
}
|
|
809
|
-
finally { if (e_1) throw e_1.error; }
|
|
810
|
-
}
|
|
811
|
-
}
|
|
812
|
-
catch (e) {
|
|
813
|
-
// ?
|
|
814
|
-
}
|
|
815
|
-
}
|
|
816
|
-
res.end();
|
|
817
|
-
});
|
|
580
|
+
const defaultStatus = {
|
|
581
|
+
GET: exports.EHttpStatusCode.OK,
|
|
582
|
+
POST: exports.EHttpStatusCode.Created,
|
|
583
|
+
PUT: exports.EHttpStatusCode.Created,
|
|
584
|
+
PATCH: exports.EHttpStatusCode.Accepted,
|
|
585
|
+
DELETE: exports.EHttpStatusCode.Accepted,
|
|
586
|
+
};
|
|
587
|
+
const baseRenderer = new BaseHttpResponseRenderer();
|
|
588
|
+
class BaseHttpResponse {
|
|
589
|
+
constructor(renderer = baseRenderer) {
|
|
590
|
+
this.renderer = renderer;
|
|
591
|
+
this._status = 0;
|
|
592
|
+
this._headers = {};
|
|
593
|
+
}
|
|
594
|
+
get status() {
|
|
595
|
+
return this._status;
|
|
596
|
+
}
|
|
597
|
+
set status(value) {
|
|
598
|
+
this._status = value;
|
|
599
|
+
}
|
|
600
|
+
get body() {
|
|
601
|
+
return this._body;
|
|
602
|
+
}
|
|
603
|
+
set body(value) {
|
|
604
|
+
this._body = value;
|
|
605
|
+
}
|
|
606
|
+
setStatus(value) {
|
|
607
|
+
this.status = value;
|
|
608
|
+
return this;
|
|
609
|
+
}
|
|
610
|
+
setBody(value) {
|
|
611
|
+
this.body = value;
|
|
612
|
+
return this;
|
|
613
|
+
}
|
|
614
|
+
getContentType() {
|
|
615
|
+
return this._headers['content-type'];
|
|
616
|
+
}
|
|
617
|
+
setContentType(value) {
|
|
618
|
+
this._headers['content-type'] = value;
|
|
619
|
+
return this;
|
|
620
|
+
}
|
|
621
|
+
enableCors(origin = '*') {
|
|
622
|
+
this._headers['Access-Control-Allow-Origin'] = origin;
|
|
623
|
+
return this;
|
|
624
|
+
}
|
|
625
|
+
setCookie(name, value, attrs) {
|
|
626
|
+
const cookies = (this._headers['set-cookie'] = (this._headers['set-cookie'] || []));
|
|
627
|
+
cookies.push(renderCookie(name, { value, attrs: attrs || {} }));
|
|
628
|
+
return this;
|
|
629
|
+
}
|
|
630
|
+
setCacheControl(data) {
|
|
631
|
+
this.setHeader('cache-control', renderCacheControl(data));
|
|
632
|
+
}
|
|
633
|
+
setCookieRaw(rawValue) {
|
|
634
|
+
const cookies = (this._headers['set-cookie'] = (this._headers['set-cookie'] || []));
|
|
635
|
+
cookies.push(rawValue);
|
|
636
|
+
return this;
|
|
637
|
+
}
|
|
638
|
+
header(name, value) {
|
|
639
|
+
this._headers[name] = value;
|
|
640
|
+
return this;
|
|
641
|
+
}
|
|
642
|
+
setHeader(name, value) {
|
|
643
|
+
return this.header(name, value);
|
|
644
|
+
}
|
|
645
|
+
getHeader(name) {
|
|
646
|
+
return this._headers[name];
|
|
647
|
+
}
|
|
648
|
+
mergeHeaders() {
|
|
649
|
+
const { headers } = useSetHeaders();
|
|
650
|
+
const { cookies, removeCookie } = useSetCookies();
|
|
651
|
+
const newCookies = this._headers['set-cookie'] || [];
|
|
652
|
+
for (const cookie of newCookies) {
|
|
653
|
+
removeCookie(cookie.slice(0, cookie.indexOf('=')));
|
|
654
|
+
}
|
|
655
|
+
this._headers = {
|
|
656
|
+
...headers(),
|
|
657
|
+
...this._headers,
|
|
658
|
+
};
|
|
659
|
+
const setCookie = [...newCookies, ...cookies()];
|
|
660
|
+
if (setCookie && setCookie.length) {
|
|
661
|
+
this._headers['set-cookie'] = setCookie;
|
|
662
|
+
}
|
|
663
|
+
return this;
|
|
664
|
+
}
|
|
665
|
+
mergeStatus(renderedBody) {
|
|
666
|
+
this.status = this.status || useResponse().status();
|
|
667
|
+
if (!this.status) {
|
|
668
|
+
const { method } = useRequest();
|
|
669
|
+
this.status = renderedBody
|
|
670
|
+
? defaultStatus[method] || exports.EHttpStatusCode.OK
|
|
671
|
+
: exports.EHttpStatusCode.NoContent;
|
|
672
|
+
}
|
|
673
|
+
return this;
|
|
674
|
+
}
|
|
675
|
+
mergeFetchStatus(fetchStatus) {
|
|
676
|
+
this.status = this.status || useResponse().status() || fetchStatus;
|
|
677
|
+
}
|
|
678
|
+
panic(text, logger) {
|
|
679
|
+
const error = new Error(text);
|
|
680
|
+
logger.error(error);
|
|
681
|
+
throw error;
|
|
682
|
+
}
|
|
683
|
+
async respond() {
|
|
684
|
+
const { rawResponse, hasResponded } = useResponse();
|
|
685
|
+
const { method, rawRequest } = useRequest();
|
|
686
|
+
const logger = eventCore.useEventLogger('http-response');
|
|
687
|
+
if (hasResponded()) {
|
|
688
|
+
this.panic('The response was already sent.', logger);
|
|
689
|
+
}
|
|
690
|
+
this.mergeHeaders();
|
|
691
|
+
const res = rawResponse();
|
|
692
|
+
if (this.body instanceof stream.Readable) {
|
|
693
|
+
// responding with readable stream
|
|
694
|
+
const stream = this.body;
|
|
695
|
+
this.mergeStatus('ok');
|
|
696
|
+
res.writeHead(this.status, {
|
|
697
|
+
...this._headers,
|
|
698
|
+
});
|
|
699
|
+
rawRequest.once('close', () => {
|
|
700
|
+
stream.destroy();
|
|
701
|
+
});
|
|
702
|
+
if (method === 'HEAD') {
|
|
703
|
+
stream.destroy();
|
|
704
|
+
res.end();
|
|
705
|
+
}
|
|
706
|
+
else {
|
|
707
|
+
return new Promise((resolve, reject) => {
|
|
708
|
+
stream.on('error', (e) => {
|
|
709
|
+
stream.destroy();
|
|
710
|
+
res.end();
|
|
711
|
+
reject(e);
|
|
712
|
+
});
|
|
713
|
+
stream.on('close', () => {
|
|
714
|
+
stream.destroy();
|
|
715
|
+
resolve(undefined);
|
|
716
|
+
});
|
|
717
|
+
stream.pipe(res);
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
else if (globalThis.Response &&
|
|
722
|
+
this.body instanceof Response /* Fetch Response */) {
|
|
723
|
+
this.mergeFetchStatus(this.body.status);
|
|
724
|
+
if (method === 'HEAD') {
|
|
725
|
+
res.end();
|
|
726
|
+
}
|
|
727
|
+
else {
|
|
728
|
+
const additionalHeaders = {};
|
|
729
|
+
if (this.body.headers.get('content-length')) {
|
|
730
|
+
additionalHeaders['content-length'] = this.body.headers.get('content-length');
|
|
731
|
+
}
|
|
732
|
+
if (this.body.headers.get('content-type')) {
|
|
733
|
+
additionalHeaders['content-type'] = this.body.headers.get('content-type');
|
|
734
|
+
}
|
|
735
|
+
res.writeHead(this.status, {
|
|
736
|
+
...additionalHeaders,
|
|
737
|
+
...this._headers,
|
|
738
|
+
});
|
|
739
|
+
await respondWithFetch(this.body.body, res);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
else {
|
|
743
|
+
const renderedBody = this.renderer.render(this);
|
|
744
|
+
this.mergeStatus(renderedBody);
|
|
745
|
+
res.writeHead(this.status, {
|
|
746
|
+
'content-length': Buffer.byteLength(renderedBody),
|
|
747
|
+
...this._headers,
|
|
748
|
+
}).end(method !== 'HEAD' ? renderedBody : '');
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
async function respondWithFetch(fetchBody, res) {
|
|
753
|
+
if (fetchBody) {
|
|
754
|
+
try {
|
|
755
|
+
for await (const chunk of fetchBody) {
|
|
756
|
+
res.write(chunk);
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
catch (e) {
|
|
760
|
+
// ?
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
res.end();
|
|
818
764
|
}
|
|
819
765
|
|
|
820
|
-
const preStyles = 'font-family: monospace;' +
|
|
821
|
-
'width: 100%;' +
|
|
822
|
-
'max-width: 900px;' +
|
|
823
|
-
'padding: 10px;' +
|
|
824
|
-
'margin: 20px auto;' +
|
|
825
|
-
'border-radius: 8px;' +
|
|
826
|
-
'background-color: #494949;' +
|
|
827
|
-
'box-shadow: 0px 0px 3px 2px rgb(255 255 255 / 20%);';
|
|
828
|
-
class HttpErrorRenderer extends BaseHttpResponseRenderer {
|
|
829
|
-
renderHtml(response) {
|
|
830
|
-
const data = response.body || {};
|
|
831
|
-
response.setContentType('text/html');
|
|
832
|
-
const keys = Object.keys(data).filter((key) => !['statusCode', 'error', 'message'].includes(key));
|
|
833
|
-
return ('<html style="background-color: #333; color: #bbb;">' +
|
|
834
|
-
`<head><title>${data.statusCode} ${httpStatusCodes[data.statusCode]}</title></head>` +
|
|
835
|
-
`<body><center><h1>${data.statusCode} ${httpStatusCodes[data.statusCode]}</h1></center>` +
|
|
836
|
-
`<center><h4>${data.message}</h1></center><hr color="#666">` +
|
|
837
|
-
`<center style="color: #666;"> Wooks v${"0.4.
|
|
838
|
-
`${keys.length
|
|
839
|
-
? `<pre style="${preStyles}">${JSON.stringify(
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
return this.renderJson(response);
|
|
881
|
-
}
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
766
|
+
const preStyles = 'font-family: monospace;' +
|
|
767
|
+
'width: 100%;' +
|
|
768
|
+
'max-width: 900px;' +
|
|
769
|
+
'padding: 10px;' +
|
|
770
|
+
'margin: 20px auto;' +
|
|
771
|
+
'border-radius: 8px;' +
|
|
772
|
+
'background-color: #494949;' +
|
|
773
|
+
'box-shadow: 0px 0px 3px 2px rgb(255 255 255 / 20%);';
|
|
774
|
+
class HttpErrorRenderer extends BaseHttpResponseRenderer {
|
|
775
|
+
renderHtml(response) {
|
|
776
|
+
const data = response.body || {};
|
|
777
|
+
response.setContentType('text/html');
|
|
778
|
+
const keys = Object.keys(data).filter((key) => !['statusCode', 'error', 'message'].includes(key));
|
|
779
|
+
return ('<html style="background-color: #333; color: #bbb;">' +
|
|
780
|
+
`<head><title>${data.statusCode} ${httpStatusCodes[data.statusCode]}</title></head>` +
|
|
781
|
+
`<body><center><h1>${data.statusCode} ${httpStatusCodes[data.statusCode]}</h1></center>` +
|
|
782
|
+
`<center><h4>${data.message}</h1></center><hr color="#666">` +
|
|
783
|
+
`<center style="color: #666;"> Wooks v${"0.4.11"} </center>` +
|
|
784
|
+
`${keys.length
|
|
785
|
+
? `<pre style="${preStyles}">${JSON.stringify({
|
|
786
|
+
...data,
|
|
787
|
+
statusCode: undefined,
|
|
788
|
+
message: undefined,
|
|
789
|
+
error: undefined,
|
|
790
|
+
}, null, ' ')}</pre>`
|
|
791
|
+
: ''}` +
|
|
792
|
+
'</body></html>');
|
|
793
|
+
}
|
|
794
|
+
renderText(response) {
|
|
795
|
+
const data = response.body || {};
|
|
796
|
+
response.setContentType('text/plain');
|
|
797
|
+
const keys = Object.keys(data).filter((key) => !['statusCode', 'error', 'message'].includes(key));
|
|
798
|
+
return (`${data.statusCode} ${httpStatusCodes[data.statusCode]}\n${data.message}` +
|
|
799
|
+
`\n\n${keys.length
|
|
800
|
+
? `${JSON.stringify({
|
|
801
|
+
...data,
|
|
802
|
+
statusCode: undefined,
|
|
803
|
+
message: undefined,
|
|
804
|
+
error: undefined,
|
|
805
|
+
}, null, ' ')}`
|
|
806
|
+
: ''}`);
|
|
807
|
+
}
|
|
808
|
+
renderJson(response) {
|
|
809
|
+
const data = response.body || {};
|
|
810
|
+
response.setContentType('application/json');
|
|
811
|
+
const keys = Object.keys(data).filter((key) => !['statusCode', 'error', 'message'].includes(key));
|
|
812
|
+
return (`{"statusCode":${escapeQuotes(data.statusCode)},` +
|
|
813
|
+
`"error":"${escapeQuotes(data.error)}",` +
|
|
814
|
+
`"message":"${escapeQuotes(data.message)}"` +
|
|
815
|
+
`${keys.length
|
|
816
|
+
? ',' +
|
|
817
|
+
keys
|
|
818
|
+
.map((k) => `"${escapeQuotes(k)}":${JSON.stringify(data[k])}`)
|
|
819
|
+
.join(',')
|
|
820
|
+
: ''}}`);
|
|
821
|
+
}
|
|
822
|
+
render(response) {
|
|
823
|
+
const { acceptsJson, acceptsText, acceptsHtml } = useAccept();
|
|
824
|
+
response.status = response.body?.statusCode || 500;
|
|
825
|
+
if (acceptsJson()) {
|
|
826
|
+
return this.renderJson(response);
|
|
827
|
+
}
|
|
828
|
+
else if (acceptsHtml()) {
|
|
829
|
+
return this.renderHtml(response);
|
|
830
|
+
}
|
|
831
|
+
else if (acceptsText()) {
|
|
832
|
+
return this.renderText(response);
|
|
833
|
+
}
|
|
834
|
+
else {
|
|
835
|
+
return this.renderJson(response);
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
function escapeQuotes(s) {
|
|
840
|
+
return (typeof s === 'number' ? s : s || '')
|
|
841
|
+
.toString()
|
|
842
|
+
.replace(/[\""]/g, '\\"');
|
|
888
843
|
}
|
|
889
844
|
|
|
890
|
-
class HttpError extends Error {
|
|
891
|
-
constructor(code = 500, _body = '') {
|
|
892
|
-
super(typeof _body === 'string' ? _body : _body.message);
|
|
893
|
-
this.code = code;
|
|
894
|
-
this._body = _body;
|
|
895
|
-
}
|
|
896
|
-
get body() {
|
|
897
|
-
return typeof this._body === 'string'
|
|
898
|
-
? {
|
|
899
|
-
statusCode: this.code,
|
|
900
|
-
message: this.message,
|
|
901
|
-
error: httpStatusCodes[this.code],
|
|
902
|
-
}
|
|
903
|
-
:
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
845
|
+
class HttpError extends Error {
|
|
846
|
+
constructor(code = 500, _body = '') {
|
|
847
|
+
super(typeof _body === 'string' ? _body : _body.message);
|
|
848
|
+
this.code = code;
|
|
849
|
+
this._body = _body;
|
|
850
|
+
}
|
|
851
|
+
get body() {
|
|
852
|
+
return typeof this._body === 'string'
|
|
853
|
+
? {
|
|
854
|
+
statusCode: this.code,
|
|
855
|
+
message: this.message,
|
|
856
|
+
error: httpStatusCodes[this.code],
|
|
857
|
+
}
|
|
858
|
+
: {
|
|
859
|
+
...this._body,
|
|
860
|
+
statusCode: this.code,
|
|
861
|
+
message: this.message,
|
|
862
|
+
error: httpStatusCodes[this.code],
|
|
863
|
+
};
|
|
864
|
+
}
|
|
865
|
+
attachRenderer(renderer) {
|
|
866
|
+
this.renderer = renderer;
|
|
867
|
+
}
|
|
868
|
+
getRenderer() {
|
|
869
|
+
return this.renderer;
|
|
870
|
+
}
|
|
911
871
|
}
|
|
912
872
|
|
|
913
|
-
function createWooksResponder(
|
|
914
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
915
|
-
renderer = new BaseHttpResponseRenderer(),
|
|
916
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
917
|
-
errorRenderer = new HttpErrorRenderer()) {
|
|
918
|
-
function createResponse(data) {
|
|
919
|
-
const { hasResponded } = useResponse();
|
|
920
|
-
if (hasResponded())
|
|
921
|
-
return null;
|
|
922
|
-
if (data instanceof Error) {
|
|
923
|
-
const r = new BaseHttpResponse(errorRenderer);
|
|
924
|
-
let httpError;
|
|
925
|
-
if (data instanceof HttpError) {
|
|
926
|
-
httpError = data;
|
|
927
|
-
}
|
|
928
|
-
else {
|
|
929
|
-
httpError = new HttpError(500, data.message);
|
|
930
|
-
}
|
|
931
|
-
r.setBody(httpError.body);
|
|
932
|
-
return r;
|
|
933
|
-
}
|
|
934
|
-
else if (data instanceof BaseHttpResponse) {
|
|
935
|
-
return data;
|
|
936
|
-
}
|
|
937
|
-
else {
|
|
938
|
-
return new BaseHttpResponse(renderer).setBody(data);
|
|
939
|
-
}
|
|
940
|
-
}
|
|
941
|
-
return {
|
|
942
|
-
createResponse,
|
|
943
|
-
respond: (data) =>
|
|
944
|
-
};
|
|
873
|
+
function createWooksResponder(
|
|
874
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
875
|
+
renderer = new BaseHttpResponseRenderer(),
|
|
876
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
877
|
+
errorRenderer = new HttpErrorRenderer()) {
|
|
878
|
+
function createResponse(data) {
|
|
879
|
+
const { hasResponded } = useResponse();
|
|
880
|
+
if (hasResponded())
|
|
881
|
+
return null;
|
|
882
|
+
if (data instanceof Error) {
|
|
883
|
+
const r = new BaseHttpResponse(errorRenderer);
|
|
884
|
+
let httpError;
|
|
885
|
+
if (data instanceof HttpError) {
|
|
886
|
+
httpError = data;
|
|
887
|
+
}
|
|
888
|
+
else {
|
|
889
|
+
httpError = new HttpError(500, data.message);
|
|
890
|
+
}
|
|
891
|
+
r.setBody(httpError.body);
|
|
892
|
+
return r;
|
|
893
|
+
}
|
|
894
|
+
else if (data instanceof BaseHttpResponse) {
|
|
895
|
+
return data;
|
|
896
|
+
}
|
|
897
|
+
else {
|
|
898
|
+
return new BaseHttpResponse(renderer).setBody(data);
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
return {
|
|
902
|
+
createResponse,
|
|
903
|
+
respond: (data) => createResponse(data)?.respond(),
|
|
904
|
+
};
|
|
945
905
|
}
|
|
946
906
|
|
|
947
|
-
class WooksHttp extends wooks.WooksAdapterBase {
|
|
948
|
-
constructor(opts, wooks) {
|
|
949
|
-
super(wooks, opts
|
|
950
|
-
this.opts = opts;
|
|
951
|
-
this.responder = createWooksResponder();
|
|
952
|
-
this.logger =
|
|
953
|
-
}
|
|
954
|
-
all(path, handler) {
|
|
955
|
-
return this.on('*', path, handler);
|
|
956
|
-
}
|
|
957
|
-
get(path, handler) {
|
|
958
|
-
return this.on('GET', path, handler);
|
|
959
|
-
}
|
|
960
|
-
post(path, handler) {
|
|
961
|
-
return this.on('POST', path, handler);
|
|
962
|
-
}
|
|
963
|
-
put(path, handler) {
|
|
964
|
-
return this.on('PUT', path, handler);
|
|
965
|
-
}
|
|
966
|
-
patch(path, handler) {
|
|
967
|
-
return this.on('PATCH', path, handler);
|
|
968
|
-
}
|
|
969
|
-
delete(path, handler) {
|
|
970
|
-
return this.on('DELETE', path, handler);
|
|
971
|
-
}
|
|
972
|
-
head(path, handler) {
|
|
973
|
-
return this.on('HEAD', path, handler);
|
|
974
|
-
}
|
|
975
|
-
options(path, handler) {
|
|
976
|
-
return this.on('OPTIONS', path, handler);
|
|
977
|
-
}
|
|
978
|
-
/**
|
|
979
|
-
* Starts the http(s) server.
|
|
980
|
-
*
|
|
981
|
-
* Use this only if you rely on Wooks server.
|
|
982
|
-
*/
|
|
983
|
-
listen(...args) {
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
*
|
|
1009
|
-
*
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
*
|
|
1018
|
-
* to
|
|
1019
|
-
*
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
*
|
|
1034
|
-
*
|
|
1035
|
-
*
|
|
1036
|
-
*
|
|
1037
|
-
*
|
|
1038
|
-
*
|
|
1039
|
-
*
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
}
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
const
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
* @param opts TWooksHttpOptions
|
|
1100
|
-
* @param wooks Wooks | WooksAdapterBase
|
|
1101
|
-
* @returns WooksHttp
|
|
1102
|
-
*/
|
|
1103
|
-
function createHttpApp(opts, wooks) {
|
|
1104
|
-
return new WooksHttp(opts, wooks);
|
|
907
|
+
class WooksHttp extends wooks.WooksAdapterBase {
|
|
908
|
+
constructor(opts, wooks) {
|
|
909
|
+
super(wooks, opts?.logger, opts?.router);
|
|
910
|
+
this.opts = opts;
|
|
911
|
+
this.responder = createWooksResponder();
|
|
912
|
+
this.logger = opts?.logger || this.getLogger('wooks-http');
|
|
913
|
+
}
|
|
914
|
+
all(path, handler) {
|
|
915
|
+
return this.on('*', path, handler);
|
|
916
|
+
}
|
|
917
|
+
get(path, handler) {
|
|
918
|
+
return this.on('GET', path, handler);
|
|
919
|
+
}
|
|
920
|
+
post(path, handler) {
|
|
921
|
+
return this.on('POST', path, handler);
|
|
922
|
+
}
|
|
923
|
+
put(path, handler) {
|
|
924
|
+
return this.on('PUT', path, handler);
|
|
925
|
+
}
|
|
926
|
+
patch(path, handler) {
|
|
927
|
+
return this.on('PATCH', path, handler);
|
|
928
|
+
}
|
|
929
|
+
delete(path, handler) {
|
|
930
|
+
return this.on('DELETE', path, handler);
|
|
931
|
+
}
|
|
932
|
+
head(path, handler) {
|
|
933
|
+
return this.on('HEAD', path, handler);
|
|
934
|
+
}
|
|
935
|
+
options(path, handler) {
|
|
936
|
+
return this.on('OPTIONS', path, handler);
|
|
937
|
+
}
|
|
938
|
+
/**
|
|
939
|
+
* Starts the http(s) server.
|
|
940
|
+
*
|
|
941
|
+
* Use this only if you rely on Wooks server.
|
|
942
|
+
*/
|
|
943
|
+
async listen(...args) {
|
|
944
|
+
const server = (this.server = http.createServer(this.getServerCb()));
|
|
945
|
+
return new Promise((resolve, reject) => {
|
|
946
|
+
server.once('listening', resolve);
|
|
947
|
+
server.once('error', reject);
|
|
948
|
+
server.listen(...args);
|
|
949
|
+
});
|
|
950
|
+
}
|
|
951
|
+
/**
|
|
952
|
+
* Stops the server if it was attached or passed via argument
|
|
953
|
+
* @param server
|
|
954
|
+
*/
|
|
955
|
+
close(server) {
|
|
956
|
+
const srv = server || this.server;
|
|
957
|
+
return new Promise((resolve, reject) => {
|
|
958
|
+
srv?.close((err) => {
|
|
959
|
+
if (err)
|
|
960
|
+
return reject(err);
|
|
961
|
+
resolve(srv);
|
|
962
|
+
});
|
|
963
|
+
});
|
|
964
|
+
}
|
|
965
|
+
/**
|
|
966
|
+
* Returns http(s) server that was attached to Wooks
|
|
967
|
+
*
|
|
968
|
+
* See attachServer method docs
|
|
969
|
+
* @returns Server
|
|
970
|
+
*/
|
|
971
|
+
getServer() {
|
|
972
|
+
return this.server;
|
|
973
|
+
}
|
|
974
|
+
/**
|
|
975
|
+
* Attaches http(s) server instance
|
|
976
|
+
* to Wooks.
|
|
977
|
+
*
|
|
978
|
+
* Use it only if you want to `close` method to stop the server.
|
|
979
|
+
* @param server Server
|
|
980
|
+
*/
|
|
981
|
+
attachServer(server) {
|
|
982
|
+
this.server = server;
|
|
983
|
+
}
|
|
984
|
+
respond(data) {
|
|
985
|
+
void this.responder.respond(data)?.catch((e) => {
|
|
986
|
+
this.logger.error('Uncought response exception', e);
|
|
987
|
+
});
|
|
988
|
+
}
|
|
989
|
+
/**
|
|
990
|
+
* Returns server callback function
|
|
991
|
+
* that can be passed to any node server:
|
|
992
|
+
* ```js
|
|
993
|
+
* import { createHttpApp } from '@wooksjs/event-http'
|
|
994
|
+
* import http from 'http'
|
|
995
|
+
*
|
|
996
|
+
* const app = createHttpApp()
|
|
997
|
+
* const server = http.createServer(app.getServerCb())
|
|
998
|
+
* server.listen(3000)
|
|
999
|
+
* ```
|
|
1000
|
+
*/
|
|
1001
|
+
getServerCb() {
|
|
1002
|
+
return async (req, res) => {
|
|
1003
|
+
const { restoreCtx, clearCtx } = createHttpContext({ req, res }, this.mergeEventOptions(this.opts?.eventOptions));
|
|
1004
|
+
const { handlers } = this.wooks.lookup(req.method, req.url);
|
|
1005
|
+
if (handlers || this.opts?.onNotFound) {
|
|
1006
|
+
try {
|
|
1007
|
+
await this.processHandlers(handlers || [this.opts?.onNotFound]);
|
|
1008
|
+
}
|
|
1009
|
+
catch (e) {
|
|
1010
|
+
this.logger.error('Internal error, please report', e);
|
|
1011
|
+
restoreCtx();
|
|
1012
|
+
this.respond(e);
|
|
1013
|
+
clearCtx();
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
else {
|
|
1017
|
+
// not found
|
|
1018
|
+
this.logger.debug(`404 Not found (${req.method})${req.url}`);
|
|
1019
|
+
this.respond(new HttpError(404));
|
|
1020
|
+
clearCtx();
|
|
1021
|
+
}
|
|
1022
|
+
};
|
|
1023
|
+
}
|
|
1024
|
+
async processHandlers(handlers) {
|
|
1025
|
+
const { restoreCtx, clearCtx, store } = useHttpContext();
|
|
1026
|
+
for (const [i, handler] of handlers.entries()) {
|
|
1027
|
+
const isLastHandler = handlers.length === i + 1;
|
|
1028
|
+
try {
|
|
1029
|
+
restoreCtx();
|
|
1030
|
+
const promise = handler();
|
|
1031
|
+
clearCtx();
|
|
1032
|
+
const result = await promise;
|
|
1033
|
+
// even if the returned value is an Error instance
|
|
1034
|
+
// we still want to process it as a response
|
|
1035
|
+
restoreCtx();
|
|
1036
|
+
this.respond(result);
|
|
1037
|
+
clearCtx();
|
|
1038
|
+
break;
|
|
1039
|
+
}
|
|
1040
|
+
catch (e) {
|
|
1041
|
+
this.logger.error(`Uncought route handler exception: ${store('event').get('req').url || ''}`, e);
|
|
1042
|
+
if (isLastHandler) {
|
|
1043
|
+
restoreCtx();
|
|
1044
|
+
this.respond(e);
|
|
1045
|
+
clearCtx();
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
/**
|
|
1052
|
+
* Factory for WooksHttp App
|
|
1053
|
+
* @param opts TWooksHttpOptions
|
|
1054
|
+
* @param wooks Wooks | WooksAdapterBase
|
|
1055
|
+
* @returns WooksHttp
|
|
1056
|
+
*/
|
|
1057
|
+
function createHttpApp(opts, wooks) {
|
|
1058
|
+
return new WooksHttp(opts, wooks);
|
|
1105
1059
|
}
|
|
1106
1060
|
|
|
1107
1061
|
exports.BaseHttpResponse = BaseHttpResponse;
|