$
This commit is contained in:
118
node_modules/make-fetch-happen/lib/fetch.js
generated
vendored
Normal file
118
node_modules/make-fetch-happen/lib/fetch.js
generated
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
'use strict'
|
||||
|
||||
const { FetchError, Request, isRedirect } = require('minipass-fetch')
|
||||
const url = require('url')
|
||||
|
||||
const CachePolicy = require('./cache/policy.js')
|
||||
const cache = require('./cache/index.js')
|
||||
const remote = require('./remote.js')
|
||||
|
||||
// given a Request, a Response and user options
|
||||
// return true if the response is a redirect that
|
||||
// can be followed. we throw errors that will result
|
||||
// in the fetch being rejected if the redirect is
|
||||
// possible but invalid for some reason
|
||||
const canFollowRedirect = (request, response, options) => {
|
||||
if (!isRedirect(response.status)) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (options.redirect === 'manual') {
|
||||
return false
|
||||
}
|
||||
|
||||
if (options.redirect === 'error') {
|
||||
throw new FetchError(`redirect mode is set to error: ${request.url}`,
|
||||
'no-redirect', { code: 'ENOREDIRECT' })
|
||||
}
|
||||
|
||||
if (!response.headers.has('location')) {
|
||||
throw new FetchError(`redirect location header missing for: ${request.url}`,
|
||||
'no-location', { code: 'EINVALIDREDIRECT' })
|
||||
}
|
||||
|
||||
if (request.counter >= request.follow) {
|
||||
throw new FetchError(`maximum redirect reached at: ${request.url}`,
|
||||
'max-redirect', { code: 'EMAXREDIRECT' })
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// given a Request, a Response, and the user's options return an object
|
||||
// with a new Request and a new options object that will be used for
|
||||
// following the redirect
|
||||
const getRedirect = (request, response, options) => {
|
||||
const _opts = { ...options }
|
||||
const location = response.headers.get('location')
|
||||
const redirectUrl = new url.URL(location, /^https?:/.test(location) ? undefined : request.url)
|
||||
// Comment below is used under the following license:
|
||||
/**
|
||||
* @license
|
||||
* Copyright (c) 2010-2012 Mikeal Rogers
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an "AS
|
||||
* IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
|
||||
* express or implied. See the License for the specific language
|
||||
* governing permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
// Remove authorization if changing hostnames (but not if just
|
||||
// changing ports or protocols). This matches the behavior of request:
|
||||
// https://github.com/request/request/blob/b12a6245/lib/redirect.js#L134-L138
|
||||
if (new url.URL(request.url).hostname !== redirectUrl.hostname) {
|
||||
request.headers.delete('authorization')
|
||||
request.headers.delete('cookie')
|
||||
}
|
||||
|
||||
// for POST request with 301/302 response, or any request with 303 response,
|
||||
// use GET when following redirect
|
||||
if (
|
||||
response.status === 303 ||
|
||||
(request.method === 'POST' && [301, 302].includes(response.status))
|
||||
) {
|
||||
_opts.method = 'GET'
|
||||
_opts.body = null
|
||||
request.headers.delete('content-length')
|
||||
}
|
||||
|
||||
_opts.headers = {}
|
||||
request.headers.forEach((value, key) => {
|
||||
_opts.headers[key] = value
|
||||
})
|
||||
|
||||
_opts.counter = ++request.counter
|
||||
const redirectReq = new Request(url.format(redirectUrl), _opts)
|
||||
return {
|
||||
request: redirectReq,
|
||||
options: _opts,
|
||||
}
|
||||
}
|
||||
|
||||
const fetch = async (request, options) => {
|
||||
const response = CachePolicy.storable(request, options)
|
||||
? await cache(request, options)
|
||||
: await remote(request, options)
|
||||
|
||||
// if the request wasn't a GET or HEAD, and the response
|
||||
// status is between 200 and 399 inclusive, invalidate the
|
||||
// request url
|
||||
if (!['GET', 'HEAD'].includes(request.method) &&
|
||||
response.status >= 200 &&
|
||||
response.status <= 399) {
|
||||
await cache.invalidate(request, options)
|
||||
}
|
||||
|
||||
if (!canFollowRedirect(request, response, options)) {
|
||||
return response
|
||||
}
|
||||
|
||||
const redirect = getRedirect(request, response, options)
|
||||
return fetch(redirect.request, redirect.options)
|
||||
}
|
||||
|
||||
module.exports = fetch
|
Reference in New Issue
Block a user