trouble-in-terror-town/node_modules/npm-registry-fetch/lib/check-response.js
Mikolaj 2bbacbea09 did some more work on networking and removed EOS in favor of LRM
did some more work on networking and removed EOS in favor of Light Reflective Mirror
2022-05-31 15:04:31 +02:00

98 lines
3.2 KiB
JavaScript

'use strict'
const errors = require('./errors.js')
const { Response } = require('minipass-fetch')
const defaultOpts = require('./default-opts.js')
const log = require('proc-log')
const cleanUrl = require('./clean-url.js')
/* eslint-disable-next-line max-len */
const moreInfoUrl = 'https://github.com/npm/cli/wiki/No-auth-for-URI,-but-auth-present-for-scoped-registry'
const checkResponse =
async ({ method, uri, res, startTime, auth, opts }) => {
opts = { ...defaultOpts, ...opts }
if (res.headers.has('npm-notice') && !res.headers.has('x-local-cache')) {
log.notice('', res.headers.get('npm-notice'))
}
if (res.status >= 400) {
logRequest(method, res, startTime)
if (auth && auth.scopeAuthKey && !auth.token && !auth.auth) {
// we didn't have auth for THIS request, but we do have auth for
// requests to the registry indicated by the spec's scope value.
// Warn the user.
log.warn('registry', `No auth for URI, but auth present for scoped registry.
URI: ${uri}
Scoped Registry Key: ${auth.scopeAuthKey}
More info here: ${moreInfoUrl}`)
}
return checkErrors(method, res, startTime, opts)
} else {
res.body.on('end', () => logRequest(method, res, startTime, opts))
if (opts.ignoreBody) {
res.body.resume()
return new Response(null, res)
}
return res
}
}
module.exports = checkResponse
function logRequest (method, res, startTime) {
const elapsedTime = Date.now() - startTime
const attempt = res.headers.get('x-fetch-attempts')
const attemptStr = attempt && attempt > 1 ? ` attempt #${attempt}` : ''
const cacheStatus = res.headers.get('x-local-cache-status')
const cacheStr = cacheStatus ? ` (cache ${cacheStatus})` : ''
const urlStr = cleanUrl(res.url)
log.http(
'fetch',
`${method.toUpperCase()} ${res.status} ${urlStr} ${elapsedTime}ms${attemptStr}${cacheStr}`
)
}
function checkErrors (method, res, startTime, opts) {
return res.buffer()
.catch(() => null)
.then(body => {
let parsed = body
try {
parsed = JSON.parse(body.toString('utf8'))
} catch (e) {}
if (res.status === 401 && res.headers.get('www-authenticate')) {
const auth = res.headers.get('www-authenticate')
.split(/,\s*/)
.map(s => s.toLowerCase())
if (auth.indexOf('ipaddress') !== -1) {
throw new errors.HttpErrorAuthIPAddress(
method, res, parsed, opts.spec
)
} else if (auth.indexOf('otp') !== -1) {
throw new errors.HttpErrorAuthOTP(
method, res, parsed, opts.spec
)
} else {
throw new errors.HttpErrorAuthUnknown(
method, res, parsed, opts.spec
)
}
} else if (
res.status === 401 &&
body != null &&
/one-time pass/.test(body.toString('utf8'))
) {
// Heuristic for malformed OTP responses that don't include the
// www-authenticate header.
throw new errors.HttpErrorAuthOTP(
method, res, parsed, opts.spec
)
} else {
throw new errors.HttpErrorGeneral(
method, res, parsed, opts.spec
)
}
})
}