summaryrefslogtreecommitdiff
path: root/deps/npm/node_modules/npm-registry-client/lib/fetch.js
blob: 5ab8587780f20686682bb0d717e3ed57deed4416 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
var assert = require('assert')
var url = require('url')

var request = require('request')
var once = require('once')

module.exports = fetch

function fetch (uri, params, cb) {
  assert(typeof uri === 'string', 'must pass uri to request')
  assert(params && typeof params === 'object', 'must pass params to request')
  assert(typeof cb === 'function', 'must pass callback to request')

  cb = once(cb)

  var client = this
  this.attempt(function (operation) {
    makeRequest.call(client, uri, params, function (er, req) {
      if (er) return cb(er)

      req.once('error', retryOnError)

      function retryOnError (er) {
        if (operation.retry(er)) {
          client.log.info('retry', 'will retry, error on last attempt: ' + er)
        } else {
          cb(er)
        }
      }

      req.on('response', function (res) {
        client.log.http('fetch', '' + res.statusCode, uri)
        req.removeListener('error', retryOnError)

        var er
        var statusCode = res && res.statusCode
        if (statusCode === 200) {
          res.resume()

          req.once('error', function (er) {
            res.emit('error', er)
          })

          return cb(null, res)
          // Only retry on 408, 5xx or no `response`.
        } else if (statusCode === 408) {
          er = new Error('request timed out')
        } else if (statusCode >= 500) {
          er = new Error('server error ' + statusCode)
        }

        if (er && operation.retry(er)) {
          client.log.info('retry', 'will retry, error on last attempt: ' + er)
        } else {
          cb(new Error('fetch failed with status code ' + statusCode))
        }
      })
    })
  })
}

function makeRequest (remote, params, cb) {
  var parsed = url.parse(remote)
  this.log.http('fetch', 'GET', parsed.href)

  var headers = params.headers || {}
  var er = this.authify(
    params.auth && params.auth.alwaysAuth,
    parsed,
    headers,
    params.auth
  )
  if (er) return cb(er)

  var opts = this.initialize(
    parsed,
    'GET',
    'application/x-tar, application/vnd.github+json; q=0.1',
    headers
  )
  // always want to follow redirects for fetch
  opts.followRedirect = true

  cb(null, request(opts))
}