more
This commit is contained in:
parent
260f0592be
commit
419b84a1ab
87
README.md
87
README.md
|
@ -1,4 +1,5 @@
|
|||
# letsencrypt-express
|
||||
|
||||
Free SSL and Automatic HTTPS for node.js with Express, Connect, and other middleware systems
|
||||
|
||||
## Coming Soon
|
||||
|
@ -9,6 +10,78 @@ We're working on it
|
|||
|
||||
See [examples/express-minimal.js](https://github.com/Daplie/node-letsencrypt/blob/master/examples/express-minimal.js)
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
npm install --save letsencrypt-express
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
**Minimal**
|
||||
|
||||
```javascript
|
||||
'use strict';
|
||||
|
||||
var le = require('letsencrypt-express');
|
||||
var express = require('express');
|
||||
var app = express();
|
||||
|
||||
app.use('/', function (req, res) {
|
||||
res.send({ success: true });
|
||||
});
|
||||
|
||||
le.create('/etc/letsencrypt', app).listen([80], [443, 5001], function () {
|
||||
console.log("ENCRYPT **ALL** THE DOMAINS!");
|
||||
});
|
||||
```
|
||||
|
||||
### More Options Exposed
|
||||
|
||||
```javascript
|
||||
'use strict';
|
||||
|
||||
var le = require('letsencrypt-express');
|
||||
var express = require('express');
|
||||
var app = express();
|
||||
|
||||
app.use('/', function (req, res) {
|
||||
res.send({ success: true });
|
||||
});
|
||||
|
||||
var results = le.create({
|
||||
configDir: '/etc/letsencrypt'
|
||||
, onRequest: app
|
||||
}).listen(
|
||||
|
||||
// you can give just the port, or expand out to the full options
|
||||
[80, { port: 8080, address: 'localhost', onListening: function () { console.log('http://localhost'); } }]
|
||||
|
||||
// you can give just the port, or expand out to the full options
|
||||
, [443, 5001, { port: 8443, address: 'localhost' }]
|
||||
|
||||
// this is pretty much the default onListening handler
|
||||
, function onListening() {
|
||||
var server = this;
|
||||
var protocol = ('requestCert' in server) ? 'https': 'http';
|
||||
console.log("Listening at " + protocol + '://localhost:' + this.address().port);
|
||||
}
|
||||
);
|
||||
|
||||
// In case you need access to the raw servers (i.e. using websockets)
|
||||
console.log(results.plainServers);
|
||||
console.log(results.tlsServers);
|
||||
```
|
||||
|
||||
### WebSockets with Let's Encrypt
|
||||
|
||||
Note: you don't need to create websockets for the plain ports.
|
||||
|
||||
```
|
||||
results.tlsServers.forEach(function (server) {
|
||||
});
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
If any of these values are `undefined` or `null` the will assume use reasonable defaults.
|
||||
|
@ -18,6 +91,9 @@ Partially defined values will be merged with the defaults.
|
|||
Setting the value to `false` will, in many cases (as documented), disable the defaults.
|
||||
|
||||
```
|
||||
configDir: string //
|
||||
|
||||
|
||||
webrootPath: string // string a path to a folder where temporary challenge files will be stored and read
|
||||
// default os.tmpdir() + path.sep + 'acme-challenge'
|
||||
|
||||
|
@ -45,4 +121,15 @@ httpsOptions: object // object will be merged with internal defau
|
|||
|
||||
|
||||
sniCallback: func // func replace the default sniCallback handler (which manages certificates) with your own
|
||||
|
||||
|
||||
letsencrypt: object // object configure the letsencrypt object yourself and pass it in directly
|
||||
//
|
||||
// default we create the letsencrypt object using parameters you specify
|
||||
```
|
||||
|
||||
## Heroku?
|
||||
|
||||
This doesn't work on heroku because heroku uses a proxy with built-in https
|
||||
(which is a smart thing to do) and besides, they want you to pay big bucks
|
||||
for https. (hopefully not for long?...)
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
'use strict';
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
// TODO handle templating :hostname in letsencrypt proper
|
||||
|
||||
// Note: we're explicitly doing this on the filesystem
|
||||
// rather than in-memory to support node cluster
|
||||
|
||||
module.exports = {
|
||||
set: function setChallenge(args, hostname, key, value, cb) {
|
||||
var keyfile = path.join((args.webrootPath || args.webrootTpl).replace(':hostname', hostname), key);
|
||||
|
||||
fs.writeFile(keyfile, value, 'utf8', cb);
|
||||
}
|
||||
|
||||
, get: function getChallenge(args, hostname, key, cb) {
|
||||
var keyfile = path.join((args.webrootPath || args.webrootTpl).replace(':hostname', hostname), key);
|
||||
|
||||
fs.readFile(keyfile, 'utf8', cb);
|
||||
}
|
||||
|
||||
, remove: function removeChallenge(args, hostname, key, cb) {
|
||||
var keyfile = path.join((args.webrootPath || args.webrootTpl).replace(':hostname', hostname), key);
|
||||
|
||||
// Note: it's not actually terribly important that we wait for the unlink callback
|
||||
// but it's a polite thing to do - and we're polite people!
|
||||
fs.unlink(keyfile, cb);
|
||||
}
|
||||
};
|
|
@ -1,22 +1,10 @@
|
|||
'use strict';
|
||||
|
||||
var path = require('path');
|
||||
var challengeStore = require('./lib/challange-handlers');
|
||||
|
||||
function getChallenge(args, hostname, key, cb) {
|
||||
var fs = require('fs');
|
||||
var keyfile = path.join((args.webrootPath || args.webrootTpl).replace(':hostname', hostname), key);
|
||||
|
||||
fs.readFile(keyfile, 'utf8', function (err, text) {
|
||||
if (err) {
|
||||
cb(err);
|
||||
return;
|
||||
}
|
||||
|
||||
cb(null, text);
|
||||
});
|
||||
}
|
||||
|
||||
function create(obj) {
|
||||
function create(obj, app) {
|
||||
var LE = require('letsencrypt');
|
||||
var https = require('https');
|
||||
var http = require('http');
|
||||
|
||||
|
@ -26,12 +14,23 @@ function create(obj) {
|
|||
if (!obj) {
|
||||
obj = {};
|
||||
}
|
||||
else if ('function' === typeof obj) {
|
||||
|
||||
if ('string' === typeof obj) {
|
||||
obj = {
|
||||
configDir: obj
|
||||
};
|
||||
}
|
||||
|
||||
if ('function' === typeof obj) {
|
||||
obj = {
|
||||
onRequest: obj
|
||||
};
|
||||
}
|
||||
|
||||
if ('function' === typeof app) {
|
||||
obj.onRequest = obj.onRequest || app;
|
||||
}
|
||||
|
||||
if (!obj.getChallenge) {
|
||||
if (false !== obj.getChallenge) {
|
||||
obj.getChallenge = getChallenge;
|
||||
|
@ -41,11 +40,18 @@ function create(obj) {
|
|||
}
|
||||
}
|
||||
|
||||
if (!obj.onRequest) {
|
||||
console.warn("You did not specify args.onRequest, using 'Hello, World!'");
|
||||
obj.onRequest = function (req, res) {
|
||||
res.end('Hello, World!');
|
||||
};
|
||||
if (!obj.onRequest && false !== obj.onRequest) {
|
||||
console.warn("You should either do args.onRequest = app or server.on('request', app),"
|
||||
+ " otherwise only acme-challenge requests will be handled (and the rest will hang)");
|
||||
console.warn("You can silence this warning by setting args.onRequest = false");
|
||||
}
|
||||
|
||||
if (!obj.letsencrypt) {
|
||||
//LE.merge(obj, );
|
||||
obj.letsencrypt = LE.create(obj, {
|
||||
setChallenge: setChallenge
|
||||
, removeChallenge: removeChallenge
|
||||
});
|
||||
}
|
||||
|
||||
function acmeResponder(req, res) {
|
||||
|
@ -142,7 +148,7 @@ function create(obj) {
|
|||
|
||||
// deleting creates a "slow object", but that's okay (we only use it once)
|
||||
return results;
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
listen: listen
|
||||
|
@ -151,4 +157,6 @@ function create(obj) {
|
|||
|
||||
module.exports = create;
|
||||
module.exports.create = create;
|
||||
module.exports.getChallenge = getChallenge;
|
||||
module.exports.setChallenge = challengeStore.set;
|
||||
module.exports.getChallenge = challengeStore.get;
|
||||
module.exports.removeChallenge = challengeStore.remove;
|
||||
|
|
Loading…
Reference in New Issue