Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix handling of https/http for dev proxy #1788

Merged
merged 1 commit into from
Jan 22, 2021
Merged
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
2 changes: 1 addition & 1 deletion packages/xarc-app-dev/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"@babel/preset-react": "^7.0.0",
"@babel/preset-typescript": "^7.0.0",
"@babel/register": "^7.0.0",
"@jchip/redbird": "^1.2.1",
"@jchip/redbird": "^1.2.2",
"@loadable/babel-plugin": "^5.10.0",
"@xarc/subapp": "^0.1.3",
"@xarc/webpack": "^9.1.0",
Expand Down
9 changes: 5 additions & 4 deletions packages/xarc-app-dev/src/config/env-proxy.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { isValidPort } from "../lib/utils";

/* eslint-disable @typescript-eslint/no-var-requires */
export {};

const { merge } = require("lodash");

Expand All @@ -12,9 +13,9 @@ module.exports = function getEnvProxy() {
"ELECTRODE_DEV_HTTPS", // deprecated but still check
"XARC_DEV_HTTPS"
],
default: 0,
envMap: { true: 443, false: 0 },
post: x => x || 0
default: -1,
envMap: { true: 443, false: -1 },
post: x => (isValidPort(x) ? x : -1)
},
adminLogLevel: {
env: [
Expand Down
23 changes: 15 additions & 8 deletions packages/xarc-app-dev/src/config/get-dev-proxy.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-var-requires, max-statements, no-console, prefer-const */

import { getDevAdminPortFromEnv } from "../lib/utils";
import { getDevAdminPortFromEnv, isValidPort } from "../lib/utils";

const Path = require("path");
const Fs = require("fs");
Expand Down Expand Up @@ -81,25 +81,32 @@ module.exports = function createDevProxy() {
const { elevated } = envProxy;
const useDevProxy = appPort > 0;

if (httpsPort) {
port = httpsPort;
// auto do https for 443 or 8443
if ((httpPort === 443 || httpPort === 8443) && !isValidPort(httpsPort)) {
httpsPort = httpPort;
protocol = "https";
} else if (httpPort === 443) {
port = httpsPort = httpPort;
httpPort = appPort !== 3000 ? 3000 : 3300;
}

if (isValidPort(httpsPort)) {
port = httpsPort;
protocol = "https";
// avoid http and https conflicting
if (httpPort === httpsPort) {
httpPort = -1;
}
} else {
port = httpPort;
protocol = "http";
}

const settings = {
host,
port,
port, // the primary port to listen for app, could be http or https
adminLogLevel,
appPort,
httpPort,
httpsPort,
httpPort, // the port to always listen on for HTTP
httpsPort, // dev proxy actually ignores this
https: protocol === "https",
webpackDev,
webpackDevPort,
Expand Down
33 changes: 27 additions & 6 deletions packages/xarc-app-dev/src/config/opt2/xarc-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,32 +16,53 @@ export type XarcOptions = {
* port to listen on for serving your application
*
* @remarks
* This is what the dev proxy listens on. Your app server
* listens on a different port that the proxy forwards to.
* In development, this is what the dev proxy listens on. Your app server
* listens on `appServerPort` that the proxy forwards to.
*
* - Typical values are `3000` for `HTTP` or `443`/`8443` for `HTTPS`.
*
* - **Default: `3000`**
* - If it's 443, then automatically enable HTTPS.
* - If it's `443` or `8443`, then automatically enable `HTTPS` and try
* to **also** listen on `3000` or `3300` for `http`
* - Set it to `0` and the proxy will pick a random port.
* - Set it to `-1` to disable `http` and use `httpsPort` to listen on `https` only.
* - If not set, then check env `PORT`
*
* @remarks Regarding `HTTPS`:
* - If you want full control of `https` and `http` ports, set `httpsPort` and `port`.
* - If you set `port` to `443` or `8443`, then dev proxy do `https` on that port, and
* listens on something that doesn't conflict with `appServerPort`, which is
* `3000` or `3300`.
* - if `https` is enabled, the dev proxy will always try to listen on `http` also.
*
* .
*/
port?: number;

/**
* In case you want to serve your app with https on a port other
* than 443, then you can set it with this.
* Set this to force `https` on the port you want, in case you want to serve your app
* with https on a port other than `443` or `8443`.
*
* - if not set, then check env then `XARC_DEV_HTTPS`
* - Set it to `0` and the proxy will pick a random port for `https`.
* - Set to `-1` to force disable `https`
*
* @remarks
* If this is set, it cannot be the same as `port`, which then will be
* forced to be HTTP only.
* forced to be `http` only.
*
* .
*/
httpsPort?: number;

/**
* Port number for your app server to listen on so the dev proxy
* can forward request to it.
*
* - **Default: `3100`**
* - If not set, then check env `APP_PORT_FOR_PROXY`, then `APP_SERVER_PORT`
*
* .
*/
appServerPort?: number; // renamed from portForProxy

Expand Down
60 changes: 38 additions & 22 deletions packages/xarc-app-dev/src/lib/dev-admin/redbird-proxy.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-var-requires, @typescript-eslint/ban-ts-ignore */
export {};
import { isValidPort } from "../utils";

/* eslint-disable @typescript-eslint/no-var-requires, @typescript-eslint/ban-ts-ignore */
/* eslint-disable max-statements, no-process-exit, global-require, no-console */

const assert = require("assert");
Expand Down Expand Up @@ -221,27 +221,55 @@ const startProxy = (inOptions = {}) => {
const options = Object.assign(
{
xfwd: false,
bunyan: {
level: "warn",
name: "redbird"
pino: {
level: "warn"
},
resolvers: []
},
settings,
inOptions
);

const proxyOptions = _.pick(options, ["port", "xfwd", "bunyan", "resolvers"]);
const proxyOptions = _.pick(options, ["port", "xfwd", "pino", "resolvers"]);
const { host, port, protocol } = options;

const ssl = Boolean(options.httpsPort);
const enableCdnMock = process.argv.includes("--mock-cdn");

let listenReportTimer;
const proxyUrls = {} as any;
proxyOptions.reportListening = (proto, _port, actualPort) => {
proxyUrls[proto] = formUrl({ protocol: proto, host, port: actualPort });
console.log(`Electrode dev proxy listening on ${proto} port`, actualPort);
clearTimeout(listenReportTimer);
listenReportTimer = setTimeout(() => {
const mockCdnMsg = enableCdnMock
? `\nMock CDN is enabled (mapping saved to config/assets.json)\n`
: "\n";
console.log(
ck`${mockCdnMsg}${buildProxyTree(options, ["appPort", "webpackDevPort"])}
View status at <green>${proxyUrls.https || proxyUrls.http}${controlPaths.status}</>`
);

const urlsShow = Object.keys(proxyUrls)
.map(x => {
return ck`<green>${proxyUrls[x]}</>`;
})
.join(" or ");

console.log(ck`You can access your app at ${urlsShow}`);
}, 100).unref();
};

if (ssl) {
const enableSsl = ssl && isValidPort(options.httpsPort);

if (enableSsl) {
const proxyCerts = searchSSLCerts();
assert(proxyCerts.key && proxyCerts.cert, "Dev Proxy can't find SSL key and certs");
const httpPort = isValidPort(options.httpPort) ? options.httpPort : -1;
Object.assign(proxyOptions, {
// We still setup a regular http rules even if HTTPS is enabled
port: options.httpPort,
port: httpPort,
host,
secure: true,
ssl: {
Expand Down Expand Up @@ -286,13 +314,12 @@ const startProxy = (inOptions = {}) => {
res.end();
});

const enableCdnMock = process.argv.includes("--mock-cdn");
const noDev = process.argv.includes("--no-dev");
// register with primary protocol/host/port
registerElectrodeDevRules({ ...options, ssl, proxy, restart, enableCdnMock, noDev });
registerElectrodeDevRules({ ...options, ssl: enableSsl, proxy, restart, enableCdnMock, noDev });

// if primary protocol is https, then register regular http rules at httpPort
if (ssl) {
if (enableSsl && isValidPort(options.httpPort)) {
// @ts-ignore
registerElectrodeDevRules({
proxy,
Expand All @@ -309,17 +336,6 @@ const startProxy = (inOptions = {}) => {
console.log("Calling proxy setupRules from your archetype/config/dev-proxy");
userDevProxy.setupRules(proxy, options);
}

const proxyUrl = formUrl({ protocol, host, port: options.port });
const mockCdnMsg = enableCdnMock
? `\nMock CDN is enabled (mapping saved to config/assets.json)\n`
: "\n";
console.log(
ck`Electrode dev proxy server running:${mockCdnMsg}
${buildProxyTree(options, ["appPort", "webpackDevPort"])}
View status at <green>${proxyUrl}${controlPaths.status}</>`
);
console.log(ck`You can access your app at <green>${proxyUrl}</>`);
};

module.exports = startProxy;
Expand Down
9 changes: 9 additions & 0 deletions packages/xarc-app-dev/src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,12 @@ export function getDevAdminPortFromEnv(fallback?: number): number {

return fromEnv || fallback || 8991;
}

/**
* Check if a port number is valid
* @param p - port number
* @returns `true` or `false`
*/
export const isValidPort = p => {
return Number.isInteger(p) && p >= 0 && p < 65536;
};