support to specify the `buildHttp.proxy` for `HttpUrlPlugin`

This commit is contained in:
Aleen 2022-02-10 11:01:55 +08:00
parent 8524b28c6c
commit f05009b698
9 changed files with 68 additions and 22 deletions

View File

@ -2900,6 +2900,10 @@ export interface HttpUriOptions {
* Location of the lockfile.
*/
lockfileLocation?: string;
/**
* Proxy configuration, which can be used to specify a proxy server to use for HTTP requests.
*/
proxy?: string;
/**
* When set, resources of existing lockfile entries will be fetched and entries will be upgraded when resource content has changed.
*/

View File

@ -34,6 +34,10 @@ export interface HttpUriOptions {
* Location of the lockfile.
*/
lockfileLocation?: string;
/**
* Proxy configuration, which can be used to specify a proxy server to use for HTTP requests.
*/
proxy?: string;
/**
* When set, resources of existing lockfile entries will be fetched and entries will be upgraded when resource content has changed.
*/

View File

@ -5,6 +5,7 @@
"use strict";
const EventEmitter = require("events");
const { extname, basename } = require("path");
const { URL } = require("url");
const { createGunzip, createBrotliDecompress, createInflate } = require("zlib");
@ -19,13 +20,15 @@ const memoize = require("../util/memoize");
const getHttp = memoize(() => require("http"));
const getHttps = memoize(() => require("https"));
const proxyFetch = request => (url, options, callback) =>
new Promise(resolve => {
const key = "http_proxy";
const proxyUrl = process.env[key] || process.env[key.toUpperCase()];
if (!proxyUrl) return resolve();
const proxyFetch = (request, proxy) => (url, options, callback) => {
const eventEmitter = new EventEmitter();
const doRequest = socket =>
request
.get(url, { ...options, ...(socket && { socket }) }, callback)
.on("error", eventEmitter.emit.bind(eventEmitter, "error"));
const { hostname: host, port } = new URL(proxyUrl);
if (proxy) {
const { hostname: host, port } = new URL(proxy);
getHttp()
.request({
@ -37,16 +40,24 @@ const proxyFetch = request => (url, options, callback) =>
.on("connect", (res, socket) => {
if (res.statusCode === 200) {
// connected to proxy server
resolve(socket);
doRequest(socket);
}
})
.on("error", err => {
console.error("Failed to connect to the proxy:", err);
eventEmitter.emit(
"error",
new Error(
`Failed to connect to proxy server "${proxy}": ${err.message}`
)
);
})
.end();
}).then(socket =>
request.get(url, { ...options, ...(socket && { socket }) }, callback)
);
} else {
doRequest();
}
return eventEmitter;
};
/** @type {(() => void)[] | undefined} */
let inProgressWrite = undefined;
@ -302,6 +313,7 @@ class HttpUriPlugin {
this._upgrade = options.upgrade;
this._frozen = options.frozen;
this._allowedUris = options.allowedUris;
this._proxy = options.proxy;
}
/**
@ -310,14 +322,16 @@ class HttpUriPlugin {
* @returns {void}
*/
apply(compiler) {
const proxy =
this._proxy || process.env["http_proxy"] || process.env["HTTP_PROXY"];
const schemes = [
{
scheme: "http",
fetch: proxyFetch(getHttp())
fetch: proxyFetch(getHttp(), proxy)
},
{
scheme: "https",
fetch: proxyFetch(getHttps())
fetch: proxyFetch(getHttps(), proxy)
}
];
let lockfileCache;
@ -700,13 +714,11 @@ class HttpUriPlugin {
});
});
}
).then(request =>
request.on("error", err => {
logger.log(`GET ${url} (error)`);
err.message += `\nwhile fetching ${url}`;
callback(err);
})
);
).on("error", err => {
logger.log(`GET ${url} (error)`);
err.message += `\nwhile fetching ${url}`;
callback(err);
});
};
const fetchContent = cachedWithKey(

File diff suppressed because one or more lines are too long

View File

@ -1425,6 +1425,10 @@
"type": "string",
"absolutePath": true
},
"proxy": {
"description": "Proxy configuration, which can be used to specify a proxy server to use for HTTP requests.",
"type": "string"
},
"upgrade": {
"description": "When set, resources of existing lockfile entries will be fetched and entries will be upgraded when resource content has changed.",
"type": "boolean"

View File

@ -3,4 +3,4 @@
* DO NOT MODIFY BY HAND.
* Run `yarn special-lint-fix` to update
*/
const r=/^(?:[A-Za-z]:[\\/]|\\\\|\/)/;module.exports=n,module.exports.default=n;const t=new RegExp("^https?://","u");function e(n,{instancePath:o="",parentData:s,parentDataProperty:a,rootData:l=n}={}){let i=null,p=0;if(0===p){if(!n||"object"!=typeof n||Array.isArray(n))return e.errors=[{params:{type:"object"}}],!1;{let o;if(void 0===n.allowedUris&&(o="allowedUris"))return e.errors=[{params:{missingProperty:o}}],!1;{const o=p;for(const r in n)if("allowedUris"!==r&&"cacheLocation"!==r&&"frozen"!==r&&"lockfileLocation"!==r&&"upgrade"!==r)return e.errors=[{params:{additionalProperty:r}}],!1;if(o===p){if(void 0!==n.allowedUris){let r=n.allowedUris;const o=p;if(p==p){if(!Array.isArray(r))return e.errors=[{params:{type:"array"}}],!1;{const n=r.length;for(let o=0;o<n;o++){let n=r[o];const s=p,a=p;let l=!1;const f=p;if(!(n instanceof RegExp)){const r={params:{}};null===i?i=[r]:i.push(r),p++}var c=f===p;if(l=l||c,!l){const r=p;if(p===r)if("string"==typeof n){if(!t.test(n)){const r={params:{pattern:"^https?://"}};null===i?i=[r]:i.push(r),p++}}else{const r={params:{type:"string"}};null===i?i=[r]:i.push(r),p++}if(c=r===p,l=l||c,!l){const r=p;if(!(n instanceof Function)){const r={params:{}};null===i?i=[r]:i.push(r),p++}c=r===p,l=l||c}}if(!l){const r={params:{}};return null===i?i=[r]:i.push(r),p++,e.errors=i,!1}if(p=a,null!==i&&(a?i.length=a:i=null),s!==p)break}}}var f=o===p}else f=!0;if(f){if(void 0!==n.cacheLocation){let t=n.cacheLocation;const o=p,s=p;let a=!1;const l=p;if(!1!==t){const r={params:{}};null===i?i=[r]:i.push(r),p++}var u=l===p;if(a=a||u,!a){const e=p;if(p===e)if("string"==typeof t){if(t.includes("!")||!0!==r.test(t)){const r={params:{}};null===i?i=[r]:i.push(r),p++}}else{const r={params:{type:"string"}};null===i?i=[r]:i.push(r),p++}u=e===p,a=a||u}if(!a){const r={params:{}};return null===i?i=[r]:i.push(r),p++,e.errors=i,!1}p=s,null!==i&&(s?i.length=s:i=null),f=o===p}else f=!0;if(f){if(void 0!==n.frozen){const r=p;if("boolean"!=typeof n.frozen)return e.errors=[{params:{type:"boolean"}}],!1;f=r===p}else f=!0;if(f){if(void 0!==n.lockfileLocation){let t=n.lockfileLocation;const o=p;if(p===o){if("string"!=typeof t)return e.errors=[{params:{type:"string"}}],!1;if(t.includes("!")||!0!==r.test(t))return e.errors=[{params:{}}],!1}f=o===p}else f=!0;if(f)if(void 0!==n.upgrade){const r=p;if("boolean"!=typeof n.upgrade)return e.errors=[{params:{type:"boolean"}}],!1;f=r===p}else f=!0}}}}}}}return e.errors=i,0===p}function n(r,{instancePath:t="",parentData:o,parentDataProperty:s,rootData:a=r}={}){let l=null,i=0;const p=i;let c=!1,f=null;const u=i;if(e(r,{instancePath:t,parentData:o,parentDataProperty:s,rootData:a})||(l=null===l?e.errors:l.concat(e.errors),i=l.length),u===i&&(c=!0,f=0),!c){const r={params:{passingSchemas:f}};return null===l?l=[r]:l.push(r),i++,n.errors=l,!1}return i=p,null!==l&&(p?l.length=p:l=null),n.errors=l,0===i}
const r=/^(?:[A-Za-z]:[\\/]|\\\\|\/)/;module.exports=n,module.exports.default=n;const t=new RegExp("^https?://","u");function e(n,{instancePath:o="",parentData:s,parentDataProperty:a,rootData:l=n}={}){let i=null,p=0;if(0===p){if(!n||"object"!=typeof n||Array.isArray(n))return e.errors=[{params:{type:"object"}}],!1;{let o;if(void 0===n.allowedUris&&(o="allowedUris"))return e.errors=[{params:{missingProperty:o}}],!1;{const o=p;for(const r in n)if("allowedUris"!==r&&"cacheLocation"!==r&&"frozen"!==r&&"lockfileLocation"!==r&&"proxy"!==r&&"upgrade"!==r)return e.errors=[{params:{additionalProperty:r}}],!1;if(o===p){if(void 0!==n.allowedUris){let r=n.allowedUris;const o=p;if(p==p){if(!Array.isArray(r))return e.errors=[{params:{type:"array"}}],!1;{const n=r.length;for(let o=0;o<n;o++){let n=r[o];const s=p,a=p;let l=!1;const c=p;if(!(n instanceof RegExp)){const r={params:{}};null===i?i=[r]:i.push(r),p++}var f=c===p;if(l=l||f,!l){const r=p;if(p===r)if("string"==typeof n){if(!t.test(n)){const r={params:{pattern:"^https?://"}};null===i?i=[r]:i.push(r),p++}}else{const r={params:{type:"string"}};null===i?i=[r]:i.push(r),p++}if(f=r===p,l=l||f,!l){const r=p;if(!(n instanceof Function)){const r={params:{}};null===i?i=[r]:i.push(r),p++}f=r===p,l=l||f}}if(!l){const r={params:{}};return null===i?i=[r]:i.push(r),p++,e.errors=i,!1}if(p=a,null!==i&&(a?i.length=a:i=null),s!==p)break}}}var c=o===p}else c=!0;if(c){if(void 0!==n.cacheLocation){let t=n.cacheLocation;const o=p,s=p;let a=!1;const l=p;if(!1!==t){const r={params:{}};null===i?i=[r]:i.push(r),p++}var u=l===p;if(a=a||u,!a){const e=p;if(p===e)if("string"==typeof t){if(t.includes("!")||!0!==r.test(t)){const r={params:{}};null===i?i=[r]:i.push(r),p++}}else{const r={params:{type:"string"}};null===i?i=[r]:i.push(r),p++}u=e===p,a=a||u}if(!a){const r={params:{}};return null===i?i=[r]:i.push(r),p++,e.errors=i,!1}p=s,null!==i&&(s?i.length=s:i=null),c=o===p}else c=!0;if(c){if(void 0!==n.frozen){const r=p;if("boolean"!=typeof n.frozen)return e.errors=[{params:{type:"boolean"}}],!1;c=r===p}else c=!0;if(c){if(void 0!==n.lockfileLocation){let t=n.lockfileLocation;const o=p;if(p===o){if("string"!=typeof t)return e.errors=[{params:{type:"string"}}],!1;if(t.includes("!")||!0!==r.test(t))return e.errors=[{params:{}}],!1}c=o===p}else c=!0;if(c){if(void 0!==n.proxy){const r=p;if("string"!=typeof n.proxy)return e.errors=[{params:{type:"string"}}],!1;c=r===p}else c=!0;if(c)if(void 0!==n.upgrade){const r=p;if("boolean"!=typeof n.upgrade)return e.errors=[{params:{type:"boolean"}}],!1;c=r===p}else c=!0}}}}}}}}return e.errors=i,0===p}function n(r,{instancePath:t="",parentData:o,parentDataProperty:s,rootData:a=r}={}){let l=null,i=0;const p=i;let f=!1,c=null;const u=i;if(e(r,{instancePath:t,parentData:o,parentDataProperty:s,rootData:a})||(l=null===l?e.errors:l.concat(e.errors),i=l.length),u===i&&(f=!0,c=0),!f){const r={params:{passingSchemas:c}};return null===l?l=[r]:l.push(r),i++,n.errors=l,!1}return i=p,null!==l&&(p?l.length=p:l=null),n.errors=l,0===i}

View File

@ -29,6 +29,10 @@
"type": "string",
"absolutePath": true
},
"proxy": {
"description": "Proxy configuration, which can be used to specify a proxy server to use for HTTP requests.",
"type": "string"
},
"upgrade": {
"description": "When set, resources of existing lockfile entries will be fetched and entries will be upgraded when resource content has changed.",
"type": "boolean"

View File

@ -568,6 +568,19 @@ Object {
"multiple": false,
"simpleType": "string",
},
"experiments-build-http-proxy": Object {
"configs": Array [
Object {
"description": "Proxy configuration, which can be used to specify a proxy server to use for HTTP requests.",
"multiple": false,
"path": "experiments.buildHttp.proxy",
"type": "string",
},
],
"description": "Proxy configuration, which can be used to specify a proxy server to use for HTTP requests.",
"multiple": false,
"simpleType": "string",
},
"experiments-build-http-upgrade": Object {
"configs": Array [
Object {

5
types.d.ts vendored
View File

@ -4563,6 +4563,11 @@ declare interface HttpUriOptions {
*/
lockfileLocation?: string;
/**
* Proxy configuration, which can be used to specify a proxy server to use for HTTP requests.
*/
proxy?: string;
/**
* When set, resources of existing lockfile entries will be fetched and entries will be upgraded when resource content has changed.
*/