diff --git a/packages/react-dev-utils/WebpackDevServerUtils.js b/packages/react-dev-utils/WebpackDevServerUtils.js index 1cd060592f9..464cd559f4c 100644 --- a/packages/react-dev-utils/WebpackDevServerUtils.js +++ b/packages/react-dev-utils/WebpackDevServerUtils.js @@ -16,6 +16,7 @@ const chalk = require('chalk'); const detect = require('detect-port-alt'); const isRoot = require('is-root'); const inquirer = require('inquirer'); +const HttpsProxyAgent = require('https-proxy-agent'); const clearConsole = require('./clearConsole'); const formatWebpackMessages = require('./formatWebpackMessages'); const getProcessForPort = require('./getProcessForPort'); @@ -364,6 +365,21 @@ function prepareProxy(proxy, appPublicFolder) { } else { target = proxy[context].target; } + let proxyAgent; + if (proxy[context].hasOwnProperty('agent') || process.env.PROXY_AGENT) { + const agentVal = proxy[context].agent || process.env.PROXY_AGENT; + if (typeof agentVal !== 'string') { + console.log( + chalk.red('"agent" value in package.json must be a string') + ); + process.exit(1); + } + if (agentVal.toLowerCase() !== 'none') { + proxyAgent = process.env[agentVal] + ? new HttpsProxyAgent(process.env[agentVal]) + : new HttpsProxyAgent(agentVal); + } + } return Object.assign({}, proxy[context], { context: function(pathname) { return mayProxy(pathname) && pathname.match(context); @@ -377,6 +393,7 @@ function prepareProxy(proxy, appPublicFolder) { } }, target, + agent: proxyAgent ? proxyAgent : undefined, onError: onProxyError(target), }); }); diff --git a/packages/react-dev-utils/package.json b/packages/react-dev-utils/package.json index 0e4e135f89f..95447f0b021 100644 --- a/packages/react-dev-utils/package.json +++ b/packages/react-dev-utils/package.json @@ -45,6 +45,7 @@ "global-modules": "1.0.0", "gzip-size": "3.0.0", "html-entities": "1.2.1", + "https-proxy-agent": "^2.1.0", "inquirer": "3.2.1", "is-root": "1.0.0", "opn": "5.1.0", diff --git a/packages/react-scripts/template/README.md b/packages/react-scripts/template/README.md index c55ccdf949f..935e605922f 100644 --- a/packages/react-scripts/template/README.md +++ b/packages/react-scripts/template/README.md @@ -46,6 +46,7 @@ You can find the most recent version of this guide [here](https://github.com/fac - ["Invalid Host Header" Errors After Configuring Proxy](#invalid-host-header-errors-after-configuring-proxy) - [Configuring the Proxy Manually](#configuring-the-proxy-manually) - [Configuring a WebSocket Proxy](#configuring-a-websocket-proxy) + - [Configuring the Proxy Behind a Network Proxy](#configuring-the-proxy-behind-a-network-proxy) - [Using HTTPS in Development](#using-https-in-development) - [Generating Dynamic `` Tags on the Server](#generating-dynamic-meta-tags-on-the-server) - [Pre-Rendering into Static HTML Files](#pre-rendering-into-static-html-files) @@ -1114,6 +1115,65 @@ Either way, you can proxy WebSocket requests manually in `package.json`: } ``` +### Configuring the Proxy Behind a Network Proxy + +If you are behind a network proxy (common in corporate environments), and require requests to the url specified in the `target` property of the `proxy` object to be forwarded through your network proxy, you may specify an `agent` property in your `package.json` under the `proxy` object. +The `agent` property must be a string value representing either the environment variable containing your network proxy configuration (case sensitive), or the proxy configuration itself, in the format: + +`://[:@]:` + +eg: `http://myproxy.com:8080` + +or: `http://my_name:my_password@myproxy.com:8080` + +You may also set the network proxy for all specified proxies via an environment variable named `PROXY_AGENT` either in your system environment variables or your `.env` or `.env.development` files. + +If the `PROXY_AGENT` environment variable exists, it will be used for all proxies which do not explicitly set an `agent` property manually. If you need to exclude a proxy from using the `PROXY_AGENT` value, simply set the `agent` property to "none". + +A more complete example of using the proxy agent is: + +```js +{ + // ... + "proxy": { + // Matches any request starting with /api + "/api": { + "target": "", + "ws": true + // Specify a network proxy agent for this context via environment variable + "agent": "http_proxy" + // ... + }, + // Matches any request starting with /foo + "/foo": { + "target": "", + "ssl": true, + "pathRewrite": { + "^/foo": "/foo/beta" + } + // Specify a network proxy agent for this context directly + "agent": "http://username:password@myproxy.local:8080" + // ... + }, + // Matches /bar/abc.html but not /bar/sub/def.html + // Does not need to be forwarded through the network proxy as it is local to the machine + "/bar/*.html": { + "target": "http://localhost:5000/bar_api", + // ... + }, + // Matches /baz/abc.html and /baz/sub/def.html + // Does not need to be forwarded through the network proxy as it is in the local domain, explicitly setting to none to override "PROXY_AGENT" environment variable + "/baz/**/*.html": { + "target": "http://apiserver.local", + "agent": "none" + // ... + } + } + // ... +} +``` + + ## Using HTTPS in Development >Note: this feature is available with `react-scripts@0.4.0` and higher.