source: trip-planner-front/node_modules/make-fetch-happen/lib/fetch.js@ 8d391a1

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

initial commit

  • Property mode set to 100644
File size: 3.7 KB
Line 
1'use strict'
2
3const { FetchError, Request, isRedirect } = require('minipass-fetch')
4const url = require('url')
5
6const CachePolicy = require('./cache/policy.js')
7const cache = require('./cache/index.js')
8const remote = require('./remote.js')
9
10// given a Request, a Response and user options
11// return true if the response is a redirect that
12// can be followed. we throw errors that will result
13// in the fetch being rejected if the redirect is
14// possible but invalid for some reason
15const canFollowRedirect = (request, response, options) => {
16 if (!isRedirect(response.status))
17 return false
18
19 if (options.redirect === 'manual')
20 return false
21
22 if (options.redirect === 'error')
23 throw new FetchError(`redirect mode is set to error: ${request.url}`, 'no-redirect', { code: 'ENOREDIRECT' })
24
25 if (!response.headers.has('location'))
26 throw new FetchError(`redirect location header missing for: ${request.url}`, 'no-location', { code: 'EINVALIDREDIRECT' })
27
28 if (request.counter >= request.follow)
29 throw new FetchError(`maximum redirect reached at: ${request.url}`, 'max-redirect', { code: 'EMAXREDIRECT' })
30
31 return true
32}
33
34// given a Request, a Response, and the user's options return an object
35// with a new Request and a new options object that will be used for
36// following the redirect
37const getRedirect = (request, response, options) => {
38 const _opts = { ...options }
39 const location = response.headers.get('location')
40 const redirectUrl = new url.URL(location, /^https?:/.test(location) ? undefined : request.url)
41 // Comment below is used under the following license:
42 // Copyright (c) 2010-2012 Mikeal Rogers
43 // Licensed under the Apache License, Version 2.0 (the "License");
44 // you may not use this file except in compliance with the License.
45 // You may obtain a copy of the License at
46 // http://www.apache.org/licenses/LICENSE-2.0
47 // Unless required by applicable law or agreed to in writing,
48 // software distributed under the License is distributed on an "AS
49 // IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
50 // express or implied. See the License for the specific language
51 // governing permissions and limitations under the License.
52
53 // Remove authorization if changing hostnames (but not if just
54 // changing ports or protocols). This matches the behavior of request:
55 // https://github.com/request/request/blob/b12a6245/lib/redirect.js#L134-L138
56 if (new url.URL(request.url).hostname !== redirectUrl.hostname)
57 request.headers.delete('authorization')
58
59 // for POST request with 301/302 response, or any request with 303 response,
60 // use GET when following redirect
61 if (response.status === 303 || (request.method === 'POST' && [301, 302].includes(response.status))) {
62 _opts.method = 'GET'
63 _opts.body = null
64 request.headers.delete('content-length')
65 }
66
67 _opts.headers = {}
68 request.headers.forEach((value, key) => {
69 _opts.headers[key] = value
70 })
71
72 _opts.counter = ++request.counter
73 const redirectReq = new Request(url.format(redirectUrl), _opts)
74 return {
75 request: redirectReq,
76 options: _opts,
77 }
78}
79
80const fetch = async (request, options) => {
81 const response = CachePolicy.storable(request, options)
82 ? await cache(request, options)
83 : await remote(request, options)
84
85 // if the request wasn't a GET or HEAD, and the response
86 // status is between 200 and 399 inclusive, invalidate the
87 // request url
88 if (!['GET', 'HEAD'].includes(request.method) &&
89 response.status >= 200 &&
90 response.status <= 399)
91 await cache.invalidate(request, options)
92
93 if (!canFollowRedirect(request, response, options))
94 return response
95
96 const redirect = getRedirect(request, response, options)
97 return fetch(redirect.request, redirect.options)
98}
99
100module.exports = fetch
Note: See TracBrowser for help on using the repository browser.