source: trip-planner-front/node_modules/minipass-fetch/lib/request.js@ 571e0df

Last change on this file since 571e0df was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 6.6 KB
RevLine 
[6a3a178]1'use strict'
2const Url = require('url')
3const Minipass = require('minipass')
4const Headers = require('./headers.js')
5const { exportNodeCompatibleHeaders } = Headers
6const Body = require('./body.js')
7const { clone, extractContentType, getTotalBytes } = Body
8
9const version = require('../package.json').version
10const defaultUserAgent =
11 `minipass-fetch/${version} (+https://github.com/isaacs/minipass-fetch)`
12
13const INTERNALS = Symbol('Request internals')
14
15const { parse: parseUrl, format: formatUrl } = Url
16
17const isRequest = input =>
18 typeof input === 'object' && typeof input[INTERNALS] === 'object'
19
20const isAbortSignal = signal => {
21 const proto = (
22 signal
23 && typeof signal === 'object'
24 && Object.getPrototypeOf(signal)
25 )
26 return !!(proto && proto.constructor.name === 'AbortSignal')
27}
28
29class Request extends Body {
30 constructor (input, init = {}) {
31 const parsedURL = isRequest(input) ? Url.parse(input.url)
32 : input && input.href ? Url.parse(input.href)
33 : Url.parse(`${input}`)
34
35 if (isRequest(input))
36 init = { ...input[INTERNALS], ...init }
37 else if (!input || typeof input === 'string')
38 input = {}
39
40 const method = (init.method || input.method || 'GET').toUpperCase()
41 const isGETHEAD = method === 'GET' || method === 'HEAD'
42
43 if ((init.body !== null && init.body !== undefined ||
44 isRequest(input) && input.body !== null) && isGETHEAD)
45 throw new TypeError('Request with GET/HEAD method cannot have body')
46
47 const inputBody = init.body !== null && init.body !== undefined ? init.body
48 : isRequest(input) && input.body !== null ? clone(input)
49 : null
50
51 super(inputBody, {
52 timeout: init.timeout || input.timeout || 0,
53 size: init.size || input.size || 0,
54 })
55
56 const headers = new Headers(init.headers || input.headers || {})
57
58 if (inputBody !== null && inputBody !== undefined &&
59 !headers.has('Content-Type')) {
60 const contentType = extractContentType(inputBody)
61 if (contentType)
62 headers.append('Content-Type', contentType)
63 }
64
65 const signal = 'signal' in init ? init.signal
66 : null
67
68 if (signal !== null && signal !== undefined && !isAbortSignal(signal))
69 throw new TypeError('Expected signal must be an instanceof AbortSignal')
70
71 // TLS specific options that are handled by node
72 const {
73 ca,
74 cert,
75 ciphers,
76 clientCertEngine,
77 crl,
78 dhparam,
79 ecdhCurve,
80 family,
81 honorCipherOrder,
82 key,
83 passphrase,
84 pfx,
85 rejectUnauthorized = process.env.NODE_TLS_REJECT_UNAUTHORIZED !== '0',
86 secureOptions,
87 secureProtocol,
88 servername,
89 sessionIdContext,
90 } = init
91
92 this[INTERNALS] = {
93 method,
94 redirect: init.redirect || input.redirect || 'follow',
95 headers,
96 parsedURL,
97 signal,
98 ca,
99 cert,
100 ciphers,
101 clientCertEngine,
102 crl,
103 dhparam,
104 ecdhCurve,
105 family,
106 honorCipherOrder,
107 key,
108 passphrase,
109 pfx,
110 rejectUnauthorized,
111 secureOptions,
112 secureProtocol,
113 servername,
114 sessionIdContext,
115 }
116
117 // node-fetch-only options
118 this.follow = init.follow !== undefined ? init.follow
119 : input.follow !== undefined ? input.follow
120 : 20
121 this.compress = init.compress !== undefined ? init.compress
122 : input.compress !== undefined ? input.compress
123 : true
124 this.counter = init.counter || input.counter || 0
125 this.agent = init.agent || input.agent
126 }
127
128 get method() {
129 return this[INTERNALS].method
130 }
131
132 get url() {
133 return formatUrl(this[INTERNALS].parsedURL)
134 }
135
136 get headers() {
137 return this[INTERNALS].headers
138 }
139
140 get redirect() {
141 return this[INTERNALS].redirect
142 }
143
144 get signal() {
145 return this[INTERNALS].signal
146 }
147
148 clone () {
149 return new Request(this)
150 }
151
152 get [Symbol.toStringTag] () {
153 return 'Request'
154 }
155
156 static getNodeRequestOptions (request) {
157 const parsedURL = request[INTERNALS].parsedURL
158 const headers = new Headers(request[INTERNALS].headers)
159
160 // fetch step 1.3
161 if (!headers.has('Accept'))
162 headers.set('Accept', '*/*')
163
164 // Basic fetch
165 if (!parsedURL.protocol || !parsedURL.hostname)
166 throw new TypeError('Only absolute URLs are supported')
167
168 if (!/^https?:$/.test(parsedURL.protocol))
169 throw new TypeError('Only HTTP(S) protocols are supported')
170
171 if (request.signal &&
172 Minipass.isStream(request.body) &&
173 typeof request.body.destroy !== 'function') {
174 throw new Error(
175 'Cancellation of streamed requests with AbortSignal is not supported')
176 }
177
178 // HTTP-network-or-cache fetch steps 2.4-2.7
179 const contentLengthValue =
180 (request.body === null || request.body === undefined) &&
181 /^(POST|PUT)$/i.test(request.method) ? '0'
182 : request.body !== null && request.body !== undefined
183 ? getTotalBytes(request)
184 : null
185
186 if (contentLengthValue)
187 headers.set('Content-Length', contentLengthValue + '')
188
189 // HTTP-network-or-cache fetch step 2.11
190 if (!headers.has('User-Agent'))
191 headers.set('User-Agent', defaultUserAgent)
192
193 // HTTP-network-or-cache fetch step 2.15
194 if (request.compress && !headers.has('Accept-Encoding'))
195 headers.set('Accept-Encoding', 'gzip,deflate')
196
197 const agent = typeof request.agent === 'function'
198 ? request.agent(parsedURL)
199 : request.agent
200
201 if (!headers.has('Connection') && !agent)
202 headers.set('Connection', 'close')
203
204 // TLS specific options that are handled by node
205 const {
206 ca,
207 cert,
208 ciphers,
209 clientCertEngine,
210 crl,
211 dhparam,
212 ecdhCurve,
213 family,
214 honorCipherOrder,
215 key,
216 passphrase,
217 pfx,
218 rejectUnauthorized,
219 secureOptions,
220 secureProtocol,
221 servername,
222 sessionIdContext,
223 } = request[INTERNALS]
224
225 // HTTP-network fetch step 4.2
226 // chunked encoding is handled by Node.js
227
228 return {
229 ...parsedURL,
230 method: request.method,
231 headers: exportNodeCompatibleHeaders(headers),
232 agent,
233 ca,
234 cert,
235 ciphers,
236 clientCertEngine,
237 crl,
238 dhparam,
239 ecdhCurve,
240 family,
241 honorCipherOrder,
242 key,
243 passphrase,
244 pfx,
245 rejectUnauthorized,
246 secureOptions,
247 secureProtocol,
248 servername,
249 sessionIdContext,
250 }
251 }
252}
253
254module.exports = Request
255
256Object.defineProperties(Request.prototype, {
257 method: { enumerable: true },
258 url: { enumerable: true },
259 headers: { enumerable: true },
260 redirect: { enumerable: true },
261 clone: { enumerable: true },
262 signal: { enumerable: true },
263})
Note: See TracBrowser for help on using the repository browser.