|
|
|
/**
|
|
|
|
* 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
|
|
|
|
|
|
|
|
module.exports = fetch
|
|
|
|
|
|
|
|
function fetch (remote, local, headers, cb) {
|
|
|
|
if (typeof cb !== "function") cb = headers, headers = {}
|
|
|
|
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 })
|
|
|
|
fstr.on("error", function (er) {
|
|
|
|
fs.close(fstr.fd, function () {})
|
|
|
|
if (fstr._ERROR) return
|
|
|
|
cb(fstr._ERROR = er)
|
|
|
|
})
|
|
|
|
fstr.on("open", function () {
|
|
|
|
makeRequest(remote, fstr, headers)
|
|
|
|
})
|
|
|
|
fstr.on("close", function () {
|
|
|
|
if (fstr._ERROR) return
|
|
|
|
cb()
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
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 = npm.config.get( remote.protocol === "https:"
|
|
|
|
? "https-proxy"
|
|
|
|
: "proxy")
|
|
|
|
|
|
|
|
request({ url: remote
|
|
|
|
, proxy: proxy
|
|
|
|
, strictSSL: npm.config.get("strict-ssl")
|
|
|
|
, ca: remote.host === regHost ? npm.config.get("ca") : undefined
|
|
|
|
, headers: { "user-agent": npm.config.get("user-agent") }
|
|
|
|
, onResponse: onResponse }).pipe(fstr)
|
|
|
|
function onResponse (er, res) {
|
|
|
|
if (er) return fstr.emit("error", er)
|
|
|
|
log.http(res.statusCode, remote.href)
|
|
|
|
}
|
|
|
|
}
|