/** * Fetch an HTTP url to a local file. **/ var request = require("request") , fs = require("graceful-fs") , npm = require("../npm.js") , url = require("url") , log = require("npmlog") , path = require("path") , mkdir = require("mkdirp") , chownr = require("chownr") , regHost , once = require("once") , crypto = require("crypto") module.exports = fetch function fetch (remote, local, headers, cb) { if (typeof cb !== "function") cb = headers, headers = {} cb = once(cb) log.verbose("fetch", "to=", local) mkdir(path.dirname(local), function (er, made) { if (er) return cb(er) fetch_(remote, local, headers, cb) }) } function fetch_ (remote, local, headers, cb) { var fstr = fs.createWriteStream(local, { mode : npm.modes.file }) var response = null fstr.on("error", function (er) { cb(er) fstr.destroy() }) var req = makeRequest(remote, fstr, headers) req.on("response", function (res) { log.http(res.statusCode, remote) response = res response.resume() // Work around bug in node v0.10.0 where the CryptoStream // gets stuck and never starts reading again. if (process.version === "v0.10.0") { response.resume = function (orig) { return function() { var ret = orig.apply(response, arguments) if (response.socket.encrypted) response.socket.encrypted.read(0) return ret }}(response.resume) } }) fstr.on("close", function () { var er if (response && response.statusCode && response.statusCode >= 400) { er = new Error(response.statusCode + " " + require("http").STATUS_CODES[response.statusCode]) } cb(er, response) }) } function makeRequest (remote, fstr, headers) { remote = url.parse(remote) log.http("GET", remote.href) regHost = regHost || url.parse(npm.config.get("registry")).host if (remote.host === regHost && npm.config.get("always-auth")) { remote.auth = new Buffer( npm.config.get("_auth") , "base64" ).toString("utf8") if (!remote.auth) return fstr.emit("error", new Error( "Auth required and none provided. Please run 'npm adduser'")) } var proxy if (remote.protocol !== "https:" || !(proxy = npm.config.get("https-proxy"))) { proxy = npm.config.get("proxy") } var sessionToken = npm.registry.sessionToken if (!sessionToken) { sessionToken = crypto.randomBytes(8).toString("hex") npm.registry.sessionToken = sessionToken } var ca = remote.host === regHost ? npm.config.get("ca") : undefined var opts = { url: remote , proxy: proxy , strictSSL: npm.config.get("strict-ssl") , rejectUnauthorized: npm.config.get("strict-ssl") , ca: ca , headers: { "user-agent": npm.config.get("user-agent") , "npm-session": sessionToken , referer: npm.registry.refer } } var req = request(opts) req.on("error", function (er) { fstr.emit("error", er) }) req.pipe(fstr) return req }