Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
download.js87 linesDownload Raw Back to lib
1const { Readable } = require('stream')
2const { EnvHttpProxyAgent } = require('undici')
3const { promises: fs } = require('graceful-fs')
4const log = require('./log')
5
6async function download (gyp, url) {
7  log.http('GET', url)
8
9  const requestOpts = {
10    headers: {
11      'User-Agent': `node-gyp v${gyp.version} (node ${process.version})`,
12      Connection: 'keep-alive'
13    },
14    dispatcher: await createDispatcher(gyp)
15  }
16
17  let res
18  try {
19    res = await fetch(url, requestOpts)
20  } catch (err) {
21    // Built-in fetch wraps low-level errors in "TypeError: fetch failed" with
22    // the underlying error on .cause. Callers inspect .code (e.g. ENOTFOUND).
23    if (err.cause) {
24      throw err.cause
25    }
26    throw err
27  }
28
29  log.http(res.status, res.url)
30
31  const body = res.body ? Readable.fromWeb(res.body) : Readable.from([])
32  return {
33    status: res.status,
34    url: res.url,
35    body,
36    text: async () => {
37      let data = ''
38      body.setEncoding('utf8')
39      for await (const chunk of body) {
40        data += chunk
41      }
42      return data
43    }
44  }
45}
46
47async function createDispatcher (gyp) {
48  const env = process.env
49  const hasProxyEnv = env.http_proxy || env.HTTP_PROXY || env.https_proxy || env.HTTPS_PROXY
50  if (!gyp.opts.proxy && !gyp.opts.cafile && !hasProxyEnv) {
51    return undefined
52  }
53
54  const opts = {}
55  if (gyp.opts.cafile) {
56    const ca = await readCAFile(gyp.opts.cafile)
57    // EnvHttpProxyAgent forwards opts to both its internal Agent (direct) and
58    // ProxyAgent (proxied). Agent reads TLS config from `connect`; ProxyAgent
59    // reads it from `requestTls` (origin) / `proxyTls` (proxy). Set all three
60    // so the custom CA is applied regardless of which path a request takes.
61    opts.connect = { ca }
62    opts.requestTls = { ca }
63    opts.proxyTls = { ca }
64  }
65  if (gyp.opts.proxy) {
66    opts.httpProxy = gyp.opts.proxy
67    opts.httpsProxy = gyp.opts.proxy
68  }
69  if (gyp.opts.noproxy) {
70    opts.noProxy = gyp.opts.noproxy
71  }
72  return new EnvHttpProxyAgent(opts)
73}
74
75async function readCAFile (filename) {
76  // The CA file can contain multiple certificates so split on certificate
77  // boundaries.  [\S\s]*? is used to match everything including newlines.
78  const ca = await fs.readFile(filename, 'utf8')
79  const re = /(-----BEGIN CERTIFICATE-----[\S\s]*?-----END CERTIFICATE-----)/g
80  return ca.match(re)
81}
82
83module.exports = {
84  download,
85  readCAFile
86}
87 
codekingpro/portable-devtools · Team Ai