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?...) | ||||
|  | ||||
							
								
								
									
										31
									
								
								lib/challenge-handlers.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								lib/challenge-handlers.js
									
									
									
									
									
										Normal file
									
								
							| @ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user