163 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			163 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 'use strict';
 | |
| 
 | |
| var path = require('path');
 | |
| var challengeStore = require('./lib/challange-handlers');
 | |
| 
 | |
| function create(obj, app) {
 | |
|   var LE = require('letsencrypt');
 | |
|   var https = require('https');
 | |
|   var http = require('http');
 | |
| 
 | |
|   var httpsOptions = obj.httpsOptions || {};
 | |
|   var defaultPems = require('localhost.daplie.com-certificates');
 | |
| 
 | |
|   if (!obj) {
 | |
|     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;
 | |
|     }
 | |
|     if (!obj.webrootPath) {
 | |
|       obj.webrootPath = path.join(require('os').tmpdir(), 'acme-challenge');
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   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) {
 | |
|     var acmeChallengePrefix = '/.well-known/acme-challenge/';
 | |
| 
 | |
|     if (0 !== req.url.indexOf(acmeChallengePrefix)) {
 | |
|       obj.onRequest(req, res);
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|     var key = req.url.slice(acmeChallengePrefix.length);
 | |
| 
 | |
|     obj.getChallenge(obj, req.headers.host, key, function (err, val) {
 | |
|       res.end(val || '_');
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   // https://nodejs.org/api/https.html
 | |
|   // pfx, key, cert, passphrase, ca, ciphers, rejectUnauthorized, secureProtocol
 | |
|   if (!httpsOptions.pfx) {
 | |
|     if (!(httpsOptions.cert || httpsOptions.key)) {
 | |
|       httpsOptions.key = defaultPems.key;
 | |
|       httpsOptions.cert = defaultPems.cert;
 | |
|     }
 | |
|     else if (!(httpsOptions.cert && httpsOptions.key)) {
 | |
|       if (!httpsOptions.cert) {
 | |
|         console.warn("You specified httpsOptions.cert, but not httpsOptions.key");
 | |
|       }
 | |
|       if (!httpsOptions.key) {
 | |
|         console.warn("You specified httpsOptions.key, but not httpsOptions.cert");
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   function listen(plainPorts, tlsPorts, onListening) {
 | |
|     var results = {
 | |
|       plainServers: []
 | |
|     , tlsServers: []
 | |
|     };
 | |
| 
 | |
|     plainPorts = plainPorts || [80];
 | |
|     tlsPorts = tlsPorts || [443, 5001];
 | |
| 
 | |
|     function defaultOnListening() {
 | |
|       /*jshint validthis: true*/
 | |
|       var server = this;
 | |
|       var protocol = ('honorCipherOrder' in server || 'rejectUnauthorized' in server) ? 'https': 'http';
 | |
|       var addr = server.address();
 | |
|       var port;
 | |
| 
 | |
|       if (80 === addr.port || 443 === addr.port) {
 | |
|         port = '';
 | |
|       } else {
 | |
|         port = ':' + addr.port;
 | |
|       }
 | |
|       console.info('Listening ' + protocol + '://' + addr.address + port + '/');
 | |
|     }
 | |
| 
 | |
|     console.log(plainPorts);
 | |
|     plainPorts.forEach(function (addr) {
 | |
|       var port = addr.port || addr;
 | |
|       var address = addr.address || '';
 | |
|       var server = http.createServer(acmeResponder);
 | |
| 
 | |
|       server.__le_onListening = addr.onListen;
 | |
|       server.__le_port = port;
 | |
|       server.__le_address = address;
 | |
| 
 | |
|       results.plainServers.push(server);
 | |
|     });
 | |
| 
 | |
|     tlsPorts.forEach(function (addr) {
 | |
|       var port = addr.port || addr;
 | |
|       var address = addr.address || '';
 | |
|       var options = addr.httpsOptions || httpsOptions;
 | |
|       var server = https.createServer(options, acmeResponder);
 | |
| 
 | |
|       server.__le_onListen = addr.onListen;
 | |
|       server.__le_port = port;
 | |
|       server.__le_address = address;
 | |
| 
 | |
|       results.tlsServers.push(server);
 | |
|     });
 | |
| 
 | |
|     results.plainServers.forEach(function (server) {
 | |
|       var listen = server.__le_onListening || onListening || defaultOnListening;
 | |
|       server.listen(server.__le_port, server.__le_address, listen);
 | |
|     });
 | |
| 
 | |
|     results.tlsServers.forEach(function (server) {
 | |
|       var listen = server.__le_onListening || onListening || defaultOnListening;
 | |
|       server.listen(server.__le_port, server.__le_address, listen);
 | |
|     });
 | |
| 
 | |
|     // deleting creates a "slow object", but that's okay (we only use it once)
 | |
|     return results;
 | |
|   }
 | |
| 
 | |
|   return {
 | |
|     listen: listen
 | |
|   };
 | |
| }
 | |
| 
 | |
| module.exports = create;
 | |
| module.exports.create = create;
 | |
| module.exports.setChallenge = challengeStore.set;
 | |
| module.exports.getChallenge = challengeStore.get;
 | |
| module.exports.removeChallenge = challengeStore.remove;
 |