You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

93 lines
2.6 KiB

'use strict'
const Buffer = require('safe-buffer').Buffer
const checkWarnings = require('./check-warning-header')
const fetch = require('make-fetch-happen')
const registryKey = require('./registry-key')
const url = require('url')
module.exports = regFetch
function regFetch (uri, registry, opts) {
const startTime = Date.now()
return fetch(uri, {
agent: opts.agent,
algorithms: opts.algorithms,
cache: getCacheMode(opts),
cacheManager: opts.cache,
headers: getHeaders(uri, registry, opts),
integrity: opts.integrity,
memoize: opts.memoize,
noProxy: opts.noProxy,
proxy: opts.proxy,
referer: opts.refer,
retry: opts.retry,
timeout: opts.timeout
}).then(res => {
if (res.headers.has('npm-notice') && !res.headers.has('x-local-cache')) {
opts.log.warn('notice', res.headers.get('npm-notice'))
}
checkWarnings(res, registry, opts)
if (res.status >= 400) {
const err = new Error(`${res.status} ${res.statusText}: ${
opts.spec ? opts.spec : uri
}`)
err.code = `E${res.status}`
err.uri = uri
err.response = res
err.spec = opts.spec
logRequest(uri, res, startTime, opts)
throw err
} else {
res.body.on('end', () => logRequest(uri, res, startTime, opts))
return res
}
})
}
function logRequest (uri, res, startTime, opts) {
const elapsedTime = Date.now() - startTime
const attempt = res.headers.get('x-fetch-attempts')
const attemptStr = attempt && attempt > 1 ? ` attempt #${attempt}` : ''
const cacheStr = res.headers.get('x-local-cache') ? ' (from cache)' : ''
opts.log.http(
'fetch',
`GET ${res.status} ${uri} ${elapsedTime}ms${attemptStr}${cacheStr}`
)
}
function getCacheMode (opts) {
return opts.offline
? 'only-if-cached'
: opts.preferOffline
? 'force-cache'
: opts.preferOnline
? 'no-cache'
: 'default'
}
function getHeaders (uri, registry, opts) {
const headers = Object.assign({
'npm-in-ci': opts.isFromCI,
'npm-scope': opts.projectScope,
'user-agent': opts.userAgent,
'referer': opts.refer
}, opts.headers)
const auth = (
opts.auth &&
// If these two are on different hosts, don't send credentials.
// This is mainly used by the tarball fetcher.
url.parse(uri).host === url.parse(registry).host &&
opts.auth[registryKey(registry)]
)
if (auth && auth.token) {
headers.authorization = `Bearer ${auth.token}`
} else if (auth && opts.alwaysAuth && auth.username && auth.password) {
const encoded = Buffer.from(
`${auth.username}:${auth.password}`, 'utf8'
).toString('base64')
headers.authorization = `Basic ${encoded}`
}
return headers
}