Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ Some additional resources for Node.js native addons and writing `gyp` configurat
| `--devdir=$path` | SDK download directory (default is OS cache directory)
| `--ensure` | Don't reinstall headers if already present
| `--dist-url=$url` | Download header tarball from custom URL
| `--dist-url-auth-token=$token` | Use a Bearer token when downloading from the custom distribution URL
| `--proxy=$url` | Set HTTP(S) proxy for downloading header tarball
| `--noproxy=$urls` | Set urls to ignore proxies when downloading header tarball
| `--cafile=$cafile` | Override default CA chain (to download tarball)
Expand Down
26 changes: 22 additions & 4 deletions lib/download.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,16 @@ const log = require('./log')
async function download (gyp, url) {
log.http('GET', url)

const headers = {
'User-Agent': `node-gyp v${gyp.version} (node ${process.version})`,
Connection: 'keep-alive'
}
if (gyp.opts['dist-url-auth-token'] && isDistUrl(gyp, url)) {
headers.Authorization = `Bearer ${gyp.opts['dist-url-auth-token']}`
}

const requestOpts = {
headers: {
'User-Agent': `node-gyp v${gyp.version} (node ${process.version})`,
Connection: 'keep-alive'
},
headers,
dispatcher: await createDispatcher(gyp)
}

Expand Down Expand Up @@ -44,6 +49,19 @@ async function download (gyp, url) {
}
}

function isDistUrl (gyp, url) {
const distUrl = gyp.opts['dist-url'] || gyp.opts.disturl
if (!distUrl) {
return false
}

const base = new URL(distUrl)
const target = new URL(url)
const basePath = base.pathname.endsWith('/') ? base.pathname : base.pathname + '/'

return base.origin === target.origin && target.pathname.startsWith(basePath)
}

async function createDispatcher (gyp) {
const env = process.env
const hasProxyEnv = env.http_proxy || env.HTTP_PROXY || env.https_proxy || env.HTTPS_PROXY
Expand Down
1 change: 1 addition & 0 deletions lib/node-gyp.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class Gyp extends EventEmitter {
loglevel: String, // everywhere
python: String, // 'configure'
'dist-url': String, // 'install'
'dist-url-auth-token': String, // 'install'
tarball: String, // 'install'
jobs: String, // 'build'
thin: String, // 'configure'
Expand Down
44 changes: 44 additions & 0 deletions test/test-download.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,50 @@ describe('download', function () {
assert.strictEqual(await res.text(), 'ok')
})

it('download from a custom distribution URL with an auth token', async function () {
const server = http.createServer((req, res) => {
assert.strictEqual(req.headers.authorization, 'Bearer secret')
res.end('ok')
})

after(() => new Promise((resolve) => server.close(resolve)))

const host = 'localhost'
await new Promise((resolve) => server.listen(0, host, resolve))
const { port } = server.address()
const gyp = {
opts: {
'dist-url': `http://${host}:${port}/mirror`,
'dist-url-auth-token': 'secret'
},
version: '42'
}
const res = await download(gyp, `http://${host}:${port}/mirror/v42/headers.tar.gz`)
assert.strictEqual(await res.text(), 'ok')
})

it('does not send a distribution auth token to another URL', async function () {
const server = http.createServer((req, res) => {
assert.strictEqual(req.headers.authorization, undefined)
res.end('ok')
})

after(() => new Promise((resolve) => server.close(resolve)))

const host = 'localhost'
await new Promise((resolve) => server.listen(0, host, resolve))
const { port } = server.address()
const gyp = {
opts: {
'dist-url': `http://${host}:${port}/mirror`,
'dist-url-auth-token': 'secret'
},
version: '42'
}
const res = await download(gyp, `http://${host}:${port}/other/file`)
assert.strictEqual(await res.text(), 'ok')
})

it('download over https with custom ca', async function () {
const cafile = path.join(__dirname, 'fixtures/ca.crt')
const cacontents = certs['ca.crt']
Expand Down