Skip to content

Commit

Permalink
Support HTTPS development server
Browse files Browse the repository at this point in the history
  • Loading branch information
astronomersiva committed Dec 23, 2018
1 parent c827139 commit a4b3287
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 7 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,17 @@ include directories. For example, in this tree structure,
the URL of nepal.md will be `site.com/nepal` if this option is `true`. By default(`false`), the URL
of this post would be `site.com/travel/nepal`. This option will be overridden if the post's front-matter
has a `url` field.
* `server`: Options for the development server. Refer [live-server](https://github.com/tapio/live-server/#usage-from-node).
* `server.ssl`: If this option is set as `true`, lego will start an HTTPS development server using
a self-signed certificate. Please note that self-signed certificates might not be accepted
by many browsers by default. If you would like to use your own `cert` and `key` files, you
can do so by passing them to this option like,
```javascript
ssl: {
key: 'server.key',
cert: 'server.crt'
}
```

### Installation

Expand Down
38 changes: 32 additions & 6 deletions lib/tasks/startServer.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,41 @@
module.exports = function() {
module.exports = function(site) {
const fs = require('fs-extra');
const liveServer = require('live-server');
const { BUILD } = require('../utils/constants');
const { BUILD, CERT_FILE, KEY_FILE } = require('../utils/constants');

const params = {
let config = site.getConfig();
let options = Object.assign({
port: 8181,
host: '0.0.0.0',
host: '127.0.0.1',
root: BUILD,
open: true,
wait: 50,
logLevel: 0
};
}, config.server);

liveServer.start(params);
let ssl = config.server && config.server.ssl;
if (ssl) {
let httpsOptions = ssl;

if (ssl.key && ssl.cert) {
httpsOptions = {
key: fs.readFileSync(ssl.key),
cert: fs.readFileSync(ssl.cert)
};
} else {
require('../utils/generateSslCert')();

httpsOptions = {
cert: fs.readFileSync(CERT_FILE),
key: fs.readFileSync(KEY_FILE)
};
}

options = {
...options,
https: httpsOptions
};
}

liveServer.start(options);
}
2 changes: 2 additions & 0 deletions lib/utils/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ module.exports = {
STATIC: 'static',
LAYOUTS: 'layouts',
DATA: 'data',
CERT_FILE: 'tmp/ssl.crt',
KEY_FILE: 'tmp/ssl.pem',
IMAGES,
MEDIA: [
...IMAGES,
Expand Down
101 changes: 101 additions & 0 deletions lib/utils/generateSslCert.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
module.exports = function() {
const fs = require('fs-extra');

const { CERT_FILE, KEY_FILE } = require('./constants');
if (fs.existsSync(KEY_FILE) && fs.existsSync(CERT_FILE)) {
return;
}

fs.mkdirSync('tmp');

const forge = require('node-forge')
const pki = forge.pki;

let keys = pki.rsa.generateKeyPair(2048);
let cert = pki.createCertificate();

cert.publicKey = keys.publicKey;

// NOTE: serialNumber is the hex encoded value of an ASN.1 INTEGER.
// Conforming CAs should ensure serialNumber is:
// - no more than 20 octets
// - non-negative (prefix a '00' if your value starts with a '1' bit)

// set serialNumber to a unique value ~ timestamp
cert.serialNumber = Date.now().toString();
cert.validity.notBefore = new Date();
cert.validity.notAfter = new Date();
cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 1);

let attrs = [{
name: 'commonName',
value: 'sivasubramanyam.me'
}, {
name: 'countryName',
value: 'IN'
}, {
shortName: 'ST',
value: 'TN'
}, {
name: 'localityName',
value: 'legoland'
}, {
name: 'organizationName',
value: '@astronomersiva/lego'
}, {
shortName: 'OU',
value: 'Test'
}];

cert.setSubject(attrs);
cert.setIssuer(attrs);

cert.setExtensions([{
name: 'basicConstraints',
cA: true
}, {
name: 'keyUsage',
keyCertSign: true,
digitalSignature: true,
nonRepudiation: true,
keyEncipherment: true,
dataEncipherment: true
}, {
name: 'extKeyUsage',
serverAuth: true,
clientAuth: true,
codeSigning: true,
emailProtection: true,
timeStamping: true
}, {
name: 'nsCertType',
client: true,
server: true,
email: true,
objsign: true,
sslCA: true,
emailCA: true,
objCA: true
}, {
name: 'subjectAltName',
altNames: [{
type: 6, // URI
value: 'http://example.org/webid#me'
}, {
type: 7, // IP
ip: '127.0.0.1'
}]
}, {
name: 'subjectKeyIdentifier'
}]);

// self-sign certificate
cert.sign(keys.privateKey, forge.md.sha256.create());

// convert a Forge certificate to PEM
let crt = pki.certificateToPem(cert);
let key = pki.privateKeyToPem(keys.privateKey);

fs.writeFileSync(KEY_FILE, key);
fs.writeFileSync(CERT_FILE, crt);
};
7 changes: 6 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"markdown-it-container": "^2.0.0",
"markdown-it-front-matter": "^0.1.2",
"markdown-it-link-attributes": "^2.1.0",
"node-forge": "^0.7.6",
"node-version-assets": "^1.2.2",
"p-limit": "^2.0.0",
"postcss": "^7.0.1",
Expand Down

0 comments on commit a4b3287

Please sign in to comment.