1 var assert = require('assert')
2 var url = require('url')
4 var request = require('request')
5 var once = require('once')
9 function fetch (uri, params, cb) {
10 assert(typeof uri === 'string', 'must pass uri to request')
11 assert(params && typeof params === 'object', 'must pass params to request')
12 assert(typeof cb === 'function', 'must pass callback to request')
17 this.attempt(function (operation) {
18 makeRequest.call(client, uri, params, function (er, req) {
21 req.on('error', function (er) {
22 if (operation.retry(er)) {
23 client.log.info('retry', 'will retry, error on last attempt: ' + er)
29 req.on('response', function (res) {
30 client.log.http('fetch', '' + res.statusCode, uri)
33 var statusCode = res && res.statusCode
34 if (statusCode === 200) {
35 // Work around bug in node v0.10.0 where the CryptoStream
36 // gets stuck and never starts reading again.
38 if (process.version === 'v0.10.0') unstick(res)
41 // Only retry on 408, 5xx or no `response`.
42 } else if (statusCode === 408) {
43 er = new Error('request timed out')
44 } else if (statusCode >= 500) {
45 er = new Error('server error ' + statusCode)
48 if (er && operation.retry(er)) {
49 client.log.info('retry', 'will retry, error on last attempt: ' + er)
51 cb(new Error('fetch failed with status code ' + statusCode))
58 function unstick (response) {
59 response.resume = (function (orig) {
61 var ret = orig.apply(response, arguments)
62 if (response.socket.encrypted) response.socket.encrypted.read(0)
68 function makeRequest (remote, params, cb) {
69 var parsed = url.parse(remote)
70 this.log.http('fetch', 'GET', parsed.href)
72 var headers = params.headers || {}
73 var er = this.authify(
74 params.auth && params.auth.alwaysAuth,
81 var opts = this.initialize(
84 'application/x-tar, application/vnd.github+json; q=0.1',
87 // always want to follow redirects for fetch
88 opts.followRedirect = true
90 cb(null, request(opts))