@e22m4u/js-trie-router 0.2.0 → 0.3.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 +3 -3
- package/dist/cjs/index.cjs +225 -213
- package/examples/{cookie-parsing-example.js → cookies-parsing-example.js} +8 -8
- package/examples/params-parsing-example.js +11 -7
- package/examples/query-parsing-example.js +11 -7
- package/examples/uptime-example.js +4 -4
- package/package.json +9 -8
- package/src/debuggable-service.d.ts +2 -10
- package/src/debuggable-service.js +16 -17
- package/src/hooks/hook-invoker.js +3 -4
- package/src/hooks/hook-invoker.spec.js +3 -3
- package/src/hooks/hook-registry.d.ts +1 -1
- package/src/hooks/hook-registry.js +6 -7
- package/src/hooks/hook-registry.spec.js +14 -5
- package/src/parsers/body-parser.js +10 -11
- package/src/parsers/body-parser.spec.js +4 -4
- package/src/parsers/cookies-parser.d.ts +15 -0
- package/src/parsers/cookies-parser.js +33 -0
- package/src/parsers/{cookie-parser.spec.js → cookies-parser.spec.js} +6 -6
- package/src/parsers/index.d.ts +1 -1
- package/src/parsers/index.js +1 -1
- package/src/parsers/query-parser.js +4 -3
- package/src/parsers/request-parser.d.ts +2 -2
- package/src/parsers/request-parser.js +7 -7
- package/src/parsers/request-parser.spec.js +12 -12
- package/src/request-context.d.ts +3 -3
- package/src/request-context.js +5 -5
- package/src/request-context.spec.js +3 -3
- package/src/route-registry.js +14 -14
- package/src/route-registry.spec.js +4 -1
- package/src/route.d.ts +12 -7
- package/src/route.js +16 -14
- package/src/route.spec.js +13 -7
- package/src/router-options.js +1 -1
- package/src/router-options.spec.js +1 -1
- package/src/senders/data-sender.js +6 -5
- package/src/senders/error-sender.js +11 -4
- package/src/trie-router.js +46 -38
- package/src/trie-router.spec.js +54 -3
- package/src/utils/create-cookies-string.d.ts +6 -0
- package/src/utils/{create-cookie-string.js → create-cookies-string.js} +4 -4
- package/src/utils/{create-cookie-string.spec.js → create-cookies-string.spec.js} +7 -7
- package/src/utils/create-debugger.js +1 -1
- package/src/utils/create-debugger.spec.js +1 -1
- package/src/utils/create-error.js +2 -2
- package/src/utils/create-error.spec.js +2 -2
- package/src/utils/create-request-mock.d.ts +1 -1
- package/src/utils/create-request-mock.js +47 -43
- package/src/utils/create-request-mock.spec.js +18 -18
- package/src/utils/fetch-request-body.d.ts +11 -2
- package/src/utils/fetch-request-body.js +10 -17
- package/src/utils/fetch-request-body.spec.js +8 -9
- package/src/utils/get-request-pathname.js +1 -1
- package/src/utils/get-request-pathname.spec.js +1 -1
- package/src/utils/index.d.ts +2 -2
- package/src/utils/index.js +2 -2
- package/src/utils/is-readable-stream.js +1 -2
- package/src/utils/is-response-sent.js +1 -1
- package/src/utils/is-response-sent.spec.js +1 -1
- package/src/utils/parse-content-type.js +1 -1
- package/src/utils/parse-cookies.d.ts +19 -0
- package/src/utils/{parse-cookie.js → parse-cookies.js} +8 -5
- package/src/utils/{parse-cookie.spec.js → parse-cookies.spec.js} +13 -8
- package/src/utils/to-camel-case.js +1 -1
- package/src/utils/to-camel-case.spec.js +1 -1
- package/src/parsers/cookie-parser.d.ts +0 -15
- package/src/parsers/cookie-parser.js +0 -32
- package/src/utils/create-cookie-string.d.ts +0 -6
- package/src/utils/parse-cookie.d.ts +0 -19
|
@@ -4,7 +4,7 @@ import {TLSSocket} from 'tls';
|
|
|
4
4
|
import {expect} from '../chai.js';
|
|
5
5
|
import {format} from '@e22m4u/js-format';
|
|
6
6
|
import {createRequestMock} from './create-request-mock.js';
|
|
7
|
-
import {
|
|
7
|
+
import {CHARACTER_ENCODING_LIST} from './fetch-request-body.js';
|
|
8
8
|
|
|
9
9
|
describe('createRequestMock', function () {
|
|
10
10
|
it('requires the first argument to be an Object', function () {
|
|
@@ -12,7 +12,7 @@ describe('createRequestMock', function () {
|
|
|
12
12
|
const error = v =>
|
|
13
13
|
format(
|
|
14
14
|
'The first parameter of "createRequestMock" ' +
|
|
15
|
-
'should be an Object, but %s given.',
|
|
15
|
+
'should be an Object, but %s was given.',
|
|
16
16
|
v,
|
|
17
17
|
);
|
|
18
18
|
expect(throwable('str')).to.throw(error('"str"'));
|
|
@@ -32,7 +32,7 @@ describe('createRequestMock', function () {
|
|
|
32
32
|
const error = v =>
|
|
33
33
|
format(
|
|
34
34
|
'The parameter "host" of "createRequestMock" ' +
|
|
35
|
-
'should be a String, but %s given.',
|
|
35
|
+
'should be a String, but %s was given.',
|
|
36
36
|
v,
|
|
37
37
|
);
|
|
38
38
|
expect(throwable(10)).to.throw(error('10'));
|
|
@@ -52,7 +52,7 @@ describe('createRequestMock', function () {
|
|
|
52
52
|
const error = v =>
|
|
53
53
|
format(
|
|
54
54
|
'The parameter "method" of "createRequestMock" ' +
|
|
55
|
-
'should be a String, but %s given.',
|
|
55
|
+
'should be a String, but %s was given.',
|
|
56
56
|
v,
|
|
57
57
|
);
|
|
58
58
|
expect(throwable(10)).to.throw(error('10'));
|
|
@@ -72,7 +72,7 @@ describe('createRequestMock', function () {
|
|
|
72
72
|
const error = v =>
|
|
73
73
|
format(
|
|
74
74
|
'The parameter "secure" of "createRequestMock" ' +
|
|
75
|
-
'should be a Boolean, but %s given.',
|
|
75
|
+
'should be a Boolean, but %s was given.',
|
|
76
76
|
v,
|
|
77
77
|
);
|
|
78
78
|
expect(throwable('str')).to.throw(error('"str"'));
|
|
@@ -92,7 +92,7 @@ describe('createRequestMock', function () {
|
|
|
92
92
|
const error = v =>
|
|
93
93
|
format(
|
|
94
94
|
'The parameter "path" of "createRequestMock" ' +
|
|
95
|
-
'should be a String, but %s given.',
|
|
95
|
+
'should be a String, but %s was given.',
|
|
96
96
|
v,
|
|
97
97
|
);
|
|
98
98
|
expect(throwable(10)).to.throw(error('10'));
|
|
@@ -112,7 +112,7 @@ describe('createRequestMock', function () {
|
|
|
112
112
|
const error = v =>
|
|
113
113
|
format(
|
|
114
114
|
'The parameter "query" of "createRequestMock" ' +
|
|
115
|
-
'should be a String or Object, but %s given.',
|
|
115
|
+
'should be a String or Object, but %s was given.',
|
|
116
116
|
v,
|
|
117
117
|
);
|
|
118
118
|
expect(throwable(10)).to.throw(error('10'));
|
|
@@ -128,12 +128,12 @@ describe('createRequestMock', function () {
|
|
|
128
128
|
throwable(null)();
|
|
129
129
|
});
|
|
130
130
|
|
|
131
|
-
it('requires the parameter "
|
|
132
|
-
const throwable = v => () => createRequestMock({
|
|
131
|
+
it('requires the parameter "cookies" to be a String or Object', function () {
|
|
132
|
+
const throwable = v => () => createRequestMock({cookies: v});
|
|
133
133
|
const error = v =>
|
|
134
134
|
format(
|
|
135
|
-
'The parameter "
|
|
136
|
-
'should be a String or Object, but %s given.',
|
|
135
|
+
'The parameter "cookies" of "createRequestMock" ' +
|
|
136
|
+
'should be a String or Object, but %s was given.',
|
|
137
137
|
v,
|
|
138
138
|
);
|
|
139
139
|
expect(throwable(10)).to.throw(error('10'));
|
|
@@ -154,7 +154,7 @@ describe('createRequestMock', function () {
|
|
|
154
154
|
const error = v =>
|
|
155
155
|
format(
|
|
156
156
|
'The parameter "headers" of "createRequestMock" ' +
|
|
157
|
-
'should be an Object, but %s given.',
|
|
157
|
+
'should be an Object, but %s was given.',
|
|
158
158
|
v,
|
|
159
159
|
);
|
|
160
160
|
expect(throwable('str')).to.throw(error('"str"'));
|
|
@@ -175,7 +175,7 @@ describe('createRequestMock', function () {
|
|
|
175
175
|
const error = v =>
|
|
176
176
|
format(
|
|
177
177
|
'The parameter "stream" of "createRequestMock" ' +
|
|
178
|
-
'should be a Stream, but %s given.',
|
|
178
|
+
'should be a Stream, but %s was given.',
|
|
179
179
|
v,
|
|
180
180
|
);
|
|
181
181
|
expect(throwable('str')).to.throw(error('"str"'));
|
|
@@ -196,7 +196,7 @@ describe('createRequestMock', function () {
|
|
|
196
196
|
const error = v =>
|
|
197
197
|
format(
|
|
198
198
|
'The parameter "encoding" of "createRequestMock" ' +
|
|
199
|
-
'should be a String, but %s given.',
|
|
199
|
+
'should be a String, but %s was given.',
|
|
200
200
|
v,
|
|
201
201
|
);
|
|
202
202
|
expect(throwable(10)).to.throw(error('10'));
|
|
@@ -212,10 +212,10 @@ describe('createRequestMock', function () {
|
|
|
212
212
|
|
|
213
213
|
it('requires the parameter "encoding" to be the BufferEncoding', function () {
|
|
214
214
|
const throwable = v => () => createRequestMock({encoding: v});
|
|
215
|
-
const error = v => format('
|
|
215
|
+
const error = v => format('Character encoding %s is not supported.', v);
|
|
216
216
|
expect(throwable('str')).to.throw(error('"str"'));
|
|
217
217
|
expect(throwable('')).to.throw(error('""'));
|
|
218
|
-
|
|
218
|
+
CHARACTER_ENCODING_LIST.forEach(v => throwable(v)());
|
|
219
219
|
});
|
|
220
220
|
|
|
221
221
|
it('does not allow the option "secure" with the "stream"', function () {
|
|
@@ -389,12 +389,12 @@ describe('createRequestMock', function () {
|
|
|
389
389
|
});
|
|
390
390
|
|
|
391
391
|
it('sets the header "cookie" from a String', function () {
|
|
392
|
-
const req = createRequestMock({
|
|
392
|
+
const req = createRequestMock({cookies: 'test'});
|
|
393
393
|
expect(req.headers['cookie']).to.be.eq('test');
|
|
394
394
|
});
|
|
395
395
|
|
|
396
396
|
it('sets the header "cookie" from an Object', function () {
|
|
397
|
-
const req = createRequestMock({
|
|
397
|
+
const req = createRequestMock({cookies: {p1: 'foo', p2: 'bar'}});
|
|
398
398
|
expect(req.headers['cookie']).to.be.eq('p1=foo; p2=bar;');
|
|
399
399
|
});
|
|
400
400
|
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import {IncomingMessage} from 'http';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Character encoding list.
|
|
5
5
|
*/
|
|
6
|
-
export
|
|
6
|
+
export const CHARACTER_ENCODING_LIST: (
|
|
7
|
+
| 'ascii'
|
|
8
|
+
| 'utf8'
|
|
9
|
+
| 'utf-8'
|
|
10
|
+
| 'utf16le'
|
|
11
|
+
| 'utf-16le'
|
|
12
|
+
| 'ucs2'
|
|
13
|
+
| 'ucs-2'
|
|
14
|
+
| 'latin1'
|
|
15
|
+
)[];
|
|
7
16
|
|
|
8
17
|
/**
|
|
9
18
|
* Fetch request body.
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import HttpErrors from 'http-errors';
|
|
2
|
+
import {IncomingMessage} from 'http';
|
|
3
|
+
import {Errorf} from '@e22m4u/js-format';
|
|
2
4
|
import {createError} from './create-error.js';
|
|
3
5
|
import {parseContentType} from './parse-content-type.js';
|
|
4
|
-
import {Errorf} from '@e22m4u/js-format';
|
|
5
|
-
import {IncomingMessage} from 'http';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* @type {import('buffer').BufferEncoding[]}
|
|
8
|
+
* Character encoding list.
|
|
11
9
|
*/
|
|
12
|
-
export const
|
|
10
|
+
export const CHARACTER_ENCODING_LIST = [
|
|
13
11
|
'ascii',
|
|
14
12
|
'utf8',
|
|
15
13
|
'utf-8',
|
|
@@ -17,11 +15,7 @@ export const BUFFER_ENCODING_LIST = [
|
|
|
17
15
|
'utf-16le',
|
|
18
16
|
'ucs2',
|
|
19
17
|
'ucs-2',
|
|
20
|
-
'base64',
|
|
21
|
-
'base64url',
|
|
22
18
|
'latin1',
|
|
23
|
-
'binary',
|
|
24
|
-
'hex',
|
|
25
19
|
];
|
|
26
20
|
|
|
27
21
|
/**
|
|
@@ -35,13 +29,13 @@ export function fetchRequestBody(req, bodyBytesLimit = 0) {
|
|
|
35
29
|
if (!(req instanceof IncomingMessage))
|
|
36
30
|
throw new Errorf(
|
|
37
31
|
'The first parameter of "fetchRequestBody" should be ' +
|
|
38
|
-
'an IncomingMessage instance, but %v given.',
|
|
32
|
+
'an IncomingMessage instance, but %v was given.',
|
|
39
33
|
req,
|
|
40
34
|
);
|
|
41
35
|
if (typeof bodyBytesLimit !== 'number')
|
|
42
36
|
throw new Errorf(
|
|
43
37
|
'The parameter "bodyBytesLimit" of "fetchRequestBody" ' +
|
|
44
|
-
'should be a number, but %v given.',
|
|
38
|
+
'should be a number, but %v was given.',
|
|
45
39
|
bodyBytesLimit,
|
|
46
40
|
);
|
|
47
41
|
return new Promise((resolve, reject) => {
|
|
@@ -64,7 +58,7 @@ export function fetchRequestBody(req, bodyBytesLimit = 0) {
|
|
|
64
58
|
const parsedContentType = parseContentType(contentType);
|
|
65
59
|
if (parsedContentType && parsedContentType.charset) {
|
|
66
60
|
encoding = parsedContentType.charset.toLowerCase();
|
|
67
|
-
if (!
|
|
61
|
+
if (!CHARACTER_ENCODING_LIST.includes(encoding))
|
|
68
62
|
throw createError(
|
|
69
63
|
HttpErrors.UnsupportedMediaType,
|
|
70
64
|
'Request encoding %v is not supported.',
|
|
@@ -106,12 +100,11 @@ export function fetchRequestBody(req, bodyBytesLimit = 0) {
|
|
|
106
100
|
reject(error);
|
|
107
101
|
return;
|
|
108
102
|
}
|
|
109
|
-
// объединение массива байтов в буфер,
|
|
110
|
-
//
|
|
111
|
-
// и передача полученных данных
|
|
103
|
+
// объединение массива байтов в буфер, кодирование
|
|
104
|
+
// результата в строку, и передача полученных данных
|
|
112
105
|
// в ожидающий Promise
|
|
113
106
|
const buffer = Buffer.concat(data);
|
|
114
|
-
const body =
|
|
107
|
+
const body = buffer.toString(encoding);
|
|
115
108
|
resolve(body || undefined);
|
|
116
109
|
};
|
|
117
110
|
// при ошибке загрузки тела запроса,
|
|
@@ -9,7 +9,7 @@ describe('fetchRequestBody', function () {
|
|
|
9
9
|
const error = v =>
|
|
10
10
|
format(
|
|
11
11
|
'The first parameter of "fetchRequestBody" should be ' +
|
|
12
|
-
'an IncomingMessage instance, but %s given.',
|
|
12
|
+
'an IncomingMessage instance, but %s was given.',
|
|
13
13
|
v,
|
|
14
14
|
);
|
|
15
15
|
expect(throwable('str')).to.throw(error('"str"'));
|
|
@@ -31,7 +31,7 @@ describe('fetchRequestBody', function () {
|
|
|
31
31
|
const error = v =>
|
|
32
32
|
format(
|
|
33
33
|
'The parameter "bodyBytesLimit" of "fetchRequestBody" ' +
|
|
34
|
-
'should be a number, but %s given.',
|
|
34
|
+
'should be a number, but %s was given.',
|
|
35
35
|
v,
|
|
36
36
|
);
|
|
37
37
|
expect(throwable('str')).to.throw(error('"str"'));
|
|
@@ -83,16 +83,15 @@ describe('fetchRequestBody', function () {
|
|
|
83
83
|
expect(result).to.be.eq(body);
|
|
84
84
|
});
|
|
85
85
|
|
|
86
|
-
it('decodes non-
|
|
87
|
-
const
|
|
88
|
-
const encoding = 'base64';
|
|
89
|
-
const encodedBody = Buffer.from(body).toString(encoding);
|
|
86
|
+
it('decodes non-UTF-8 encoding to a plain text', async function () {
|
|
87
|
+
const originalBody = 'Hello, world!';
|
|
90
88
|
const req = createRequestMock({
|
|
91
|
-
body:
|
|
92
|
-
|
|
89
|
+
body: originalBody,
|
|
90
|
+
encoding: 'latin1',
|
|
91
|
+
headers: {'content-type': `text/plain; charset=latin1`},
|
|
93
92
|
});
|
|
94
93
|
const result = await fetchRequestBody(req);
|
|
95
|
-
expect(result).to.be.eq(
|
|
94
|
+
expect(result).to.be.eq(originalBody);
|
|
96
95
|
});
|
|
97
96
|
});
|
|
98
97
|
|
|
@@ -8,7 +8,7 @@ describe('getRequestPathname', function () {
|
|
|
8
8
|
const error = v =>
|
|
9
9
|
format(
|
|
10
10
|
'The first argument of "getRequestPathname" should be ' +
|
|
11
|
-
'an instance of IncomingMessage, but %s given.',
|
|
11
|
+
'an instance of IncomingMessage, but %s was given.',
|
|
12
12
|
v,
|
|
13
13
|
);
|
|
14
14
|
expect(throwable('str')).to.throw(error('"str"'));
|
package/src/utils/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export * from './is-promise.js';
|
|
2
|
-
export * from './parse-cookie.js';
|
|
3
2
|
export * from './create-error.js';
|
|
3
|
+
export * from './parse-cookies.js';
|
|
4
4
|
export * from './to-camel-case.js';
|
|
5
5
|
export * from './create-debugger.js';
|
|
6
6
|
export * from './is-response-sent.js';
|
|
@@ -10,5 +10,5 @@ export * from './is-writable-stream.js';
|
|
|
10
10
|
export * from './fetch-request-body.js';
|
|
11
11
|
export * from './create-request-mock.js';
|
|
12
12
|
export * from './create-response-mock.js';
|
|
13
|
-
export * from './create-
|
|
13
|
+
export * from './create-cookies-string.js';
|
|
14
14
|
export * from './get-request-pathname.js';
|
package/src/utils/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export * from './is-promise.js';
|
|
2
|
-
export * from './parse-cookie.js';
|
|
3
2
|
export * from './create-error.js';
|
|
3
|
+
export * from './parse-cookies.js';
|
|
4
4
|
export * from './to-camel-case.js';
|
|
5
5
|
export * from './create-debugger.js';
|
|
6
6
|
export * from './is-response-sent.js';
|
|
@@ -10,5 +10,5 @@ export * from './is-writable-stream.js';
|
|
|
10
10
|
export * from './fetch-request-body.js';
|
|
11
11
|
export * from './create-request-mock.js';
|
|
12
12
|
export * from './create-response-mock.js';
|
|
13
|
-
export * from './create-
|
|
13
|
+
export * from './create-cookies-string.js';
|
|
14
14
|
export * from './get-request-pathname.js';
|
|
@@ -8,7 +8,7 @@ describe('isResponseSent', function () {
|
|
|
8
8
|
const error = v =>
|
|
9
9
|
format(
|
|
10
10
|
'The first argument of "isResponseSent" should be ' +
|
|
11
|
-
'an instance of ServerResponse, but %s given.',
|
|
11
|
+
'an instance of ServerResponse, but %s was given.',
|
|
12
12
|
v,
|
|
13
13
|
);
|
|
14
14
|
expect(throwable('str')).to.throw(error('"str"'));
|
|
@@ -14,7 +14,7 @@ export function parseContentType(input) {
|
|
|
14
14
|
if (typeof input !== 'string')
|
|
15
15
|
throw new Errorf(
|
|
16
16
|
'The parameter "input" of "parseContentType" ' +
|
|
17
|
-
'should be a String, but %v given.',
|
|
17
|
+
'should be a String, but %v was given.',
|
|
18
18
|
input,
|
|
19
19
|
);
|
|
20
20
|
const res = {mediaType: undefined, charset: undefined, boundary: undefined};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parsed cookies.
|
|
3
|
+
*/
|
|
4
|
+
type ParsedCookies = {
|
|
5
|
+
[key: string]: string | undefined;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Parse cookies.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* parseCookies('pkg=math; equation=E%3Dmc%5E2');
|
|
14
|
+
* // {pkg: 'math', equation: 'E=mc^2'}
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @param input
|
|
18
|
+
*/
|
|
19
|
+
export declare function parseCookies(input: string): ParsedCookies;
|
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
import {Errorf} from '@e22m4u/js-format';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Parse
|
|
4
|
+
* Parse cookies.
|
|
5
5
|
*
|
|
6
6
|
* @example
|
|
7
7
|
* ```ts
|
|
8
|
-
*
|
|
8
|
+
* parseCookies('pkg=math; equation=E%3Dmc%5E2');
|
|
9
9
|
* // {pkg: 'math', equation: 'E=mc^2'}
|
|
10
10
|
* ```
|
|
11
11
|
*
|
|
12
12
|
* @param {string} input
|
|
13
13
|
* @returns {object}
|
|
14
14
|
*/
|
|
15
|
-
export function
|
|
15
|
+
export function parseCookies(input) {
|
|
16
16
|
if (typeof input !== 'string')
|
|
17
17
|
throw new Errorf(
|
|
18
|
-
'The first parameter of "
|
|
18
|
+
'The first parameter of "parseCookies" should be a String, ' +
|
|
19
|
+
'but %v was given.',
|
|
19
20
|
input,
|
|
20
21
|
);
|
|
21
22
|
return input
|
|
@@ -24,7 +25,9 @@ export function parseCookie(input) {
|
|
|
24
25
|
.map(v => v.split('='))
|
|
25
26
|
.reduce((cookies, tuple) => {
|
|
26
27
|
const key = decodeURIComponent(tuple[0]).trim();
|
|
27
|
-
|
|
28
|
+
const value =
|
|
29
|
+
tuple[1] !== undefined ? decodeURIComponent(tuple[1]).trim() : '';
|
|
30
|
+
cookies[key] = value;
|
|
28
31
|
return cookies;
|
|
29
32
|
}, {});
|
|
30
33
|
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {expect} from '../chai.js';
|
|
2
2
|
import {format} from '@e22m4u/js-format';
|
|
3
|
-
import {
|
|
3
|
+
import {parseCookies} from './parse-cookies.js';
|
|
4
4
|
|
|
5
|
-
describe('
|
|
5
|
+
describe('parseCookies', function () {
|
|
6
6
|
it('requires the first parameter to be an IncomingMessage instance', function () {
|
|
7
|
-
const throwable = v => () =>
|
|
7
|
+
const throwable = v => () => parseCookies(v);
|
|
8
8
|
const error = v =>
|
|
9
9
|
format(
|
|
10
|
-
'The first parameter of "
|
|
11
|
-
'a String, but %s given.',
|
|
10
|
+
'The first parameter of "parseCookies" should be ' +
|
|
11
|
+
'a String, but %s was given.',
|
|
12
12
|
v,
|
|
13
13
|
);
|
|
14
14
|
expect(throwable(10)).to.throw(error('10'));
|
|
@@ -23,15 +23,20 @@ describe('parseCookie', function () {
|
|
|
23
23
|
throwable('')();
|
|
24
24
|
});
|
|
25
25
|
|
|
26
|
-
it('returns
|
|
26
|
+
it('returns cookies as a plain object', function () {
|
|
27
27
|
const value = 'pkg=math; equation=E%3Dmc%5E2';
|
|
28
|
-
const result =
|
|
28
|
+
const result = parseCookies(value);
|
|
29
29
|
expect(result).to.have.property('pkg', 'math');
|
|
30
30
|
expect(result).to.have.property('equation', 'E=mc^2');
|
|
31
31
|
});
|
|
32
32
|
|
|
33
33
|
it('returns an empty object for an empty string', function () {
|
|
34
|
-
const result =
|
|
34
|
+
const result = parseCookies('');
|
|
35
35
|
expect(result).to.be.eql({});
|
|
36
36
|
});
|
|
37
|
+
|
|
38
|
+
it('parses an empty cookie as an empty string', function () {
|
|
39
|
+
const result = parseCookies('foo=bar; baz');
|
|
40
|
+
expect(result).to.be.eql({foo: 'bar', baz: ''});
|
|
41
|
+
});
|
|
37
42
|
});
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import {IncomingMessage} from 'http';
|
|
2
|
-
import {ParsedCookie} from '../utils/index.js';
|
|
3
|
-
import {DebuggableService} from '../debuggable-service.js';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Cookie parser.
|
|
7
|
-
*/
|
|
8
|
-
export declare class CookieParser extends DebuggableService {
|
|
9
|
-
/**
|
|
10
|
-
* Parse.
|
|
11
|
-
*
|
|
12
|
-
* @param req
|
|
13
|
-
*/
|
|
14
|
-
parse(req: IncomingMessage): ParsedCookie;
|
|
15
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import {parseCookie} from '../utils/index.js';
|
|
2
|
-
import {getRequestPathname} from '../utils/index.js';
|
|
3
|
-
import {DebuggableService} from '../debuggable-service.js';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Cookie parser.
|
|
7
|
-
*/
|
|
8
|
-
export class CookieParser extends DebuggableService {
|
|
9
|
-
/**
|
|
10
|
-
* Parse
|
|
11
|
-
*
|
|
12
|
-
* @param {import('http').IncomingMessage} req
|
|
13
|
-
* @returns {object}
|
|
14
|
-
*/
|
|
15
|
-
parse(req) {
|
|
16
|
-
const cookieString = req.headers['cookie'] || '';
|
|
17
|
-
const cookie = parseCookie(cookieString);
|
|
18
|
-
const cookieKeys = Object.keys(cookie);
|
|
19
|
-
if (cookieKeys.length) {
|
|
20
|
-
cookieKeys.forEach(key => {
|
|
21
|
-
this.debug('The cookie %v has the value %v.', key, cookie[key]);
|
|
22
|
-
});
|
|
23
|
-
} else {
|
|
24
|
-
this.debug(
|
|
25
|
-
'The request %s %v has no cookie.',
|
|
26
|
-
req.method,
|
|
27
|
-
getRequestPathname(req),
|
|
28
|
-
);
|
|
29
|
-
}
|
|
30
|
-
return cookie;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Parsed cookie.
|
|
3
|
-
*/
|
|
4
|
-
type ParsedCookie = {
|
|
5
|
-
[key: string]: string | undefined;
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Parse cookie.
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* ```ts
|
|
13
|
-
* parseCookie('pkg=math; equation=E%3Dmc%5E2');
|
|
14
|
-
* // {pkg: 'math', equation: 'E=mc^2'}
|
|
15
|
-
* ```
|
|
16
|
-
*
|
|
17
|
-
* @param input
|
|
18
|
-
*/
|
|
19
|
-
export declare function parseCookie(input: string): ParsedCookie;
|