undici 5.13.0 → 5.15.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/docs/api/Connector.md +3 -1
- package/docs/api/Cookies.md +101 -0
- package/docs/api/DiagnosticsChannel.md +67 -0
- package/docs/api/Dispatcher.md +1 -0
- package/docs/api/Fetch.md +25 -0
- package/docs/api/WebSocket.md +20 -0
- package/index.d.ts +2 -0
- package/index.js +15 -0
- package/lib/client.js +6 -3
- package/lib/cookies/constants.js +12 -0
- package/lib/cookies/index.js +183 -0
- package/lib/cookies/parse.js +317 -0
- package/lib/cookies/util.js +291 -0
- package/lib/core/connect.js +62 -19
- package/lib/core/request.js +30 -5
- package/lib/core/symbols.js +1 -1
- package/lib/fetch/body.js +137 -168
- package/lib/fetch/file.js +9 -6
- package/lib/fetch/formdata.js +5 -2
- package/lib/fetch/headers.js +39 -10
- package/lib/fetch/index.js +67 -23
- package/lib/fetch/request.js +5 -2
- package/lib/fetch/response.js +1 -1
- package/lib/fetch/symbols.js +2 -1
- package/lib/fetch/util.js +67 -38
- package/lib/fetch/webidl.js +16 -4
- package/lib/fileapi/filereader.js +30 -0
- package/lib/fileapi/util.js +3 -9
- package/lib/websocket/connection.js +324 -0
- package/lib/websocket/constants.js +51 -0
- package/lib/websocket/events.js +303 -0
- package/lib/websocket/frame.js +66 -0
- package/lib/websocket/receiver.js +344 -0
- package/lib/websocket/symbols.js +15 -0
- package/lib/websocket/util.js +200 -0
- package/lib/websocket/websocket.js +559 -0
- package/package.json +10 -7
- package/types/connector.d.ts +3 -1
- package/types/cookies.d.ts +28 -0
- package/types/dispatcher.d.ts +2 -0
- package/types/patch.d.ts +20 -0
- package/types/proxy-agent.d.ts +3 -3
- package/types/webidl.d.ts +7 -2
- package/types/websocket.d.ts +121 -0
package/docs/api/Connector.md
CHANGED
|
@@ -24,8 +24,10 @@ Once you call `buildConnector`, it will return a connector function, which takes
|
|
|
24
24
|
* **hostname** `string` (required)
|
|
25
25
|
* **host** `string` (optional)
|
|
26
26
|
* **protocol** `string` (required)
|
|
27
|
-
* **port** `
|
|
27
|
+
* **port** `string` (required)
|
|
28
28
|
* **servername** `string` (optional)
|
|
29
|
+
* **localAddress** `string | null` (optional) Local address the socket should connect from.
|
|
30
|
+
* **httpSocket** `Socket` (optional) Establish secure connection on a given socket rather than creating a new socket. It can only be sent on TLS update.
|
|
29
31
|
|
|
30
32
|
### Basic example
|
|
31
33
|
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Cookie Handling
|
|
2
|
+
|
|
3
|
+
## `Cookie` interface
|
|
4
|
+
|
|
5
|
+
* **name** `string`
|
|
6
|
+
* **value** `string`
|
|
7
|
+
* **expires** `Date|number` (optional)
|
|
8
|
+
* **maxAge** `number` (optional)
|
|
9
|
+
* **domain** `string` (optional)
|
|
10
|
+
* **path** `string` (optional)
|
|
11
|
+
* **secure** `boolean` (optional)
|
|
12
|
+
* **httpOnly** `boolean` (optional)
|
|
13
|
+
* **sameSite** `'String'|'Lax'|'None'` (optional)
|
|
14
|
+
* **unparsed** `string[]` (optional) Left over attributes that weren't parsed.
|
|
15
|
+
|
|
16
|
+
## `deleteCookie(headers, name[, attributes])`
|
|
17
|
+
|
|
18
|
+
Sets the expiry time of the cookie to the unix epoch, causing browsers to delete it when received.
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
import { deleteCookie, Headers } from 'undici'
|
|
22
|
+
|
|
23
|
+
const headers = new Headers()
|
|
24
|
+
deleteCookie(headers, 'name')
|
|
25
|
+
|
|
26
|
+
console.log(headers.get('set-cookie')) // name=; Expires=Thu, 01 Jan 1970 00:00:00 GMT
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Arguments:
|
|
30
|
+
|
|
31
|
+
* **headers** `Headers`
|
|
32
|
+
* **name** `string`
|
|
33
|
+
* **attributes** `{ path?: string, domain?: string }` (optional)
|
|
34
|
+
|
|
35
|
+
Returns: `void`
|
|
36
|
+
|
|
37
|
+
## `getCookies(headers)`
|
|
38
|
+
|
|
39
|
+
Parses the `Cookie` header and returns a list of attributes and values.
|
|
40
|
+
|
|
41
|
+
```js
|
|
42
|
+
import { getCookies, Headers } from 'undici'
|
|
43
|
+
|
|
44
|
+
const headers = new Headers({
|
|
45
|
+
cookie: 'get=cookies; and=attributes'
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
console.log(getCookies(headers)) // { get: 'cookies', and: 'attributes' }
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Arguments:
|
|
52
|
+
|
|
53
|
+
* **headers** `Headers`
|
|
54
|
+
|
|
55
|
+
Returns: `Record<string, string>`
|
|
56
|
+
|
|
57
|
+
## `getSetCookies(headers)`
|
|
58
|
+
|
|
59
|
+
Parses all `Set-Cookie` headers.
|
|
60
|
+
|
|
61
|
+
```js
|
|
62
|
+
import { getSetCookies, Headers } from 'undici'
|
|
63
|
+
|
|
64
|
+
const headers = new Headers({ 'set-cookie': 'undici=getSetCookies; Secure' })
|
|
65
|
+
|
|
66
|
+
console.log(getSetCookies(headers))
|
|
67
|
+
// [
|
|
68
|
+
// {
|
|
69
|
+
// name: 'undici',
|
|
70
|
+
// value: 'getSetCookies',
|
|
71
|
+
// secure: true
|
|
72
|
+
// }
|
|
73
|
+
// ]
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Arguments:
|
|
78
|
+
|
|
79
|
+
* **headers** `Headers`
|
|
80
|
+
|
|
81
|
+
Returns: `Cookie[]`
|
|
82
|
+
|
|
83
|
+
## `setCookie(headers, cookie)`
|
|
84
|
+
|
|
85
|
+
Appends a cookie to the `Set-Cookie` header.
|
|
86
|
+
|
|
87
|
+
```js
|
|
88
|
+
import { setCookie, Headers } from 'undici'
|
|
89
|
+
|
|
90
|
+
const headers = new Headers()
|
|
91
|
+
setCookie(headers, { name: 'undici', value: 'setCookie' })
|
|
92
|
+
|
|
93
|
+
console.log(headers.get('Set-Cookie')) // undici=setCookie
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Arguments:
|
|
97
|
+
|
|
98
|
+
* **headers** `Headers`
|
|
99
|
+
* **cookie** `Cookie`
|
|
100
|
+
|
|
101
|
+
Returns: `void`
|
|
@@ -135,3 +135,70 @@ diagnosticsChannel.channel('undici:client:connectError').subscribe(({ error, soc
|
|
|
135
135
|
// connector is a function that creates the socket
|
|
136
136
|
console.log(`Connect failed with ${error.message}`)
|
|
137
137
|
})
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## `undici:websocket:open`
|
|
141
|
+
|
|
142
|
+
This message is published after the client has successfully connected to a server.
|
|
143
|
+
|
|
144
|
+
```js
|
|
145
|
+
import diagnosticsChannel from 'diagnostics_channel'
|
|
146
|
+
|
|
147
|
+
diagnosticsChannel.channel('undici:websocket:open').subscribe(({ address, protocol, extensions }) => {
|
|
148
|
+
console.log(address) // address, family, and port
|
|
149
|
+
console.log(protocol) // negotiated subprotocols
|
|
150
|
+
console.log(extensions) // negotiated extensions
|
|
151
|
+
})
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## `undici:websocket:close`
|
|
155
|
+
|
|
156
|
+
This message is published after the connection has closed.
|
|
157
|
+
|
|
158
|
+
```js
|
|
159
|
+
import diagnosticsChannel from 'diagnostics_channel'
|
|
160
|
+
|
|
161
|
+
diagnosticsChannel.channel('undici:websocket:close').subscribe(({ websocket, code, reason }) => {
|
|
162
|
+
console.log(websocket) // the WebSocket object
|
|
163
|
+
console.log(code) // the closing status code
|
|
164
|
+
console.log(reason) // the closing reason
|
|
165
|
+
})
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## `undici:websocket:socket_error`
|
|
169
|
+
|
|
170
|
+
This message is published if the socket experiences an error.
|
|
171
|
+
|
|
172
|
+
```js
|
|
173
|
+
import diagnosticsChannel from 'diagnostics_channel'
|
|
174
|
+
|
|
175
|
+
diagnosticsChannel.channel('undici:websocket:socket_error').subscribe((error) => {
|
|
176
|
+
console.log(error)
|
|
177
|
+
})
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## `undici:websocket:ping`
|
|
181
|
+
|
|
182
|
+
This message is published after the client receives a ping frame, if the connection is not closing.
|
|
183
|
+
|
|
184
|
+
```js
|
|
185
|
+
import diagnosticsChannel from 'diagnostics_channel'
|
|
186
|
+
|
|
187
|
+
diagnosticsChannel.channel('undici:websocket:ping').subscribe(({ payload }) => {
|
|
188
|
+
// a Buffer or undefined, containing the optional application data of the frame
|
|
189
|
+
console.log(payload)
|
|
190
|
+
})
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## `undici:websocket:pong`
|
|
194
|
+
|
|
195
|
+
This message is published after the client receives a pong frame.
|
|
196
|
+
|
|
197
|
+
```js
|
|
198
|
+
import diagnosticsChannel from 'diagnostics_channel'
|
|
199
|
+
|
|
200
|
+
diagnosticsChannel.channel('undici:websocket:pong').subscribe(({ payload }) => {
|
|
201
|
+
// a Buffer or undefined, containing the optional application data of the frame
|
|
202
|
+
console.log(payload)
|
|
203
|
+
})
|
|
204
|
+
```
|
package/docs/api/Dispatcher.md
CHANGED
|
@@ -192,6 +192,7 @@ Returns: `Boolean` - `false` if dispatcher is busy and further dispatch calls wo
|
|
|
192
192
|
* **origin** `string | URL`
|
|
193
193
|
* **path** `string`
|
|
194
194
|
* **method** `string`
|
|
195
|
+
* **reset** `boolean` (optional) - Default: `false` - If `false`, the request will attempt to create a long-living connection by sending the `connection: keep-alive` header,otherwise will attempt to close it immediately after response by sending `connection: close` within the request and closing the socket afterwards.
|
|
195
196
|
* **body** `string | Buffer | Uint8Array | stream.Readable | Iterable | AsyncIterable | null` (optional) - Default: `null`
|
|
196
197
|
* **headers** `UndiciHeaders | string[]` (optional) - Default: `null`.
|
|
197
198
|
* **query** `Record<string, any> | null` (optional) - Default: `null` - Query string params to be embedded in the request URL. Note that both keys and values of query are encoded using `encodeURIComponent`. If for some reason you need to send them unencoded, embed query params into path directly instead.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Fetch
|
|
2
|
+
|
|
3
|
+
Undici exposes a fetch() method starts the process of fetching a resource from the network.
|
|
4
|
+
|
|
5
|
+
Documentation and examples can be found on [MDN](https://developer.mozilla.org/en-US/docs/Web/API/fetch).
|
|
6
|
+
|
|
7
|
+
## File
|
|
8
|
+
|
|
9
|
+
This API is implemented as per the standard, you can find documentation on [MDN](https://developer.mozilla.org/en-US/docs/Web/API/File)
|
|
10
|
+
|
|
11
|
+
## FormData
|
|
12
|
+
|
|
13
|
+
This API is implemented as per the standard, you can find documentation on [MDN](https://developer.mozilla.org/en-US/docs/Web/API/FormData)
|
|
14
|
+
|
|
15
|
+
## Response
|
|
16
|
+
|
|
17
|
+
This API is implemented as per the standard, you can find documentation on [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Response)
|
|
18
|
+
|
|
19
|
+
## Request
|
|
20
|
+
|
|
21
|
+
This API is implemented as per the standard, you can find documentation on [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Request)
|
|
22
|
+
|
|
23
|
+
## Header
|
|
24
|
+
|
|
25
|
+
This API is implemented as per the standard, you can find documentation on [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Headers)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Class: WebSocket
|
|
2
|
+
|
|
3
|
+
> ⚠️ Warning: the WebSocket API is experimental and has known bugs.
|
|
4
|
+
|
|
5
|
+
Extends: [`EventTarget`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget)
|
|
6
|
+
|
|
7
|
+
The WebSocket object provides a way to manage a WebSocket connection to a server, allowing bidirectional communication. The API follows the [WebSocket spec](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket).
|
|
8
|
+
|
|
9
|
+
## `new WebSocket(url[, protocol])`
|
|
10
|
+
|
|
11
|
+
Arguments:
|
|
12
|
+
|
|
13
|
+
* **url** `URL | string` - The url's protocol *must* be `ws` or `wss`.
|
|
14
|
+
* **protocol** `string | string[]` (optional) - Subprotocol(s) to request the server use.
|
|
15
|
+
|
|
16
|
+
## Read More
|
|
17
|
+
|
|
18
|
+
- [MDN - WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket)
|
|
19
|
+
- [The WebSocket Specification](https://www.rfc-editor.org/rfc/rfc6455)
|
|
20
|
+
- [The WHATWG WebSocket Specification](https://websockets.spec.whatwg.org/)
|
package/index.d.ts
CHANGED
|
@@ -16,11 +16,13 @@ import mockErrors from'./types/mock-errors'
|
|
|
16
16
|
import ProxyAgent from'./types/proxy-agent'
|
|
17
17
|
import { request, pipeline, stream, connect, upgrade } from './types/api'
|
|
18
18
|
|
|
19
|
+
export * from './types/cookies'
|
|
19
20
|
export * from './types/fetch'
|
|
20
21
|
export * from './types/file'
|
|
21
22
|
export * from './types/filereader'
|
|
22
23
|
export * from './types/formdata'
|
|
23
24
|
export * from './types/diagnostics-channel'
|
|
25
|
+
export * from './types/websocket'
|
|
24
26
|
export { Interceptable } from './types/mock-interceptor'
|
|
25
27
|
|
|
26
28
|
export { Dispatcher, BalancedPool, Pool, Client, buildConnector, errors, Agent, request, stream, pipeline, connect, upgrade, setGlobalDispatcher, getGlobalDispatcher, setGlobalOrigin, getGlobalOrigin, MockClient, MockPool, MockAgent, mockErrors, ProxyAgent, RedirectHandler, DecoratorHandler }
|
package/index.js
CHANGED
|
@@ -119,6 +119,21 @@ if (nodeMajor > 16 || (nodeMajor === 16 && nodeMinor >= 8)) {
|
|
|
119
119
|
module.exports.getGlobalOrigin = getGlobalOrigin
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
+
if (nodeMajor >= 16) {
|
|
123
|
+
const { deleteCookie, getCookies, getSetCookies, setCookie } = require('./lib/cookies')
|
|
124
|
+
|
|
125
|
+
module.exports.deleteCookie = deleteCookie
|
|
126
|
+
module.exports.getCookies = getCookies
|
|
127
|
+
module.exports.getSetCookies = getSetCookies
|
|
128
|
+
module.exports.setCookie = setCookie
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (nodeMajor >= 18) {
|
|
132
|
+
const { WebSocket } = require('./lib/websocket/websocket')
|
|
133
|
+
|
|
134
|
+
module.exports.WebSocket = WebSocket
|
|
135
|
+
}
|
|
136
|
+
|
|
122
137
|
module.exports.request = makeDispatcher(api.request)
|
|
123
138
|
module.exports.stream = makeDispatcher(api.stream)
|
|
124
139
|
module.exports.pipeline = makeDispatcher(api.pipeline)
|
package/lib/client.js
CHANGED
|
@@ -1295,7 +1295,7 @@ function _resume (client, sync) {
|
|
|
1295
1295
|
}
|
|
1296
1296
|
|
|
1297
1297
|
function write (client, request) {
|
|
1298
|
-
const { body, method, path, host, upgrade, headers, blocking } = request
|
|
1298
|
+
const { body, method, path, host, upgrade, headers, blocking, reset } = request
|
|
1299
1299
|
|
|
1300
1300
|
// https://tools.ietf.org/html/rfc7231#section-4.3.1
|
|
1301
1301
|
// https://tools.ietf.org/html/rfc7231#section-4.3.2
|
|
@@ -1363,7 +1363,6 @@ function write (client, request) {
|
|
|
1363
1363
|
|
|
1364
1364
|
if (method === 'HEAD') {
|
|
1365
1365
|
// https://github.com/mcollina/undici/issues/258
|
|
1366
|
-
|
|
1367
1366
|
// Close after a HEAD request to interop with misbehaving servers
|
|
1368
1367
|
// that may send a body in the response.
|
|
1369
1368
|
|
|
@@ -1377,6 +1376,10 @@ function write (client, request) {
|
|
|
1377
1376
|
socket[kReset] = true
|
|
1378
1377
|
}
|
|
1379
1378
|
|
|
1379
|
+
if (reset) {
|
|
1380
|
+
socket[kReset] = true
|
|
1381
|
+
}
|
|
1382
|
+
|
|
1380
1383
|
if (client[kMaxRequests] && socket[kCounter]++ >= client[kMaxRequests]) {
|
|
1381
1384
|
socket[kReset] = true
|
|
1382
1385
|
}
|
|
@@ -1395,7 +1398,7 @@ function write (client, request) {
|
|
|
1395
1398
|
|
|
1396
1399
|
if (upgrade) {
|
|
1397
1400
|
header += `connection: upgrade\r\nupgrade: ${upgrade}\r\n`
|
|
1398
|
-
} else if (client[kPipelining]) {
|
|
1401
|
+
} else if (client[kPipelining] && !socket[kReset]) {
|
|
1399
1402
|
header += 'connection: keep-alive\r\n'
|
|
1400
1403
|
} else {
|
|
1401
1404
|
header += 'connection: close\r\n'
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
// https://wicg.github.io/cookie-store/#cookie-maximum-attribute-value-size
|
|
4
|
+
const maxAttributeValueSize = 1024
|
|
5
|
+
|
|
6
|
+
// https://wicg.github.io/cookie-store/#cookie-maximum-name-value-pair-size
|
|
7
|
+
const maxNameValuePairSize = 4096
|
|
8
|
+
|
|
9
|
+
module.exports = {
|
|
10
|
+
maxAttributeValueSize,
|
|
11
|
+
maxNameValuePairSize
|
|
12
|
+
}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { parseSetCookie } = require('./parse')
|
|
4
|
+
const { stringify, getHeadersList } = require('./util')
|
|
5
|
+
const { webidl } = require('../fetch/webidl')
|
|
6
|
+
const { Headers } = require('../fetch/headers')
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {Object} Cookie
|
|
10
|
+
* @property {string} name
|
|
11
|
+
* @property {string} value
|
|
12
|
+
* @property {Date|number|undefined} expires
|
|
13
|
+
* @property {number|undefined} maxAge
|
|
14
|
+
* @property {string|undefined} domain
|
|
15
|
+
* @property {string|undefined} path
|
|
16
|
+
* @property {boolean|undefined} secure
|
|
17
|
+
* @property {boolean|undefined} httpOnly
|
|
18
|
+
* @property {'Strict'|'Lax'|'None'} sameSite
|
|
19
|
+
* @property {string[]} unparsed
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {Headers} headers
|
|
24
|
+
* @returns {Record<string, string>}
|
|
25
|
+
*/
|
|
26
|
+
function getCookies (headers) {
|
|
27
|
+
webidl.argumentLengthCheck(arguments, 1, { header: 'getCookies' })
|
|
28
|
+
|
|
29
|
+
webidl.brandCheck(headers, Headers, { strict: false })
|
|
30
|
+
|
|
31
|
+
const cookie = headers.get('cookie')
|
|
32
|
+
const out = {}
|
|
33
|
+
|
|
34
|
+
if (!cookie) {
|
|
35
|
+
return out
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
for (const piece of cookie.split(';')) {
|
|
39
|
+
const [name, ...value] = piece.split('=')
|
|
40
|
+
|
|
41
|
+
out[name.trim()] = value.join('=')
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return out
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @param {Headers} headers
|
|
49
|
+
* @param {string} name
|
|
50
|
+
* @param {{ path?: string, domain?: string }|undefined} attributes
|
|
51
|
+
* @returns {void}
|
|
52
|
+
*/
|
|
53
|
+
function deleteCookie (headers, name, attributes) {
|
|
54
|
+
webidl.argumentLengthCheck(arguments, 2, { header: 'deleteCookie' })
|
|
55
|
+
|
|
56
|
+
webidl.brandCheck(headers, Headers, { strict: false })
|
|
57
|
+
|
|
58
|
+
name = webidl.converters.DOMString(name)
|
|
59
|
+
attributes = webidl.converters.DeleteCookieAttributes(attributes)
|
|
60
|
+
|
|
61
|
+
// Matches behavior of
|
|
62
|
+
// https://github.com/denoland/deno_std/blob/63827b16330b82489a04614027c33b7904e08be5/http/cookie.ts#L278
|
|
63
|
+
setCookie(headers, {
|
|
64
|
+
name,
|
|
65
|
+
value: '',
|
|
66
|
+
expires: new Date(0),
|
|
67
|
+
...attributes
|
|
68
|
+
})
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @param {Headers} headers
|
|
73
|
+
* @returns {Cookie[]}
|
|
74
|
+
*/
|
|
75
|
+
function getSetCookies (headers) {
|
|
76
|
+
webidl.argumentLengthCheck(arguments, 1, { header: 'getSetCookies' })
|
|
77
|
+
|
|
78
|
+
webidl.brandCheck(headers, Headers, { strict: false })
|
|
79
|
+
|
|
80
|
+
const cookies = getHeadersList(headers).cookies
|
|
81
|
+
|
|
82
|
+
if (!cookies) {
|
|
83
|
+
return []
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return cookies.map((pair) => parseSetCookie(pair[1]))
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* @param {Headers} headers
|
|
91
|
+
* @param {Cookie} cookie
|
|
92
|
+
* @returns {void}
|
|
93
|
+
*/
|
|
94
|
+
function setCookie (headers, cookie) {
|
|
95
|
+
webidl.argumentLengthCheck(arguments, 2, { header: 'setCookie' })
|
|
96
|
+
|
|
97
|
+
webidl.brandCheck(headers, Headers, { strict: false })
|
|
98
|
+
|
|
99
|
+
cookie = webidl.converters.Cookie(cookie)
|
|
100
|
+
|
|
101
|
+
const str = stringify(cookie)
|
|
102
|
+
|
|
103
|
+
if (str) {
|
|
104
|
+
headers.append('Set-Cookie', stringify(cookie))
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
webidl.converters.DeleteCookieAttributes = webidl.dictionaryConverter([
|
|
109
|
+
{
|
|
110
|
+
converter: webidl.nullableConverter(webidl.converters.DOMString),
|
|
111
|
+
key: 'path',
|
|
112
|
+
defaultValue: null
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
converter: webidl.nullableConverter(webidl.converters.DOMString),
|
|
116
|
+
key: 'domain',
|
|
117
|
+
defaultValue: null
|
|
118
|
+
}
|
|
119
|
+
])
|
|
120
|
+
|
|
121
|
+
webidl.converters.Cookie = webidl.dictionaryConverter([
|
|
122
|
+
{
|
|
123
|
+
converter: webidl.converters.DOMString,
|
|
124
|
+
key: 'name'
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
converter: webidl.converters.DOMString,
|
|
128
|
+
key: 'value'
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
converter: webidl.nullableConverter((value) => {
|
|
132
|
+
if (typeof value === 'number') {
|
|
133
|
+
return webidl.converters['unsigned long long'](value)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return new Date(value)
|
|
137
|
+
}),
|
|
138
|
+
key: 'expires',
|
|
139
|
+
defaultValue: null
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
converter: webidl.nullableConverter(webidl.converters['long long']),
|
|
143
|
+
key: 'maxAge',
|
|
144
|
+
defaultValue: null
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
converter: webidl.nullableConverter(webidl.converters.DOMString),
|
|
148
|
+
key: 'domain',
|
|
149
|
+
defaultValue: null
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
converter: webidl.nullableConverter(webidl.converters.DOMString),
|
|
153
|
+
key: 'path',
|
|
154
|
+
defaultValue: null
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
converter: webidl.nullableConverter(webidl.converters.boolean),
|
|
158
|
+
key: 'secure',
|
|
159
|
+
defaultValue: null
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
converter: webidl.nullableConverter(webidl.converters.boolean),
|
|
163
|
+
key: 'httpOnly',
|
|
164
|
+
defaultValue: null
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
converter: webidl.converters.USVString,
|
|
168
|
+
key: 'sameSite',
|
|
169
|
+
allowedValues: ['Strict', 'Lax', 'None']
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
converter: webidl.sequenceConverter(webidl.converters.DOMString),
|
|
173
|
+
key: 'unparsed',
|
|
174
|
+
defaultValue: []
|
|
175
|
+
}
|
|
176
|
+
])
|
|
177
|
+
|
|
178
|
+
module.exports = {
|
|
179
|
+
getCookies,
|
|
180
|
+
deleteCookie,
|
|
181
|
+
getSetCookies,
|
|
182
|
+
setCookie
|
|
183
|
+
}
|