Commit 1ba23cce authored by Robert Knight's avatar Robert Knight

Support serving the client over SSL in development

Following the conventions of the "h" project [1], the client's asset
server (localhost:3001) and demo page server (localhost:3000) will be
served over SSL if a certificate (".tlscert.pem") and private key
(".tlskey.pem") are found in the root of the repository.

This can be useful for testing the development client on pages served
over SSL without having to disable mixed content warnings in the
browser.

[1] https://h.readthedocs.io/en/latest/developing/ssl/
parent ddad3e3b
......@@ -5,3 +5,7 @@ docs/_build/
# The client uses Yarn rather than npm to manage the lockfile.
package-lock.json
# SSL certificate and key.
.tlscert.pem
.tlskey.pem
......@@ -24,6 +24,7 @@ const createBundle = require('./scripts/gulp/create-bundle');
const manifest = require('./scripts/gulp/manifest');
const servePackage = require('./scripts/gulp/serve-package');
const vendorBundles = require('./scripts/gulp/vendor-bundles');
const { useSsl } = require('./scripts/gulp/create-server');
const IS_PRODUCTION_BUILD = process.env.NODE_ENV === 'production';
const SCRIPT_DIR = 'build/scripts';
......@@ -272,7 +273,8 @@ function generateBootScript(manifest) {
if (process.env.NODE_ENV === 'production') {
defaultAssetRoot = `https://cdn.hypothes.is/hypothesis/${version}/`;
} else {
defaultAssetRoot = `http://${packageServerHostname()}:3001/hypothesis/${version}/`;
const scheme = useSsl ? 'https': 'http';
defaultAssetRoot = `${scheme}://${packageServerHostname()}:3001/hypothesis/${version}/`;
}
if (isFirstBuild) {
......@@ -325,8 +327,9 @@ gulp.task('watch-manifest', function () {
gulp.task('serve-live-reload', ['serve-package'], function () {
const LiveReloadServer = require('./scripts/gulp/live-reload-server');
const scheme = useSsl ? 'https' : 'http';
liveReloadServer = new LiveReloadServer(3000, {
clientUrl: `http://${packageServerHostname()}:3001/hypothesis`,
clientUrl: `${scheme}://${packageServerHostname()}:3001/hypothesis`,
});
});
......
'use strict';
const { existsSync, readFileSync } = require('fs');
const https = require('https');
const http = require('http');
const SSL_KEYFILE = '.tlskey.pem';
const SSL_CERTFILE = '.tlscert.pem';
/**
* `true` if dev servers created using `createServer` use SSL.
*
* @type {boolean}
*/
const useSsl = existsSync(SSL_KEYFILE) && existsSync(SSL_CERTFILE);
/**
* Create an HTTP(S) server to serve client assets in development.
*
* Uses SSL if ".tlskey.pem" and ".tlscert.pem" files exist in the root of
* the repository or plain HTTP otherwise.
*
* @param {Function} requestListener
*/
function createServer(requestListener) {
let server;
if (useSsl) {
const options = {
cert: readFileSync(SSL_CERTFILE),
key: readFileSync(SSL_KEYFILE),
};
server = https.createServer(options, requestListener);
} else {
server = http.createServer(requestListener);
}
return server;
}
module.exports = {
createServer,
useSsl,
};
......@@ -2,10 +2,11 @@
const fs = require('fs');
const gulpUtil = require('gulp-util');
const http = require('http');
const WebSocketServer = require('websocket').server;
const urlParser = require('url');
const { createServer, useSsl } = require('./create-server');
function readmeText() {
return fs.readFileSync('./README.md', 'utf-8');
}
......@@ -41,7 +42,7 @@ function LiveReloadServer(port, config) {
function listen() {
const log = gulpUtil.log;
const server = http.createServer(function (req, response) {
const app = function (req, response) {
const url = urlParser.parse(req.url);
let content;
......@@ -136,13 +137,15 @@ function LiveReloadServer(port, config) {
`;
}
response.end(content);
});
};
const server = createServer(app);
server.listen(port, function (err) {
if (err) {
log('Setting up live reload server failed', err);
}
log(`Live reload server listening at http://localhost:${port}/`);
const scheme = useSsl ? 'https' : 'http';
log(`Live reload server listening at ${scheme}://localhost:${port}/`);
});
const ws = new WebSocketServer({
......
......@@ -5,6 +5,7 @@ const { readFileSync } = require('fs');
const express = require('express');
const { log } = require('gulp-util');
const { createServer, useSsl } = require('./create-server');
const { version } = require('../../package.json');
/**
......@@ -40,8 +41,9 @@ function servePackage(port, hostname) {
app.get(`/hypothesis/${version}`, serveBootScript);
app.use(`/hypothesis/${version}/`, express.static('.'));
app.listen(port, function () {
log(`Package served at http://${hostname}:${port}/hypothesis`);
createServer(app).listen(port, () => {
const scheme = useSsl ? 'https' : 'http';
log(`Package served at ${scheme}://${hostname}:${port}/hypothesis`);
});
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment