From 42ab9db59d1e4128672ff82ccf72b6c5d0b2b4da Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 24 Jun 2015 14:38:30 -0600 Subject: [PATCH 001/129] Initial commit --- .gitignore | 27 +++++++ LICENSE | 202 +++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 2 + 3 files changed, 231 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..123ae94 --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +# Logs +logs +*.log + +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directory +# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git +node_modules diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8f71f43 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/README.md b/README.md new file mode 100644 index 0000000..2dd48e2 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# localhost.daplie.com-server +Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development. From 11555ba76189b2306bb6993eaae87df055d405e0 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 24 Jun 2015 15:36:17 -0600 Subject: [PATCH 002/129] initial commit --- app.js | 17 +++++++++++++++++ package.json | 44 ++++++++++++++++++++++++++++++++++++++++++++ serve.js | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 app.js create mode 100644 package.json create mode 100644 serve.js diff --git a/app.js b/app.js new file mode 100644 index 0000000..e6a9f8d --- /dev/null +++ b/app.js @@ -0,0 +1,17 @@ +'use strict'; + +module.exports = function (opts) { + var finalhandler = require('finalhandler'); + var serveStatic = require('serve-static'); + var serveIndex = require('serve-index'); + var serve = serveStatic(opts.public); + var index = serveIndex(opts.public); + + return function (req, res) { + var done = finalhandler(req, res); + serve(req, res, function (err) { + if (err) { return done(err); } + index(req, res, done); + }); + }; +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..8991288 --- /dev/null +++ b/package.json @@ -0,0 +1,44 @@ +{ + "name": "https-server", + "version": "1.0.0", + "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", + "main": "serve.js", + "scripts": { + "test": "node serve.js -p 1443 -d /tmp/" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Daplie/localhost.daplie.com-server.git" + }, + "keywords": [ + "https", + "local", + "localhost", + "development", + "dev", + "tls", + "ssl", + "cert", + "certs", + "certificate", + "certificates", + "http", + "express", + "connect", + "serve", + "server" + ], + "author": "AJ ONeal (http://coolaj86.com/)", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/Daplie/localhost.daplie.com-server/issues" + }, + "homepage": "https://github.com/Daplie/localhost.daplie.com-server#readme", + "dependencies": { + "finalhandler": "^0.4.0", + "localhost.daplie.com-certificates": "^1.0.0", + "minimist": "^1.1.1", + "serve-index": "^1.7.0", + "serve-static": "^1.10.0" + } +} diff --git a/serve.js b/serve.js new file mode 100644 index 0000000..dcf5c95 --- /dev/null +++ b/serve.js @@ -0,0 +1,47 @@ +'use strict'; + +var https = require('https'); +var path = require('path'); + +function createServer(port, pubdir) { + var server = https.createServer(require('localhost.daplie.com-certificates')); + var app = require('./app'); + + server.on('error', function (err) { + console.error(err); + process.exit(1); + }); + + server.listen(port, function () { + var msg = 'Serving ' + pubdir + ' at https://localhost.daplie.com'; + var p = server.address().port; + if (443 !== p) { + msg += ':' + p; + } + console.log(msg); + }); + + if ('function' === typeof app) { + app = app({ public: pubdir }); + } else if ('function' === typeof app.create) { + app = app.create({ public: pubdir }); + } + + Promise.resolve(app).then(function (app) { + server.on('request', app); + }); +} + +module.exports.createServer = createServer; + +function run() { + var minimist = require('minimist'); + var argv = minimist(process.argv.slice(2)); + var port = argv.p || argv._[0] || 1443; + var pubdir = path.resolve(argv.d || argv._[1] || process.cwd()); + createServer(port, pubdir); +} + +if (require.main === module) { + run(); +} From ee087c3231f3949bc9bfd1f549340086f36b7faf Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 24 Jun 2015 15:38:20 -0600 Subject: [PATCH 003/129] change name on npm --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8991288..540a597 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "https-server", + "name": "serve-https", "version": "1.0.0", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "serve.js", From 98f710dcfebc34585b225f8240342e4f64358015 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 24 Jun 2015 15:44:42 -0600 Subject: [PATCH 004/129] ready for npm --- README.md | 18 ++++++++++++++++++ package.json | 3 +++ serve.js | 1 + 3 files changed, 22 insertions(+) mode change 100644 => 100755 serve.js diff --git a/README.md b/README.md index 2dd48e2..b3a192a 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,20 @@ # localhost.daplie.com-server Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development. + +Install +------- + +```bash +npm install --global serve-https +serve-https +``` + +``` +Serving /Users/foo/ at https://localhost.daplie.com:1443 +``` + +Usage +----- + +* `-p ` - i.e. `sudo serve-https -p 443` +* `-d ` - i.e. `serve-https -d /tmp/` diff --git a/package.json b/package.json index 540a597..81d5cad 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,9 @@ "scripts": { "test": "node serve.js -p 1443 -d /tmp/" }, + "bin": { + "serve-https": "serve.js" + }, "repository": { "type": "git", "url": "git+https://github.com/Daplie/localhost.daplie.com-server.git" diff --git a/serve.js b/serve.js old mode 100644 new mode 100755 index dcf5c95..98e9f64 --- a/serve.js +++ b/serve.js @@ -1,3 +1,4 @@ +#!/bin/bash 'use strict'; var https = require('https'); From bee8267743bf6ff056cecfbf09b4a8538f54fb84 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 24 Jun 2015 15:45:54 -0600 Subject: [PATCH 005/129] bash -> node, duh --- serve.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/serve.js b/serve.js index 98e9f64..6a93434 100755 --- a/serve.js +++ b/serve.js @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env node 'use strict'; var https = require('https'); From d7b9cf55da1c1b65c358778c01e5c13d16ff09d6 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 24 Jun 2015 15:46:00 -0600 Subject: [PATCH 006/129] bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 81d5cad..ad3ea32 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "1.0.0", + "version": "1.0.1", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "serve.js", "scripts": { From 85a32486e127e1c9a38e736ea34015e524451041 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Tue, 30 Jun 2015 17:11:01 -0600 Subject: [PATCH 007/129] add ability to specify content for / --- README.md | 23 ++++++++++++++++++++++- app.js | 6 ++++++ serve.js | 15 +++++++++------ 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index b3a192a..7642e15 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ -# localhost.daplie.com-server +localhost.daplie.com-server +=========================== + Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development. Install @@ -18,3 +20,22 @@ Usage * `-p ` - i.e. `sudo serve-https -p 443` * `-d ` - i.e. `serve-https -d /tmp/` +* `-c ` - i.e. `server-https -c 'Hello, World!'` + +Examples +-------- + +```bash +serve-https -p 1443 -c 'Hello from 1443' & +serve-https -p 2443 -c 'Hello from 2443' & +serve-https -p 3443 -d /tmp & + +curl https://localhost.daplie.com:1443 +> Hello from 1443 + +curl --insecure https://localhost:2443 +> Hello from 2443 + +curl https://localhost.daplie.com:3443 +> [html index listing of /tmp] +``` diff --git a/app.js b/app.js index e6a9f8d..ed7ca78 100644 --- a/app.js +++ b/app.js @@ -6,8 +6,14 @@ module.exports = function (opts) { var serveIndex = require('serve-index'); var serve = serveStatic(opts.public); var index = serveIndex(opts.public); + var content = opts.content; return function (req, res) { + if (content && '/' === req.url) { + // res.setHeader('Content-Type', 'application/octet-stream'); + res.end(content); + return; + } var done = finalhandler(req, res); serve(req, res, function (err) { if (err) { return done(err); } diff --git a/serve.js b/serve.js index 6a93434..34ab234 100755 --- a/serve.js +++ b/serve.js @@ -4,9 +4,11 @@ var https = require('https'); var path = require('path'); -function createServer(port, pubdir) { - var server = https.createServer(require('localhost.daplie.com-certificates')); +function createServer(port, pubdir, content) { + var options = require('localhost.daplie.com-certificates'); + var server = https.createServer(options); var app = require('./app'); + var directive = { public: pubdir, content: content }; server.on('error', function (err) { console.error(err); @@ -19,13 +21,13 @@ function createServer(port, pubdir) { if (443 !== p) { msg += ':' + p; } - console.log(msg); + console.info(msg); }); if ('function' === typeof app) { - app = app({ public: pubdir }); + app = app(directive); } else if ('function' === typeof app.create) { - app = app.create({ public: pubdir }); + app = app.create(directive); } Promise.resolve(app).then(function (app) { @@ -40,7 +42,8 @@ function run() { var argv = minimist(process.argv.slice(2)); var port = argv.p || argv._[0] || 1443; var pubdir = path.resolve(argv.d || argv._[1] || process.cwd()); - createServer(port, pubdir); + var content = argv.c; + createServer(port, pubdir, content); } if (require.main === module) { From 441bef5eea4074c276614c1d32ba760947c146eb Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Tue, 30 Jun 2015 17:11:31 -0600 Subject: [PATCH 008/129] v1.1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ad3ea32..491d9b4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "1.0.1", + "version": "1.1.0", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "serve.js", "scripts": { From 356b342f3850ce3e71131fecf51b6f3d7924fd35 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Tue, 30 Jun 2015 17:18:14 -0600 Subject: [PATCH 009/129] update certificates --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 491d9b4..f4d988b 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "homepage": "https://github.com/Daplie/localhost.daplie.com-server#readme", "dependencies": { "finalhandler": "^0.4.0", - "localhost.daplie.com-certificates": "^1.0.0", + "localhost.daplie.com-certificates": "^1.0.1", "minimist": "^1.1.1", "serve-index": "^1.7.0", "serve-static": "^1.10.0" From ab9ab7ab5e848b0aa6b67fb4c0d161f47bb43af7 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Tue, 30 Jun 2015 17:18:16 -0600 Subject: [PATCH 010/129] v1.1.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f4d988b..68c170e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "1.1.0", + "version": "1.1.1", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "serve.js", "scripts": { From bfffe21297c87dba7402b8cd0ceb8030b7bf8dbf Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Mon, 6 Jul 2015 12:26:11 -0600 Subject: [PATCH 011/129] bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 68c170e..380d271 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "homepage": "https://github.com/Daplie/localhost.daplie.com-server#readme", "dependencies": { "finalhandler": "^0.4.0", - "localhost.daplie.com-certificates": "^1.0.1", + "localhost.daplie.com-certificates": "^1.0.2", "minimist": "^1.1.1", "serve-index": "^1.7.0", "serve-static": "^1.10.0" From c947d2c9e1ae64a751fe0f8011c72d0fe9a5a6fe Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Mon, 6 Jul 2015 12:26:13 -0600 Subject: [PATCH 012/129] v1.1.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 380d271..f62de52 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "1.1.1", + "version": "1.1.2", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "serve.js", "scripts": { From f068d84490e15ea661346b1200162adbf979065c Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 8 Jul 2015 00:43:46 -0600 Subject: [PATCH 013/129] custom https certs, http-to-https redirects --- README.md | 49 +++++++++++++++++++++++++++---- package.json | 1 + serve.js | 81 +++++++++++++++++++++++++++++++++++++++++++++++---- test-chain.sh | 18 ++++++++++++ 4 files changed, 138 insertions(+), 11 deletions(-) create mode 100755 test-chain.sh diff --git a/README.md b/README.md index 7642e15..f91b492 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,11 @@ -localhost.daplie.com-server -=========================== +serve-https +=========== -Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development. +Serves HTTPS using TLS (SSL) certs. + +Bundles a valid certificate for localhost.daplie.com - great for testing and development. + +Also great for testing ACME certs from letsencrypt.org. Install ------- @@ -20,7 +24,16 @@ Usage * `-p ` - i.e. `sudo serve-https -p 443` * `-d ` - i.e. `serve-https -d /tmp/` -* `-c ` - i.e. `server-https -c 'Hello, World!'` +* `-c ` - i.e. `server-https -c 'Hello, World! '` +* `--insecure-port ` - run an http server that redirects to https + +Specifying a custom HTTPS certificate: + +* `--key /path/to/privkey.pem` +* `--cert /path/to/cert.pem` +* `--chain /path/to/chain.pem` + +Note: you may specify a file containing all certificate authorities or use even `--chain` multiple times such as `--chain /path/to/intermediate-ca-1.pem --chain /path/to/intermediate-ca-2.pem` Examples -------- @@ -28,7 +41,7 @@ Examples ```bash serve-https -p 1443 -c 'Hello from 1443' & serve-https -p 2443 -c 'Hello from 2443' & -serve-https -p 3443 -d /tmp & +serve-https -p 3443 -d /tmp --insecure-port 4080 & curl https://localhost.daplie.com:1443 > Hello from 1443 @@ -39,3 +52,29 @@ curl --insecure https://localhost:2443 curl https://localhost.daplie.com:3443 > [html index listing of /tmp] ``` + +And if you tested in a browser, +it would redirect to . + +(in curl it would just show an error message) + +### Testing ACME Let's Encrypt certs + +You can get free https certificates from letsencrypt.org (ACME letsencrypt) +and even a free domain from https://freedns.afraid.org. + +```bash +serve-https -p 8443 \ + --key /etc/letsencrypt/live/test.mooo.com/privkey.pem \ + --cert /etc/letsencrypt/live/test.mooo.com/cert.pem \ + --chain /etc/letsencrypt/live/test.mooo.com/chain.pem \ + -c "$(cat '/etc/letsencrypt/live/test.mooo.com/chain.pem')" +``` + +```bash +curl --insecure https://test.mooo.com:8443 > ./chain.pem +curl https://test.mooo.com:8843 --cacert ./chain.pem +``` + +* [QuickStart Guide for Let's Encrypt](https://coolaj86.com/articles/lets-encrypt-on-raspberry-pi/) +* [QuickStart Guide for FreeDNS](https://coolaj86.com/articles/free-dns-hosting-with-freedns-afraid-org.html) diff --git a/package.json b/package.json index f62de52..d8a2d47 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "finalhandler": "^0.4.0", "localhost.daplie.com-certificates": "^1.0.2", "minimist": "^1.1.1", + "redirect-https": "^1.1.0", "serve-index": "^1.7.0", "serve-static": "^1.10.0" } diff --git a/serve.js b/serve.js index 34ab234..addebc5 100755 --- a/serve.js +++ b/serve.js @@ -2,21 +2,48 @@ 'use strict'; var https = require('https'); +var http = require('http'); +var fs = require('fs'); var path = require('path'); -function createServer(port, pubdir, content) { - var options = require('localhost.daplie.com-certificates'); - var server = https.createServer(options); +function createInsecureServer(port, pubdir, opts) { + var server = http.createServer(); + + server.on('error', function (err) { + console.error(err); + process.exit(1); + }); + + server.on('request', require('redirect-https')({ + port: port + })); + + server.listen(opts.insecurePort, function () { + var msg = 'Serving ' + pubdir + ' at http://' + opts.servername; + var p = server.address().port; + if (80 !== p) { + msg += ':' + p; + } + console.info(msg); + }); +} + +function createServer(port, pubdir, content, opts) { + var server = https.createServer(opts); var app = require('./app'); var directive = { public: pubdir, content: content }; + if (opts.insecurePort) { + createInsecureServer(port, pubdir, opts); + } + server.on('error', function (err) { console.error(err); process.exit(1); }); server.listen(port, function () { - var msg = 'Serving ' + pubdir + ' at https://localhost.daplie.com'; + var msg = 'Serving ' + pubdir + ' at https://' + opts.servername; var p = server.address().port; if (443 !== p) { msg += ':' + p; @@ -40,10 +67,52 @@ module.exports.createServer = createServer; function run() { var minimist = require('minimist'); var argv = minimist(process.argv.slice(2)); - var port = argv.p || argv._[0] || 1443; + var port = argv.p || argv.port || argv._[0] || 1443; var pubdir = path.resolve(argv.d || argv._[1] || process.cwd()); var content = argv.c; - createServer(port, pubdir, content); + + var cert = require('localhost.daplie.com-certificates'); + var opts = { + key: cert.key + , cert: cert.cert + , ca: cert.ca + , SNICallback: function (servername, cb) { + cb(null, require('tls').createSecureContext(opts)); + return; + } + }; + + if (argv.key || argv.cert || argv.chain) { + if (!argv.key || !argv.cert || !argv.chain) { + console.error("You must specify each of --key --cert and --chain (chain may be empty)"); + return; + } + + if (!Array.isArray(argv.chain)) { + argv.chain = [argv.chain]; + } + + opts.key = fs.readFileSync(argv.key); + opts.cert = fs.readFileSync(argv.cert); + // turn multiple-cert pemfile into array of cert strings + opts.ca = argv.chain.reduce(function (chain, fullpath) { + return chain.concat(fs.readFileSync(fullpath, 'ascii') + .split('-----END CERTIFICATE-----') + .filter(function (ca) { + return ca.trim(); + }).map(function (ca) { + return (ca + '-----END CERTIFICATE-----').trim(); + })); + }, []); + } + + opts.servername = 'localhost.daplie.com'; + if (argv.servername) { + opts.servername = argv.servername; + } + opts.insecurePort = argv.i || argv['insecure-port']; + + createServer(port, pubdir, content, opts); } if (require.main === module) { diff --git a/test-chain.sh b/test-chain.sh new file mode 100755 index 0000000..a5fb322 --- /dev/null +++ b/test-chain.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +node serve.js \ + --port 8443 \ + --key node_modules/localhost.daplie.com-certificates/certs/server/my-server.key.pem \ + --cert node_modules/localhost.daplie.com-certificates/certs/server/my-server.crt.pem \ + --chain node_modules/localhost.daplie.com-certificates/certs/ca/intermediate.crt.pem \ + --chain node_modules/localhost.daplie.com-certificates/certs/ca/root.crt.pem \ + -c "$(cat node_modules/localhost.daplie.com-certificates/certs/ca/root.crt.pem)" & + +PID=$! + +sleep 1 +curl -s --insecure http://localhost.daplie.com:8443 > ./root.pem +curl -s https://localhost.daplie.com:8443 --cacert ./root.pem + +rm ./root.pem +kill $PID 2>/dev/null From e0655c3f0d15c733ffad1c15a8fc3d6666f021d9 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 8 Jul 2015 00:45:40 -0600 Subject: [PATCH 014/129] update defaults, https now on 8443 --- README.md | 10 +++++----- serve.js | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index f91b492..114e4c5 100644 --- a/README.md +++ b/README.md @@ -16,16 +16,16 @@ serve-https ``` ``` -Serving /Users/foo/ at https://localhost.daplie.com:1443 +Serving /Users/foo/ at https://localhost.daplie.com:8443 ``` Usage ----- -* `-p ` - i.e. `sudo serve-https -p 443` -* `-d ` - i.e. `serve-https -d /tmp/` -* `-c ` - i.e. `server-https -c 'Hello, World! '` -* `--insecure-port ` - run an http server that redirects to https +* `-p ` - i.e. `sudo serve-https -p 443` (defaults to 8443) +* `-d ` - i.e. `serve-https -d /tmp/` (defaults to `pwd`) +* `-c ` - i.e. `server-https -c 'Hello, World! '` (defaults to directory index) +* `--insecure-port ` - run an http server that redirects to https (off by default) Specifying a custom HTTPS certificate: diff --git a/serve.js b/serve.js index addebc5..2f48470 100755 --- a/serve.js +++ b/serve.js @@ -67,7 +67,7 @@ module.exports.createServer = createServer; function run() { var minimist = require('minimist'); var argv = minimist(process.argv.slice(2)); - var port = argv.p || argv.port || argv._[0] || 1443; + var port = argv.p || argv.port || argv._[0] || 8443; var pubdir = path.resolve(argv.d || argv._[1] || process.cwd()); var content = argv.c; From c731e04f127b3957943a105e3927799fd49a3d4a Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 8 Jul 2015 00:45:48 -0600 Subject: [PATCH 015/129] v1.2.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d8a2d47..e36464e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "1.1.2", + "version": "1.2.0", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "serve.js", "scripts": { From 5af528785dc7eec7ac36b94ee4afb9d50107549f Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 8 Jul 2015 00:48:18 -0600 Subject: [PATCH 016/129] add link --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 114e4c5..3abb288 100644 --- a/README.md +++ b/README.md @@ -60,8 +60,9 @@ it would redirect to . ### Testing ACME Let's Encrypt certs -You can get free https certificates from letsencrypt.org (ACME letsencrypt) -and even a free domain from https://freedns.afraid.org. +You can get free https certificates from [letsencrypt.org](https://letsencrypt.org) +(ACME letsencrypt) +and even a free subdomain from . ```bash serve-https -p 8443 \ From c92c02dd88d89f11196b9fcd897c3cc2b76e5895 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 8 Jul 2015 00:51:38 -0600 Subject: [PATCH 017/129] clarify --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3abb288..45d7d00 100644 --- a/README.md +++ b/README.md @@ -60,10 +60,14 @@ it would redirect to . ### Testing ACME Let's Encrypt certs -You can get free https certificates from [letsencrypt.org](https://letsencrypt.org) +In case you didn't know, you can get free https certificates from +[letsencrypt.org](https://letsencrypt.org) (ACME letsencrypt) and even a free subdomain from . +If you want to quickly test the certificates you installed, +you can do so like this: + ```bash serve-https -p 8443 \ --key /etc/letsencrypt/live/test.mooo.com/privkey.pem \ From 0912135e5724a1848fde8b736631c9154547d73e Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 8 Jul 2015 01:27:14 -0600 Subject: [PATCH 018/129] add alias --letsencrypt-certs and option --serve-chain --- README.md | 15 +++++++++++++-- serve.js | 14 +++++++++++++- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 45d7d00..fe6f16d 100644 --- a/README.md +++ b/README.md @@ -69,13 +69,24 @@ If you want to quickly test the certificates you installed, you can do so like this: ```bash -serve-https -p 8443 \ +sudo serve-https -p 8443 \ + --letsencrypt-certs test.mooo.com \ + --serve-chain true +``` + +which is equilavent to + +```bash +sudo serve-https -p 8443 \ + --servername test.mooo.com --key /etc/letsencrypt/live/test.mooo.com/privkey.pem \ --cert /etc/letsencrypt/live/test.mooo.com/cert.pem \ --chain /etc/letsencrypt/live/test.mooo.com/chain.pem \ - -c "$(cat '/etc/letsencrypt/live/test.mooo.com/chain.pem')" + -c "$(cat 'sudo /etc/letsencrypt/live/test.mooo.com/chain.pem')" ``` +and can be tested like so + ```bash curl --insecure https://test.mooo.com:8443 > ./chain.pem curl https://test.mooo.com:8843 --cacert ./chain.pem diff --git a/serve.js b/serve.js index 2f48470..a1f2d42 100755 --- a/serve.js +++ b/serve.js @@ -70,6 +70,7 @@ function run() { var port = argv.p || argv.port || argv._[0] || 8443; var pubdir = path.resolve(argv.d || argv._[1] || process.cwd()); var content = argv.c; + var letsencryptHost = argv['letsencrypt-certs']; var cert = require('localhost.daplie.com-certificates'); var opts = { @@ -82,7 +83,14 @@ function run() { } }; - if (argv.key || argv.cert || argv.chain) { + if (letsencryptHost) { + argv.key = argv.key || '/etc/letsencrypt/live/' + letsencryptHost + '/privkey.pem'; + argv.cert = argv.cert || '/etc/letsencrypt/live/' + letsencryptHost + '/cert.pem'; + argv.chain = argv.chain || '/etc/letsencrypt/live/' + letsencryptHost + '/chain.pem'; + argv.servername = argv.servername || letsencryptHost; + } + + if (argv.key || argv.cert || argv.chain || argv['serve-chain']) { if (!argv.key || !argv.cert || !argv.chain) { console.error("You must specify each of --key --cert and --chain (chain may be empty)"); return; @@ -104,6 +112,10 @@ function run() { return (ca + '-----END CERTIFICATE-----').trim(); })); }, []); + + if (argv['serve-chain']) { + content = opts.ca.join('\r\n'); + } } opts.servername = 'localhost.daplie.com'; From 2055d4d67c8cc37ad83a66f5e322f3006a3d3092 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 8 Jul 2015 01:27:22 -0600 Subject: [PATCH 019/129] v1.3.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e36464e..2bbd09d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "1.2.0", + "version": "1.3.0", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "serve.js", "scripts": { From 8faf846f6d018810fb64499bf3547edcc0f62d29 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 8 Jul 2015 01:46:01 -0600 Subject: [PATCH 020/129] doc updates --- README.md | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index fe6f16d..acf5497 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,10 @@ serve-https =========== -Serves HTTPS using TLS (SSL) certs. +A simple HTTPS static file server with valid TLS (SSL) certs. -Bundles a valid certificate for localhost.daplie.com - great for testing and development. +Comes bundled a valid certificate for localhost.daplie.com, +which is great for testing and development, and you can specify your own. Also great for testing ACME certs from letsencrypt.org. @@ -29,11 +30,21 @@ Usage Specifying a custom HTTPS certificate: -* `--key /path/to/privkey.pem` -* `--cert /path/to/cert.pem` -* `--chain /path/to/chain.pem` +* `--key /path/to/privkey.pem` specifies the server private key +* `--cert /path/to/cert.pem` specifies the server certificate +* `--chain /path/to/chain.pem` specifies the certificate authorities -Note: you may specify a file containing all certificate authorities or use even `--chain` multiple times such as `--chain /path/to/intermediate-ca-1.pem --chain /path/to/intermediate-ca-2.pem` +Note: `--chain` may specify single cert, a bundle, and may be used multiple times like so: + +``` +--chain /path/to/intermediate-ca-1.pem --chain /path/to/intermediate-ca-2.pem +``` + +Other options: + +* `--serve-chain true` alias for `-c` with the contents of chain.pem +* `--servername example.com` changes the servername logged to the console +* `--letsencrypt-certs example.com` sets and key, cert, and chain to standard letsencrypt locations Examples -------- From eaf0e60b12420a357430270f6a961950ed6599b7 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 8 Jul 2015 01:46:06 -0600 Subject: [PATCH 021/129] v1.3.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2bbd09d..952bfa1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "1.3.0", + "version": "1.3.1", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "serve.js", "scripts": { From 7dbe9bd6053870ffaf12e462907b50dc926f413c Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Mon, 13 Jul 2015 17:46:44 -0600 Subject: [PATCH 022/129] update letsencrypt conventions --- README.md | 24 ++++++++++++------------ package.json | 2 +- serve.js | 41 ++++++++++++++++++++++++++++++----------- 3 files changed, 43 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index acf5497..d274f2e 100644 --- a/README.md +++ b/README.md @@ -31,20 +31,20 @@ Usage Specifying a custom HTTPS certificate: * `--key /path/to/privkey.pem` specifies the server private key -* `--cert /path/to/cert.pem` specifies the server certificate -* `--chain /path/to/chain.pem` specifies the certificate authorities +* `--cert /path/to/fullchain.pem` specifies the bundle of server certificate and all intermediate certificates +* `--root /path/to/root.pem` specifies the certificate authority(ies) -Note: `--chain` may specify single cert, a bundle, and may be used multiple times like so: +Note: `--root` may specify single cert or a bundle, and may be used multiple times like so: ``` ---chain /path/to/intermediate-ca-1.pem --chain /path/to/intermediate-ca-2.pem +--root /path/to/primary-root.pem --root /path/to/cross-root.pem ``` Other options: -* `--serve-chain true` alias for `-c` with the contents of chain.pem +* `--serve-root true` alias for `-c` with the contents of root.pem * `--servername example.com` changes the servername logged to the console -* `--letsencrypt-certs example.com` sets and key, cert, and chain to standard letsencrypt locations +* `--letsencrypt-certs example.com` sets and key, fullchain, and root to standard letsencrypt locations Examples -------- @@ -82,7 +82,7 @@ you can do so like this: ```bash sudo serve-https -p 8443 \ --letsencrypt-certs test.mooo.com \ - --serve-chain true + --serve-root true ``` which is equilavent to @@ -91,16 +91,16 @@ which is equilavent to sudo serve-https -p 8443 \ --servername test.mooo.com --key /etc/letsencrypt/live/test.mooo.com/privkey.pem \ - --cert /etc/letsencrypt/live/test.mooo.com/cert.pem \ - --chain /etc/letsencrypt/live/test.mooo.com/chain.pem \ - -c "$(cat 'sudo /etc/letsencrypt/live/test.mooo.com/chain.pem')" + --cert /etc/letsencrypt/live/test.mooo.com/fullchain.pem \ + --root /etc/letsencrypt/live/test.mooo.com/root.pem \ + -c "$(cat 'sudo /etc/letsencrypt/live/test.mooo.com/root.pem')" ``` and can be tested like so ```bash -curl --insecure https://test.mooo.com:8443 > ./chain.pem -curl https://test.mooo.com:8843 --cacert ./chain.pem +curl --insecure https://test.mooo.com:8443 > ./root.pem +curl https://test.mooo.com:8843 --cacert ./root.pem ``` * [QuickStart Guide for Let's Encrypt](https://coolaj86.com/articles/lets-encrypt-on-raspberry-pi/) diff --git a/package.json b/package.json index 952bfa1..e78a57a 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "homepage": "https://github.com/Daplie/localhost.daplie.com-server#readme", "dependencies": { "finalhandler": "^0.4.0", - "localhost.daplie.com-certificates": "^1.0.2", + "localhost.daplie.com-certificates": "^1.1.2", "minimist": "^1.1.1", "redirect-https": "^1.1.0", "serve-index": "^1.7.0", diff --git a/serve.js b/serve.js index a1f2d42..7d258cb 100755 --- a/serve.js +++ b/serve.js @@ -76,35 +76,47 @@ function run() { var opts = { key: cert.key , cert: cert.cert - , ca: cert.ca + //, ca: cert.ca , SNICallback: function (servername, cb) { cb(null, require('tls').createSecureContext(opts)); return; } }; + var peerCa; if (letsencryptHost) { argv.key = argv.key || '/etc/letsencrypt/live/' + letsencryptHost + '/privkey.pem'; - argv.cert = argv.cert || '/etc/letsencrypt/live/' + letsencryptHost + '/cert.pem'; - argv.chain = argv.chain || '/etc/letsencrypt/live/' + letsencryptHost + '/chain.pem'; + argv.cert = argv.cert || '/etc/letsencrypt/live/' + letsencryptHost + '/fullchain.pem'; + argv.root = argv.root || argv.chain || '/etc/letsencrypt/live/' + letsencryptHost + '/root.pem'; argv.servername = argv.servername || letsencryptHost; + argv['serve-root'] = argv['serve-root'] || argv['serve-chain']; } - if (argv.key || argv.cert || argv.chain || argv['serve-chain']) { - if (!argv.key || !argv.cert || !argv.chain) { - console.error("You must specify each of --key --cert and --chain (chain may be empty)"); + if (argv['serve-root'] && !argv.root) { + console.error("You must specify bath --root to use --serve-root"); + return; + } + + if (argv.key || argv.cert || argv.root) { + if (!argv.key || !argv.cert) { + console.error("You must specify bath --key and --cert, and optionally --root (required with serve-root)"); return; } - if (!Array.isArray(argv.chain)) { - argv.chain = [argv.chain]; + if (!Array.isArray(argv.root)) { + argv.root = [argv.root]; } opts.key = fs.readFileSync(argv.key); opts.cert = fs.readFileSync(argv.cert); + // turn multiple-cert pemfile into array of cert strings - opts.ca = argv.chain.reduce(function (chain, fullpath) { - return chain.concat(fs.readFileSync(fullpath, 'ascii') + peerCa = argv.root.reduce(function (roots, fullpath) { + if (!fs.existsSync(fullpath)) { + return roots; + } + + return roots.concat(fs.readFileSync(fullpath, 'ascii') .split('-----END CERTIFICATE-----') .filter(function (ca) { return ca.trim(); @@ -113,9 +125,16 @@ function run() { })); }, []); - if (argv['serve-chain']) { + if (argv['serve-root']) { content = opts.ca.join('\r\n'); } + + // TODO * `--verify /path/to/root.pem` require peers to present certificates from said authority + if (argv.verify) { + opts.ca = peerCa; + opts.requestCert = true; + opts.rejectUnauthorized = true; + } } opts.servername = 'localhost.daplie.com'; From f344ee591d7e78c7d43ac837e5b15b7e142600d3 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Mon, 13 Jul 2015 18:04:12 -0600 Subject: [PATCH 023/129] v1.4.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e78a57a..fa1b4b2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "1.3.1", + "version": "1.4.0", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "serve.js", "scripts": { From 9a264c47714f225149fdeaeb07d9042ba3c8fc7b Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Sat, 5 Dec 2015 22:43:33 -0800 Subject: [PATCH 024/129] add livereload --- README.md | 1 + app.js | 34 ++++++++++++++++++++++++++++++++++ package.json | 1 + serve.js | 9 ++++++++- 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d274f2e..8d1c6b5 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ Usage * `-p ` - i.e. `sudo serve-https -p 443` (defaults to 8443) * `-d ` - i.e. `serve-https -d /tmp/` (defaults to `pwd`) * `-c ` - i.e. `server-https -c 'Hello, World! '` (defaults to directory index) +* `--livereload` - inject livereload into all html pages * `--insecure-port ` - run an http server that redirects to https (off by default) Specifying a custom HTTPS certificate: diff --git a/app.js b/app.js index ed7ca78..35ad727 100644 --- a/app.js +++ b/app.js @@ -15,6 +15,40 @@ module.exports = function (opts) { return; } var done = finalhandler(req, res); + var livereload = ''; + var addLen = 0; + + if (opts.livereload) { + livereload = ''; + addLen = livereload.length; + } + + res.__end = res.end; + res.__write = res.write; + res.write = function (data, enc, cb) { + if (this.headersSent) { + return; + } + + if (!/html/i.test(this.getHeader('Content-Type'))) { + this.__write(data, enc, cb); + return; + } + + if (this.getHeader('Content-Length')) { + this.setHeader('Content-Length', this.getHeader('Content-Length') + addLen); + } + + this.__write(livereload); + this.__write(data, enc, cb); + }; + res.end = function () { + + + res.__end(); + }; serve(req, res, function (err) { if (err) { return done(err); } index(req, res, done); diff --git a/package.json b/package.json index fa1b4b2..9006c03 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "homepage": "https://github.com/Daplie/localhost.daplie.com-server#readme", "dependencies": { "finalhandler": "^0.4.0", + "livereload": "^0.4.0", "localhost.daplie.com-certificates": "^1.1.2", "minimist": "^1.1.1", "redirect-https": "^1.1.0", diff --git a/serve.js b/serve.js index 7d258cb..86c70ba 100755 --- a/serve.js +++ b/serve.js @@ -31,7 +31,12 @@ function createInsecureServer(port, pubdir, opts) { function createServer(port, pubdir, content, opts) { var server = https.createServer(opts); var app = require('./app'); - var directive = { public: pubdir, content: content }; + + var directive = { public: pubdir, content: content, livereload: opts.livereload, servername: opts.servername }; + var livereload = require('livereload'); + var server2 = livereload.createServer({ https: opts }); + + server2.watch(pubdir); if (opts.insecurePort) { createInsecureServer(port, pubdir, opts); @@ -68,6 +73,7 @@ function run() { var minimist = require('minimist'); var argv = minimist(process.argv.slice(2)); var port = argv.p || argv.port || argv._[0] || 8443; + var livereload = argv.livereload; var pubdir = path.resolve(argv.d || argv._[1] || process.cwd()); var content = argv.c; var letsencryptHost = argv['letsencrypt-certs']; @@ -142,6 +148,7 @@ function run() { opts.servername = argv.servername; } opts.insecurePort = argv.i || argv['insecure-port']; + opts.livereload = livereload; createServer(port, pubdir, content, opts); } From 366cb78311cc0370758304baea65df764f1e2984 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Sat, 5 Dec 2015 22:43:43 -0800 Subject: [PATCH 025/129] v1.5.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9006c03..cc58cc3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "1.4.0", + "version": "1.5.0", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "serve.js", "scripts": { From 01b5a56acdf552a6475bf5bb0ee46572011da0f6 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Sat, 5 Dec 2015 22:54:47 -0800 Subject: [PATCH 026/129] note fswatch --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8d1c6b5..876cba0 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Usage * `-p ` - i.e. `sudo serve-https -p 443` (defaults to 8443) * `-d ` - i.e. `serve-https -d /tmp/` (defaults to `pwd`) * `-c ` - i.e. `server-https -c 'Hello, World! '` (defaults to directory index) -* `--livereload` - inject livereload into all html pages +* `--livereload` - inject livereload into all html pages (see also: [fswatch](http://stackoverflow.com/a/13807906/151312)) * `--insecure-port ` - run an http server that redirects to https (off by default) Specifying a custom HTTPS certificate: From c7417bdd870eaf635ae8c5864d4e98aa63c968b4 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Sat, 5 Dec 2015 22:55:20 -0800 Subject: [PATCH 027/129] oh, did you want more than the first packet? Ooops... fixed --- app.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/app.js b/app.js index 35ad727..b94e68a 100644 --- a/app.js +++ b/app.js @@ -25,10 +25,10 @@ module.exports = function (opts) { addLen = livereload.length; } - res.__end = res.end; res.__write = res.write; res.write = function (data, enc, cb) { if (this.headersSent) { + this.__write(data, enc, cb); return; } @@ -44,11 +44,6 @@ module.exports = function (opts) { this.__write(livereload); this.__write(data, enc, cb); }; - res.end = function () { - - - res.__end(); - }; serve(req, res, function (err) { if (err) { return done(err); } index(req, res, done); From f2a10a646a8ea2eb0c1e187e677b19eac1194240 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Sat, 5 Dec 2015 22:55:26 -0800 Subject: [PATCH 028/129] v1.5.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cc58cc3..06afffe 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "1.5.0", + "version": "1.5.1", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "serve.js", "scripts": { From 48db1620ad0fc679d2fa64845d568b668e24dab4 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 10 Dec 2015 21:30:54 -0800 Subject: [PATCH 029/129] fix serve-chain bug --- serve.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/serve.js b/serve.js index 86c70ba..cc8613e 100755 --- a/serve.js +++ b/serve.js @@ -93,7 +93,7 @@ function run() { if (letsencryptHost) { argv.key = argv.key || '/etc/letsencrypt/live/' + letsencryptHost + '/privkey.pem'; argv.cert = argv.cert || '/etc/letsencrypt/live/' + letsencryptHost + '/fullchain.pem'; - argv.root = argv.root || argv.chain || '/etc/letsencrypt/live/' + letsencryptHost + '/root.pem'; + argv.root = argv.root || argv.chain || ''; argv.servername = argv.servername || letsencryptHost; argv['serve-root'] = argv['serve-root'] || argv['serve-chain']; } @@ -131,16 +131,16 @@ function run() { })); }, []); - if (argv['serve-root']) { - content = opts.ca.join('\r\n'); - } - // TODO * `--verify /path/to/root.pem` require peers to present certificates from said authority if (argv.verify) { opts.ca = peerCa; opts.requestCert = true; opts.rejectUnauthorized = true; } + + if (argv['serve-root']) { + content = peerCa.join('\r\n'); + } } opts.servername = 'localhost.daplie.com'; From 10c9218ad9fb198a893b4c4df6d26aad5b59000b Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 10 Dec 2015 21:31:04 -0800 Subject: [PATCH 030/129] v1.5.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 06afffe..a4d75dd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "1.5.1", + "version": "1.5.2", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "serve.js", "scripts": { From 87de8812e0fb0bf59b6bbe016b67a92616d3fa4c Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 10 Jun 2016 10:49:21 -0600 Subject: [PATCH 031/129] updated required ssl certs --- package.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index a4d75dd..2593872 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/Daplie/localhost.daplie.com-server.git" + "url": "git+https://github.com/Daplie/serve-https.git" }, "keywords": [ "https", @@ -31,16 +31,16 @@ "serve", "server" ], - "author": "AJ ONeal (http://coolaj86.com/)", + "author": "AJ ONeal (https://coolaj86.com/)", "license": "Apache-2.0", "bugs": { - "url": "https://github.com/Daplie/localhost.daplie.com-server/issues" + "url": "https://github.com/Daplie/server-https/issues" }, - "homepage": "https://github.com/Daplie/localhost.daplie.com-server#readme", + "homepage": "https://github.com/Daplie/serve-https#readme", "dependencies": { "finalhandler": "^0.4.0", "livereload": "^0.4.0", - "localhost.daplie.com-certificates": "^1.1.2", + "localhost.daplie.com-certificates": "^1.2.0", "minimist": "^1.1.1", "redirect-https": "^1.1.0", "serve-index": "^1.7.0", From bcd927b7eaeed5edd459b7900f602dd1e2deac30 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 10 Jun 2016 10:50:35 -0600 Subject: [PATCH 032/129] bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2593872..61fed2b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "1.5.2", + "version": "1.5.3", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "serve.js", "scripts": { From b9edabe4bfbbaa72b491c497d783d2539f9c20db Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Sat, 6 Aug 2016 12:34:15 -0600 Subject: [PATCH 033/129] allow serving express app --- README.md | 1 + app.js | 10 +++++++++- serve.js | 17 +++++++++++++---- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 876cba0..a05dc92 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ Usage * `-p ` - i.e. `sudo serve-https -p 443` (defaults to 8443) * `-d ` - i.e. `serve-https -d /tmp/` (defaults to `pwd`) * `-c ` - i.e. `server-https -c 'Hello, World! '` (defaults to directory index) +* `--express-app` - path to a file the exports an express-style app (`function (req, res, next) { ... }`) * `--livereload` - inject livereload into all html pages (see also: [fswatch](http://stackoverflow.com/a/13807906/151312)) * `--insecure-port ` - run an http server that redirects to https (off by default) diff --git a/app.js b/app.js index b94e68a..fb0a289 100644 --- a/app.js +++ b/app.js @@ -46,7 +46,15 @@ module.exports = function (opts) { }; serve(req, res, function (err) { if (err) { return done(err); } - index(req, res, done); + index(req, res, function (err) { + if (err) { return done(err); } + if (opts.expressApp) { + opts.expressApp(req, res, done); + } + else { + done(); + } + }); }); }; }; diff --git a/serve.js b/serve.js index cc8613e..d6a97b7 100755 --- a/serve.js +++ b/serve.js @@ -32,7 +32,8 @@ function createServer(port, pubdir, content, opts) { var server = https.createServer(opts); var app = require('./app'); - var directive = { public: pubdir, content: content, livereload: opts.livereload, servername: opts.servername }; + var directive = { public: pubdir, content: content, livereload: opts.livereload + , servername: opts.servername, expressApp: opts.expressApp }; var livereload = require('livereload'); var server2 = livereload.createServer({ https: opts }); @@ -48,12 +49,15 @@ function createServer(port, pubdir, content, opts) { }); server.listen(port, function () { - var msg = 'Serving ' + pubdir + ' at https://' + opts.servername; + var msg = 'Serving ' + pubdir + ' at '; + var httpsUrl = 'https://' + opts.servername; var p = server.address().port; if (443 !== p) { - msg += ':' + p; + httpsUrl += ':' + p; } console.info(msg); + console.info(''); + console.info('\t' + httpsUrl); }); if ('function' === typeof app) { @@ -62,7 +66,7 @@ function createServer(port, pubdir, content, opts) { app = app.create(directive); } - Promise.resolve(app).then(function (app) { + return Promise.resolve(app).then(function (app) { server.on('request', app); }); } @@ -96,6 +100,7 @@ function run() { argv.root = argv.root || argv.chain || ''; argv.servername = argv.servername || letsencryptHost; argv['serve-root'] = argv['serve-root'] || argv['serve-chain']; + // argv[express-app] } if (argv['serve-root'] && !argv.root) { @@ -150,6 +155,10 @@ function run() { opts.insecurePort = argv.i || argv['insecure-port']; opts.livereload = livereload; + if (argv['express-app']) { + opts.expressApp = require(path.resolve(process.cwd(), argv['express-app'])); + } + createServer(port, pubdir, content, opts); } From 28579640b7e75de130e405dbe226db1372ab246a Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Sat, 6 Aug 2016 12:34:41 -0600 Subject: [PATCH 034/129] bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 61fed2b..c51d596 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "1.5.3", + "version": "1.5.4", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "serve.js", "scripts": { From c8db5bad73afea2e551a3e5d5b1ac1b4cd6c1f3b Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Sat, 6 Aug 2016 12:37:10 -0600 Subject: [PATCH 035/129] add whitespace in output --- serve.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/serve.js b/serve.js index d6a97b7..045c45a 100755 --- a/serve.js +++ b/serve.js @@ -55,9 +55,11 @@ function createServer(port, pubdir, content, opts) { if (443 !== p) { httpsUrl += ':' + p; } + console.info(''); console.info(msg); console.info(''); console.info('\t' + httpsUrl); + console.info(''); }); if ('function' === typeof app) { From 2bd79007deebfb5a6e1c4c22708a39a26740fcf7 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Sat, 6 Aug 2016 14:15:12 -0600 Subject: [PATCH 036/129] bugfix 405 Method Not Allowed --- app.js | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/app.js b/app.js index fb0a289..bd05672 100644 --- a/app.js +++ b/app.js @@ -44,17 +44,19 @@ module.exports = function (opts) { this.__write(livereload); this.__write(data, enc, cb); }; - serve(req, res, function (err) { - if (err) { return done(err); } - index(req, res, function (err) { + + function serveStatic() { + serve(req, res, function (err) { if (err) { return done(err); } - if (opts.expressApp) { - opts.expressApp(req, res, done); - } - else { - done(); - } + index(req, res, done); }); - }); + } + + if (opts.expressApp) { + opts.expressApp(req, res, serveStatic); + } + else { + serveStatic(); + } }; }; From d62e4ed8d8d8c5535d9c20e7ba1c0ff1a3d34bc3 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Sat, 6 Aug 2016 14:15:22 -0600 Subject: [PATCH 037/129] bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c51d596..528cb56 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "1.5.4", + "version": "1.5.5", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "serve.js", "scripts": { From f4c76a8bf727cc248636d21fc7165f442321147c Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 8 Sep 2016 23:10:04 -0600 Subject: [PATCH 038/129] output network interfaces --- local-ip.js | 45 +++++++++++++++++++++++++++++++++++++++++++++ serve.js | 28 ++++++++++++++++++++++++++-- 2 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 local-ip.js diff --git a/local-ip.js b/local-ip.js new file mode 100644 index 0000000..6356491 --- /dev/null +++ b/local-ip.js @@ -0,0 +1,45 @@ +'use strict'; + +var os = require('os'); + +module.exports.find = function () { + var ifaceMap = os.networkInterfaces(); + var newMap = {}; + + Object.keys(ifaceMap).forEach(function (iname) { + var ifaces = ifaceMap[iname]; + + ifaces = ifaces.filter(function (iface) { + return !iface.internal && !/^fe80/.test(iface.address) && !/^[0:]+$/.test(iface.mac); + }); + + if (!ifaces.length) { + return; + } + + newMap[iname] = newMap[iname] || { ipv4: [], ipv6: [] }; + + ifaces.forEach(function (addr) { + addr.iface = iname; + if ('IPv4' === addr.family) { + newMap[iname].ipv4.push(addr); + } + else if ('IPv6' === addr.family) { + newMap[iname].ipv6.push(addr); + } + }); + }); + + return newMap; + + /* +https://[2601:681:300:92c0:2477:d58a:d69e:51a0]:8443 + + console.log(''); + + console.log(''); + console.log(iname); + console.log(ifaces); + console.log(''); + */ +}; diff --git a/serve.js b/serve.js index 045c45a..aa97c24 100755 --- a/serve.js +++ b/serve.js @@ -59,6 +59,28 @@ function createServer(port, pubdir, content, opts) { console.info(msg); console.info(''); console.info('\t' + httpsUrl); + Object.keys(opts.ifaces).forEach(function (iname) { + var iface = opts.ifaces[iname]; + + if (iface.ipv4.length) { + console.info(''); + console.info(iname + ':'); + + httpsUrl = 'https://' + iface.ipv4[0].address; + if (443 !== p) { + httpsUrl += ':' + p; + } + console.info('\t' + httpsUrl); + + httpsUrl = 'https://[' + iface.ipv6[0].address + ']'; + if (443 !== p) { + httpsUrl += ':' + p; + } + if (iface.ipv6.length) { + console.info('\t' + httpsUrl); + } + } + }); console.info(''); }); @@ -83,14 +105,16 @@ function run() { var pubdir = path.resolve(argv.d || argv._[1] || process.cwd()); var content = argv.c; var letsencryptHost = argv['letsencrypt-certs']; + var tls = require('tls'); var cert = require('localhost.daplie.com-certificates'); var opts = { - key: cert.key + ifaces: require('./local-ip.js').find() + , key: cert.key , cert: cert.cert //, ca: cert.ca , SNICallback: function (servername, cb) { - cb(null, require('tls').createSecureContext(opts)); + cb(null, tls.createSecureContext(opts)); return; } }; From 0df58dc2c612a4de0ac1c31684bcc98e536357b2 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 8 Sep 2016 23:10:31 -0600 Subject: [PATCH 039/129] v1.5.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 528cb56..cf768d6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "1.5.5", + "version": "1.5.6", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "serve.js", "scripts": { From 3a1efa7cdfb79947b1ad998d90da74c09bd063b9 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Tue, 13 Sep 2016 17:08:08 -0600 Subject: [PATCH 040/129] check external ips --- local-ip.js | 12 ++- package.json | 1 + serve.js | 271 ++++++++++++++++++++++++++++++++++++--------------- 3 files changed, 206 insertions(+), 78 deletions(-) diff --git a/local-ip.js b/local-ip.js index 6356491..6b19a47 100644 --- a/local-ip.js +++ b/local-ip.js @@ -2,7 +2,10 @@ var os = require('os'); -module.exports.find = function () { +module.exports.find = function (opts) { + opts = opts || {}; + opts.externals = opts.externals || []; + var ifaceMap = os.networkInterfaces(); var newMap = {}; @@ -10,7 +13,12 @@ module.exports.find = function () { var ifaces = ifaceMap[iname]; ifaces = ifaces.filter(function (iface) { - return !iface.internal && !/^fe80/.test(iface.address) && !/^[0:]+$/.test(iface.mac); + return opts.externals.some(function (ip) { + if (ip.address === iface.address) { + ip.external = true; + return true; + } + }) || (!iface.internal && !/^fe80/.test(iface.address) && !/^[0:]+$/.test(iface.mac)); }); if (!ifaces.length) { diff --git a/package.json b/package.json index cf768d6..c94d28a 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "homepage": "https://github.com/Daplie/serve-https#readme", "dependencies": { "finalhandler": "^0.4.0", + "ipify": "^1.1.0", "livereload": "^0.4.0", "localhost.daplie.com-certificates": "^1.2.0", "minimist": "^1.1.1", diff --git a/serve.js b/serve.js index aa97c24..0cfe08c 100755 --- a/serve.js +++ b/serve.js @@ -1,125 +1,142 @@ #!/usr/bin/env node 'use strict'; +var PromiseA = global.Promise; // require('bluebird'); var https = require('https'); var http = require('http'); var fs = require('fs'); var path = require('path'); +var portFallback = 8443; +var insecurePortFallback = 4080; + +function showError(err, port) { + if ('EACCES' === err.code) { + console.error(err); + console.warn("You do not have permission to use '" + port + "'."); + console.warn("You can probably fix that by running as Administrator or root."); + } + else if ('EADDRINUSE' === err.code) { + console.warn("Another server is already running on '" + port + "'."); + console.warn("You can probably fix that by rebooting your comupter (or stopping it if you know what it is)."); + } +} function createInsecureServer(port, pubdir, opts) { - var server = http.createServer(); + return new PromiseA(function (resolve) { + var server = http.createServer(); - server.on('error', function (err) { - console.error(err); - process.exit(1); - }); + server.on('error', function (err) { + if (opts.errorInsecurePort || opts.manualInsecurePort) { + showError(err, port); + process.exit(1); + return; + } - server.on('request', require('redirect-https')({ - port: port - })); + opts.errorInsecurePort = err.toString(); - server.listen(opts.insecurePort, function () { - var msg = 'Serving ' + pubdir + ' at http://' + opts.servername; - var p = server.address().port; - if (80 !== p) { - msg += ':' + p; - } - console.info(msg); + return createInsecureServer(insecurePortFallback, pubdir, opts).then(resolve); + }); + + server.on('request', require('redirect-https')({ + port: opts.port + })); + + server.listen(port, function () { + opts.insecurePort = port; + resolve(); + }); }); } function createServer(port, pubdir, content, opts) { - var server = https.createServer(opts); - var app = require('./app'); + return new PromiseA(function (resolve) { + var server = https.createServer(opts); + var app = require('./app'); - var directive = { public: pubdir, content: content, livereload: opts.livereload - , servername: opts.servername, expressApp: opts.expressApp }; - var livereload = require('livereload'); - var server2 = livereload.createServer({ https: opts }); + var directive = { public: pubdir, content: content, livereload: opts.livereload + , servername: opts.servername, expressApp: opts.expressApp }; - server2.watch(pubdir); + server.on('error', function (err) { + if (opts.errorPort || opts.manualPort) { + showError(err, port); + process.exit(1); + return; + } - if (opts.insecurePort) { - createInsecureServer(port, pubdir, opts); - } + opts.errorPort = err.toString(); - server.on('error', function (err) { - console.error(err); - process.exit(1); - }); + return createServer(portFallback, pubdir, content, opts).then(resolve); + }); - server.listen(port, function () { - var msg = 'Serving ' + pubdir + ' at '; - var httpsUrl = 'https://' + opts.servername; - var p = server.address().port; - if (443 !== p) { - httpsUrl += ':' + p; - } - console.info(''); - console.info(msg); - console.info(''); - console.info('\t' + httpsUrl); - Object.keys(opts.ifaces).forEach(function (iname) { - var iface = opts.ifaces[iname]; + server.listen(port, function () { + opts.port = port; - if (iface.ipv4.length) { - console.info(''); - console.info(iname + ':'); + var livereload = require('livereload'); + var server2 = livereload.createServer({ https: opts }); - httpsUrl = 'https://' + iface.ipv4[0].address; - if (443 !== p) { - httpsUrl += ':' + p; - } - console.info('\t' + httpsUrl); + server2.watch(pubdir); - httpsUrl = 'https://[' + iface.ipv6[0].address + ']'; - if (443 !== p) { - httpsUrl += ':' + p; - } - if (iface.ipv6.length) { - console.info('\t' + httpsUrl); - } + if ('false' !== opts.insecurePort) { + return createInsecureServer(opts.insecurePort, pubdir, opts).then(resolve); + } else { + resolve(); } }); - console.info(''); - }); - if ('function' === typeof app) { - app = app(directive); - } else if ('function' === typeof app.create) { - app = app.create(directive); - } + if ('function' === typeof app) { + app = app(directive); + } else if ('function' === typeof app.create) { + app = app.create(directive); + } - return Promise.resolve(app).then(function (app) { - server.on('request', app); + server.on('request', function (req, res) { + if ('function' === typeof app) { + app(req, res); + return; + } + + res.end('not ready'); + }); + + return PromiseA.resolve(app).then(function (_app) { + app = _app; + }); }); } module.exports.createServer = createServer; function run() { + var defaultServername = 'localhost.daplie.com'; var minimist = require('minimist'); var argv = minimist(process.argv.slice(2)); - var port = argv.p || argv.port || argv._[0] || 8443; + var port = argv.p || argv.port || argv._[0] || 443; var livereload = argv.livereload; var pubdir = path.resolve(argv.d || argv._[1] || process.cwd()); var content = argv.c; var letsencryptHost = argv['letsencrypt-certs']; var tls = require('tls'); + // letsencrypt + var email = argv.email; + var agreeTos = argv.agreeTos || argv['agree-tos']; + var cert = require('localhost.daplie.com-certificates'); var opts = { - ifaces: require('./local-ip.js').find() - , key: cert.key + key: cert.key , cert: cert.cert //, ca: cert.ca - , SNICallback: function (servername, cb) { - cb(null, tls.createSecureContext(opts)); - return; - } + + , email: email + , agreeTos: agreeTos }; var peerCa; + opts.SNICallback = function (servername, cb) { + cb(null, tls.createSecureContext(opts)); + return; + }; + if (letsencryptHost) { argv.key = argv.key || '/etc/letsencrypt/live/' + letsencryptHost + '/privkey.pem'; argv.cert = argv.cert || '/etc/letsencrypt/live/' + letsencryptHost + '/fullchain.pem'; @@ -174,18 +191,120 @@ function run() { } } - opts.servername = 'localhost.daplie.com'; + opts.servername = defaultServername; if (argv.servername) { opts.servername = argv.servername; } - opts.insecurePort = argv.i || argv['insecure-port']; + if (argv.p || argv.port || argv._[0]) { + opts.manualPort = true; + } + if (argv.i || argv['insecure-port']) { + opts.manualInsecurePort = true; + } + opts.insecurePort = argv.i || argv['insecure-port'] || 80; opts.livereload = livereload; if (argv['express-app']) { opts.expressApp = require(path.resolve(process.cwd(), argv['express-app'])); } - createServer(port, pubdir, content, opts); + return createServer(port, pubdir, content, opts).then(function () { + var msg; + var p; + var httpsUrl; + var promise; + + // Port + msg = 'Serving ' + pubdir + ' at '; + httpsUrl = 'https://' + opts.servername; + p = opts.port; + if (443 !== p) { + httpsUrl += ':' + p; + } + console.info(''); + console.info(msg); + console.info(''); + console.info('\t' + httpsUrl); + + // Insecure Port + p = ''; + if (80 !== p) { + p = ':' + opts.insecurePort; + } + msg = '\thttp://' + opts.servername + p + ' (redirecting to https)'; + console.info(msg); + console.info(''); + + if (!(argv.servername && defaultServername !== argv.servername && !(argv.key && argv.cert))) { + // ifaces + opts.ifaces = require('./local-ip.js').find(); + promise = PromiseA.resolve(); + } else { + console.info("Attempting to resolve external connection for '" + argv.servername + "'"); + try { + promise = require('./match-ips.js').match(argv.servername, opts); + } catch(e) { + console.warn("Upgrade to version 2.x to use automatic certificate issuance for '" + argv.servername + "'"); + promise = PromiseA.resolve(); + } + } + + return promise.then(function (matchingIps) { + if (matchingIps) { + if (!matchingIps.length) { + console.log("Neither the attached nor external interfaces match '" + argv.servername + "'"); + } + opts.matchingIps = matchingIps || []; + } + + if (opts.matchingIps.length) { + console.info(''); + console.info('External IPs:'); + console.info(''); + opts.matchingIps.forEach(function (ip) { + if ('IPv4' === ip.family) { + httpsUrl = 'https://' + ip.address; + if (443 !== opts.port) { + httpsUrl += ':' + opts.port; + } + console.info('\t' + httpsUrl); + } + else { + httpsUrl = 'https://[' + ip.address + ']'; + if (443 !== opts.port) { + httpsUrl += ':' + opts.port; + } + console.info('\t' + httpsUrl); + } + }); + } + + Object.keys(opts.ifaces).forEach(function (iname) { + var iface = opts.ifaces[iname]; + + if (iface.ipv4.length) { + console.info(''); + console.info(iname + ':'); + + httpsUrl = 'https://' + iface.ipv4[0].address; + if (443 !== opts.port) { + httpsUrl += ':' + opts.port; + } + console.info('\t' + httpsUrl); + + httpsUrl = 'https://[' + iface.ipv6[0].address + ']'; + if (443 !== opts.port) { + httpsUrl += ':' + opts.port; + } + if (iface.ipv6.length) { + console.info('\t' + httpsUrl); + } + } + }); + + console.info(''); + }); + }); } if (require.main === module) { From 36b15be2761888c779575a0cef5343f4f7232921 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 6 Oct 2016 16:42:38 -0600 Subject: [PATCH 041/129] updates --- app.js | 2 +- match-ips.js | 107 ++++++++++++++++++++++++++++++++++++++++ package.json | 6 ++- serve.js | 136 ++++++++++++++++++++++++++++++++++++++++++--------- 4 files changed, 226 insertions(+), 25 deletions(-) create mode 100644 match-ips.js diff --git a/app.js b/app.js index bd05672..505c824 100644 --- a/app.js +++ b/app.js @@ -21,7 +21,7 @@ module.exports = function (opts) { if (opts.livereload) { livereload = ''; + + ':' + opts.lrPort + '/livereload.js?snipver=1">'; addLen = livereload.length; } diff --git a/match-ips.js b/match-ips.js new file mode 100644 index 0000000..061e2d4 --- /dev/null +++ b/match-ips.js @@ -0,0 +1,107 @@ +'use strict'; + +var PromiseA = require('bluebird'); + +module.exports.match = function (servername, opts) { + return PromiseA.promisify(require('ipify'))().then(function (ip) { + var dns = PromiseA.promisifyAll(require('dns')); + + opts.externalIps = [ { address: ip, family: 'IPv4' } ]; + opts.ifaces = require('./local-ip.js').find({ externals: opts.externalIps }); + opts.externalIfaces = Object.keys(opts.ifaces).reduce(function (all, iname) { + var iface = opts.ifaces[iname]; + + iface.ipv4.forEach(function (addr) { + if (addr.external) { + addr.iface = iname; + all.push(addr); + } + }); + iface.ipv6.forEach(function (addr) { + if (addr.external) { + addr.iface = iname; + all.push(addr); + } + }); + + return all; + }, []).filter(Boolean); + + function resolveIps(hostname) { + var allIps = []; + + return PromiseA.all([ + dns.resolve4Async(hostname).then(function (records) { + records.forEach(function (ip) { + allIps.push({ + address: ip + , family: 'IPv4' + }); + }); + }, function () {}) + , dns.resolve6Async(hostname).then(function (records) { + records.forEach(function (ip) { + allIps.push({ + address: ip + , family: 'IPv6' + }); + }); + }, function () {}) + ]).then(function () { + return allIps; + }); + } + + function resolveIpsAndCnames(hostname) { + return PromiseA.all([ + resolveIps(hostname) + , dns.resolveCnameAsync(hostname).then(function (records) { + return PromiseA.all(records.map(function (hostname) { + return resolveIps(hostname); + })).then(function (allIps) { + return allIps.reduce(function (all, ips) { + return all.concat(ips); + }, []); + }); + }, function () { + return []; + }) + ]).then(function (ips) { + return ips.reduce(function (all, set) { + return all.concat(set); + }, []); + }); + } + + return resolveIpsAndCnames(servername).then(function (allIps) { + var matchingIps = []; + + if (!allIps.length) { + console.warn("Could not resolve '" + servername + "'"); + } + + // { address, family } + allIps.some(function (ip) { + function match(addr) { + if (ip.address === addr.address) { + matchingIps.push(addr); + } + } + + opts.externalIps.forEach(match); + // opts.externalIfaces.forEach(match); + + Object.keys(opts.ifaces).forEach(function (iname) { + var iface = opts.ifaces[iname]; + + iface.ipv4.forEach(match); + iface.ipv6.forEach(match); + }); + + return matchingIps.length; + }); + + return matchingIps; + }); + }); +}; diff --git a/package.json b/package.json index c94d28a..9ab5141 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "1.5.6", + "version": "2.0.0", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "serve.js", "scripts": { @@ -38,8 +38,12 @@ }, "homepage": "https://github.com/Daplie/serve-https#readme", "dependencies": { + "bluebird": "^3.4.6", "finalhandler": "^0.4.0", "ipify": "^1.1.0", + "le-challenge-dns": "^2.0.1", + "le-challenge-fs": "^2.0.5", + "letsencrypt-express": "^2.0.2", "livereload": "^0.4.0", "localhost.daplie.com-certificates": "^1.2.0", "minimist": "^1.1.1", diff --git a/serve.js b/serve.js index 0cfe08c..e4cb91a 100755 --- a/serve.js +++ b/serve.js @@ -6,6 +6,7 @@ var https = require('https'); var http = require('http'); var fs = require('fs'); var path = require('path'); +var DDNS = require('ddns-cli'); var portFallback = 8443; var insecurePortFallback = 4080; @@ -49,13 +50,74 @@ function createInsecureServer(port, pubdir, opts) { } function createServer(port, pubdir, content, opts) { + function approveDomains(params, certs, cb) { + // This is where you check your database and associated + // email addresses with domains and agreements and such + var domains = params.domains; + //var p; + console.log('approveDomains'); + console.log(domains); + + + // The domains being approved for the first time are listed in opts.domains + // Certs being renewed are listed in certs.altnames + if (certs) { + params.domains = certs.altnames; + //p = PromiseA.resolve(); + } + else { + //params.email = opts.email; + if (!opts.agreeTos) { + console.error("You have not previously registered '" + domains + "' so you must specify --agree-tos to agree to both the Let's Encrypt and Daplie DNS terms of service."); + process.exit(1); + return; + } + params.agreeTos = opts.agreeTos; + } + + // ddns.token(params.email, domains[0]) + params.email = opts.email; + params.refreshToken = opts.refreshToken; + params.challengeType = 'dns-01'; + params.cli = opts.argv; + + cb(null, { options: params, certs: certs }); + } + return new PromiseA(function (resolve) { - var server = https.createServer(opts); var app = require('./app'); var directive = { public: pubdir, content: content, livereload: opts.livereload , servername: opts.servername, expressApp: opts.expressApp }; + // returns an instance of node-letsencrypt with additional helper methods + var webrootPath = require('os').tmpdir(); + var leChallengeFs = require('le-challenge-fs').create({ webrootPath: webrootPath }); + var leChallengeDns = require('le-challenge-dns').create({ ttl: 1 }); + var lex = require('letsencrypt-express').create({ + // set to https://acme-v01.api.letsencrypt.org/directory in production + server: opts.debug ? 'staging' : 'https://acme-v01.api.letsencrypt.org/directory' + + // If you wish to replace the default plugins, you may do so here + // + , challenges: { + 'http-01': leChallengeFs + , 'tls-sni-01': leChallengeFs + , 'dns-01': leChallengeDns + } + , challengeType: 'dns-01' + , store: require('le-store-certbot').create({ webrootPath: webrootPath }) + , webrootPath: webrootPath + + // You probably wouldn't need to replace the default sni handler + // See https://github.com/Daplie/le-sni-auto if you think you do + //, sni: require('le-sni-auto').create({}) + + , approveDomains: approveDomains + }); + opts.httpsOptions.SNICallback = lex.httpsOptions.SNICallback; + var server = https.createServer(opts.httpsOptions); + server.on('error', function (err) { if (opts.errorPort || opts.manualPort) { showError(err, port); @@ -71,8 +133,9 @@ function createServer(port, pubdir, content, opts) { server.listen(port, function () { opts.port = port; + opts.lrPort = 35729; var livereload = require('livereload'); - var server2 = livereload.createServer({ https: opts }); + var server2 = livereload.createServer({ https: opts.httpsOptions, port: opts.lrPort }); server2.watch(pubdir); @@ -90,6 +153,8 @@ function createServer(port, pubdir, content, opts) { } server.on('request', function (req, res) { + console.log('[' + req.method + '] ' + req.url); + if ('function' === typeof app) { app(req, res); return; @@ -118,22 +183,23 @@ function run() { var tls = require('tls'); // letsencrypt - var email = argv.email; - var agreeTos = argv.agreeTos || argv['agree-tos']; - var cert = require('localhost.daplie.com-certificates'); var opts = { - key: cert.key - , cert: cert.cert - //, ca: cert.ca - - , email: email - , agreeTos: agreeTos + agreeTos: argv.agreeTos || argv['agree-tos'] + , debug: argv.debug + , email: argv.email + , httpsOptions: { + key: cert.key + , cert: cert.cert + //, ca: cert.ca + } + , argv: argv }; var peerCa; + var p; - opts.SNICallback = function (servername, cb) { - cb(null, tls.createSecureContext(opts)); + opts.httpsOptions.SNICallback = function (servername, cb) { + cb(null, tls.createSecureContext(opts.httpsOptions)); return; }; @@ -161,8 +227,8 @@ function run() { argv.root = [argv.root]; } - opts.key = fs.readFileSync(argv.key); - opts.cert = fs.readFileSync(argv.cert); + opts.httpsOptions.key = fs.readFileSync(argv.key); + opts.httpsOptions.cert = fs.readFileSync(argv.cert); // turn multiple-cert pemfile into array of cert strings peerCa = argv.root.reduce(function (roots, fullpath) { @@ -181,9 +247,9 @@ function run() { // TODO * `--verify /path/to/root.pem` require peers to present certificates from said authority if (argv.verify) { - opts.ca = peerCa; - opts.requestCert = true; - opts.rejectUnauthorized = true; + opts.httpsOptions.ca = peerCa; + opts.httpsOptions.requestCert = true; + opts.httpsOptions.rejectUnauthorized = true; } if (argv['serve-root']) { @@ -208,6 +274,29 @@ function run() { opts.expressApp = require(path.resolve(process.cwd(), argv['express-app'])); } + if (opts.email || opts.servername) { + if (!opts.agreeTos) { + console.warn("You may need to specify --agree-tos to agree to both the Let's Encrypt and Daplie DNS terms of service."); + } + if (!opts.email) { + // TODO store email in .ddnsrc.json + console.warn("You may need to specify --email to register with both the Let's Encrypt and Daplie DNS."); + } + p = DDNS.refreshToken({ + email: opts.email + , silent: true + }, { + debug: false + , email: opts.argv.email + }).then(function (refreshToken) { + opts.refreshToken = refreshToken; + }); + } + else { + p = PromiseA.resolve(); + } + + return p.then(function () { return createServer(port, pubdir, content, opts).then(function () { var msg; var p; @@ -252,7 +341,7 @@ function run() { return promise.then(function (matchingIps) { if (matchingIps) { if (!matchingIps.length) { - console.log("Neither the attached nor external interfaces match '" + argv.servername + "'"); + console.info("Neither the attached nor external interfaces match '" + argv.servername + "'"); } opts.matchingIps = matchingIps || []; } @@ -292,11 +381,11 @@ function run() { } console.info('\t' + httpsUrl); - httpsUrl = 'https://[' + iface.ipv6[0].address + ']'; - if (443 !== opts.port) { - httpsUrl += ':' + opts.port; - } if (iface.ipv6.length) { + httpsUrl = 'https://[' + iface.ipv6[0].address + ']'; + if (443 !== opts.port) { + httpsUrl += ':' + opts.port; + } console.info('\t' + httpsUrl); } } @@ -305,6 +394,7 @@ function run() { console.info(''); }); }); + }); } if (require.main === module) { From f3fb34236b1cd2d8cf04b42572b711af66d54e7b Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 6 Oct 2016 17:09:21 -0600 Subject: [PATCH 042/129] use httpolyglot --- package.json | 1 + serve.js | 36 ++++++++++++++++++++++++++---------- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index c94d28a..d14126f 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "homepage": "https://github.com/Daplie/serve-https#readme", "dependencies": { "finalhandler": "^0.4.0", + "httpolyglot": "^0.1.1", "ipify": "^1.1.0", "livereload": "^0.4.0", "localhost.daplie.com-certificates": "^1.2.0", diff --git a/serve.js b/serve.js index 0cfe08c..9d0e256 100755 --- a/serve.js +++ b/serve.js @@ -2,10 +2,12 @@ 'use strict'; var PromiseA = global.Promise; // require('bluebird'); -var https = require('https'); +var https = require('httpolyglot'); var http = require('http'); var fs = require('fs'); var path = require('path'); +var httpPort = 80; +var httpsPort = 443; var portFallback = 8443; var insecurePortFallback = 4080; @@ -76,7 +78,7 @@ function createServer(port, pubdir, content, opts) { server2.watch(pubdir); - if ('false' !== opts.insecurePort) { + if ('false' !== opts.insecurePort && httpPort !== opts.insecurePort) { return createInsecureServer(opts.insecurePort, pubdir, opts).then(resolve); } else { resolve(); @@ -90,6 +92,17 @@ function createServer(port, pubdir, content, opts) { } server.on('request', function (req, res) { + if (!req.socket.encrypted) { + res.statusCode = 301; + res.setHeader( + 'Location' + , 'https://' + (req.headers.host || 'localhost') + + (httpsPort === opts.port ? '' : ':' + opts.port) + ); + res.end(); + return; + } + if ('function' === typeof app) { app(req, res); return; @@ -110,7 +123,7 @@ function run() { var defaultServername = 'localhost.daplie.com'; var minimist = require('minimist'); var argv = minimist(process.argv.slice(2)); - var port = argv.p || argv.port || argv._[0] || 443; + var port = parseInt(argv.p || argv.port || argv._[0], 10) || httpsPort; var livereload = argv.livereload; var pubdir = path.resolve(argv.d || argv._[1] || process.cwd()); var content = argv.c; @@ -201,7 +214,10 @@ function run() { if (argv.i || argv['insecure-port']) { opts.manualInsecurePort = true; } - opts.insecurePort = argv.i || argv['insecure-port'] || 80; + opts.insecurePort = parseInt(argv.i || argv['insecure-port'], 10) + || argv.i || argv['insecure-port'] + || httpPort + ; opts.livereload = livereload; if (argv['express-app']) { @@ -218,7 +234,7 @@ function run() { msg = 'Serving ' + pubdir + ' at '; httpsUrl = 'https://' + opts.servername; p = opts.port; - if (443 !== p) { + if (httpsPort !== p) { httpsUrl += ':' + p; } console.info(''); @@ -228,7 +244,7 @@ function run() { // Insecure Port p = ''; - if (80 !== p) { + if (httpPort !== p) { p = ':' + opts.insecurePort; } msg = '\thttp://' + opts.servername + p + ' (redirecting to https)'; @@ -264,14 +280,14 @@ function run() { opts.matchingIps.forEach(function (ip) { if ('IPv4' === ip.family) { httpsUrl = 'https://' + ip.address; - if (443 !== opts.port) { + if (httpsPort !== opts.port) { httpsUrl += ':' + opts.port; } console.info('\t' + httpsUrl); } else { httpsUrl = 'https://[' + ip.address + ']'; - if (443 !== opts.port) { + if (httpsPort !== opts.port) { httpsUrl += ':' + opts.port; } console.info('\t' + httpsUrl); @@ -287,13 +303,13 @@ function run() { console.info(iname + ':'); httpsUrl = 'https://' + iface.ipv4[0].address; - if (443 !== opts.port) { + if (httpsPort !== opts.port) { httpsUrl += ':' + opts.port; } console.info('\t' + httpsUrl); httpsUrl = 'https://[' + iface.ipv6[0].address + ']'; - if (443 !== opts.port) { + if (httpsPort !== opts.port) { httpsUrl += ':' + opts.port; } if (iface.ipv6.length) { From a33084d8168003ccfefeeaaa4fd56dabce63f9e8 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 6 Oct 2016 22:28:05 -0600 Subject: [PATCH 043/129] fix matching ips and httpolyglot --- serve.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/serve.js b/serve.js index 9d0e256..278878d 100755 --- a/serve.js +++ b/serve.js @@ -81,6 +81,7 @@ function createServer(port, pubdir, content, opts) { if ('false' !== opts.insecurePort && httpPort !== opts.insecurePort) { return createInsecureServer(opts.insecurePort, pubdir, opts).then(resolve); } else { + opts.insecurePort = opts.port; resolve(); } }); @@ -270,8 +271,8 @@ function run() { if (!matchingIps.length) { console.log("Neither the attached nor external interfaces match '" + argv.servername + "'"); } - opts.matchingIps = matchingIps || []; } + opts.matchingIps = matchingIps || []; if (opts.matchingIps.length) { console.info(''); From ba0c30b685a4a29fec2fed2be9cf739f9c7326b2 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 6 Oct 2016 22:40:16 -0600 Subject: [PATCH 044/129] bugfix print ipv6 when exists --- serve.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/serve.js b/serve.js index 278878d..a6a6f60 100755 --- a/serve.js +++ b/serve.js @@ -1,7 +1,8 @@ #!/usr/bin/env node 'use strict'; -var PromiseA = global.Promise; // require('bluebird'); +//var PromiseA = global.Promise; +var PromiseA = require('bluebird'); var https = require('httpolyglot'); var http = require('http'); var fs = require('fs'); @@ -309,11 +310,11 @@ function run() { } console.info('\t' + httpsUrl); - httpsUrl = 'https://[' + iface.ipv6[0].address + ']'; - if (httpsPort !== opts.port) { - httpsUrl += ':' + opts.port; - } if (iface.ipv6.length) { + httpsUrl = 'https://[' + iface.ipv6[0].address + ']'; + if (httpsPort !== opts.port) { + httpsUrl += ':' + opts.port; + } console.info('\t' + httpsUrl); } } From 992d0a609ac3330c23e6a11106fb4bf1ca24130c Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 7 Oct 2016 10:44:25 -0600 Subject: [PATCH 045/129] add tunnel arg --- serve.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/serve.js b/serve.js index d4d6d33..59ef2ff 100755 --- a/serve.js +++ b/serve.js @@ -278,6 +278,9 @@ function run() { if (argv.p || argv.port || argv._[0]) { opts.manualPort = true; } + if (argv.t || argv.tunnel) { + opts.tunnel = true; + } if (argv.i || argv['insecure-port']) { opts.manualInsecurePort = true; } From 7f2bca2fd96eeaa161a72e29d57824b67f372cdd Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 7 Oct 2016 10:51:05 -0600 Subject: [PATCH 046/129] merge httpsOptions --- serve.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/serve.js b/serve.js index a6a6f60..844bfb0 100755 --- a/serve.js +++ b/serve.js @@ -136,7 +136,7 @@ function run() { var email = argv.email; var agreeTos = argv.agreeTos || argv['agree-tos']; - var cert = require('localhost.daplie.com-certificates'); + var cert = require('localhost.daplie.com-certificates').merge({}); var opts = { key: cert.key , cert: cert.cert From f69bbb3d66d772004d83bf07e209ca4f61db8072 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 7 Oct 2016 11:23:43 -0600 Subject: [PATCH 047/129] update redirect --- serve.js | 13 +++++-------- stages/01-serve.js | 23 +++++++++++++++++++++++ 2 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 stages/01-serve.js diff --git a/serve.js b/serve.js index 844bfb0..251cbfe 100755 --- a/serve.js +++ b/serve.js @@ -58,6 +58,9 @@ function createServer(port, pubdir, content, opts) { var directive = { public: pubdir, content: content, livereload: opts.livereload , servername: opts.servername, expressApp: opts.expressApp }; + var redirectApp = require('redirect-https')({ + port: port + }); server.on('error', function (err) { if (opts.errorPort || opts.manualPort) { @@ -95,13 +98,7 @@ function createServer(port, pubdir, content, opts) { server.on('request', function (req, res) { if (!req.socket.encrypted) { - res.statusCode = 301; - res.setHeader( - 'Location' - , 'https://' + (req.headers.host || 'localhost') - + (httpsPort === opts.port ? '' : ':' + opts.port) - ); - res.end(); + redirectApp(req, res); return; } @@ -270,7 +267,7 @@ function run() { return promise.then(function (matchingIps) { if (matchingIps) { if (!matchingIps.length) { - console.log("Neither the attached nor external interfaces match '" + argv.servername + "'"); + console.info("Neither the attached nor external interfaces match '" + argv.servername + "'"); } } opts.matchingIps = matchingIps || []; diff --git a/stages/01-serve.js b/stages/01-serve.js new file mode 100644 index 0000000..ebb483d --- /dev/null +++ b/stages/01-serve.js @@ -0,0 +1,23 @@ +'use strict'; + +var https = require('httpolyglot'); +var httpsOptions = require('localhost.daplie.com-certificates').merge({}); +var httpsPort = 8443; +var redirectApp = require('redirect-https')({ + port: httpsPort +}); + +var server = https.createServer(httpsOptions); + +server.on('request', function (req, res) { + if (!req.socket.encrypted) { + redirectApp(req, res); + return; + } + + res.end("Hello, Encrypted World!"); +}); + +server.listen(httpsPort, function () { + console.log('https://' + 'localhost.daplie.com' + (443 === httpsPort ? ':' : ':' + httpsPort)); +}); From 51249791aacc5c602b124fba86de47692e34e6b4 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 7 Oct 2016 11:36:28 -0600 Subject: [PATCH 048/129] httpsOptions --- serve.js | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/serve.js b/serve.js index 251cbfe..37834b0 100755 --- a/serve.js +++ b/serve.js @@ -77,8 +77,9 @@ function createServer(port, pubdir, content, opts) { server.listen(port, function () { opts.port = port; + opts.lrPort = 35729; var livereload = require('livereload'); - var server2 = livereload.createServer({ https: opts }); + var server2 = livereload.createServer({ https: opts.httpsOptions, port: opts.lrPort }); server2.watch(pubdir); @@ -130,22 +131,23 @@ function run() { var tls = require('tls'); // letsencrypt - var email = argv.email; - var agreeTos = argv.agreeTos || argv['agree-tos']; - var cert = require('localhost.daplie.com-certificates').merge({}); - var opts = { - key: cert.key - , cert: cert.cert - //, ca: cert.ca - , email: email - , agreeTos: agreeTos + var opts = { + agreeTos: argv.agreeTos || argv['agree-tos'] + , debug: argv.debug + , email: argv.email + , httpsOptions: { + key: cert.key + , cert: cert.cert + //, ca: cert.ca + } + , argv: argv }; var peerCa; - opts.SNICallback = function (servername, cb) { - cb(null, tls.createSecureContext(opts)); + opts.httpsOptions.SNICallback = function (servername, cb) { + cb(null, tls.createSecureContext(opts.httpsOptions)); return; }; @@ -173,8 +175,8 @@ function run() { argv.root = [argv.root]; } - opts.key = fs.readFileSync(argv.key); - opts.cert = fs.readFileSync(argv.cert); + opts.httpsOptions.key = fs.readFileSync(argv.key); + opts.httpsOptions.cert = fs.readFileSync(argv.cert); // turn multiple-cert pemfile into array of cert strings peerCa = argv.root.reduce(function (roots, fullpath) { @@ -193,9 +195,9 @@ function run() { // TODO * `--verify /path/to/root.pem` require peers to present certificates from said authority if (argv.verify) { - opts.ca = peerCa; - opts.requestCert = true; - opts.rejectUnauthorized = true; + opts.httpsOptions.ca = peerCa; + opts.httpsOptions.requestCert = true; + opts.httpsOptions.rejectUnauthorized = true; } if (argv['serve-root']) { From cb898418f2e370de533cb83b839eefb25af8cf1f Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 7 Oct 2016 12:00:21 -0600 Subject: [PATCH 049/129] cache secureContext --- serve.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/serve.js b/serve.js index 37834b0..f0c88bf 100755 --- a/serve.js +++ b/serve.js @@ -132,6 +132,7 @@ function run() { // letsencrypt var cert = require('localhost.daplie.com-certificates').merge({}); + var secureContext; var opts = { agreeTos: argv.agreeTos || argv['agree-tos'] @@ -147,7 +148,10 @@ function run() { var peerCa; opts.httpsOptions.SNICallback = function (servername, cb) { - cb(null, tls.createSecureContext(opts.httpsOptions)); + if (!secureContext) { + secureContext = tls.createSecureContext(opts.httpsOptions); + } + cb(null, secureContext); return; }; From 56244d4d84a06e8b9cc2d990d71b4ff91b8ae7b6 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 7 Oct 2016 13:12:46 -0600 Subject: [PATCH 050/129] fix conditional livereload, warn about watching too many files --- app.js | 50 ++++++++++++++++++++++++++------------------------ package.json | 2 +- serve.js | 17 +++++++++++++---- 3 files changed, 40 insertions(+), 29 deletions(-) diff --git a/app.js b/app.js index bd05672..db54571 100644 --- a/app.js +++ b/app.js @@ -8,6 +8,26 @@ module.exports = function (opts) { var index = serveIndex(opts.public); var content = opts.content; + function _reloadWrite(data, enc, cb) { + /*jshint validthis: true */ + if (this.headersSent) { + this.__write(data, enc, cb); + return; + } + + if (!/html/i.test(this.getHeader('Content-Type'))) { + this.__write(data, enc, cb); + return; + } + + if (this.getHeader('Content-Length')) { + this.setHeader('Content-Length', this.getHeader('Content-Length') + this.__my_addLen); + } + + this.__write(this.__my_livereload); + this.__write(data, enc, cb); + } + return function (req, res) { if (content && '/' === req.url) { // res.setHeader('Content-Type', 'application/octet-stream'); @@ -15,36 +35,18 @@ module.exports = function (opts) { return; } var done = finalhandler(req, res); - var livereload = ''; - var addLen = 0; if (opts.livereload) { - livereload = ''; - addLen = livereload.length; + res.__my_addLen = res.__my_livereload.length; + + // TODO modify prototype instead of each instance? + res.__write = res.write; + res.write = _reloadWrite; } - res.__write = res.write; - res.write = function (data, enc, cb) { - if (this.headersSent) { - this.__write(data, enc, cb); - return; - } - - if (!/html/i.test(this.getHeader('Content-Type'))) { - this.__write(data, enc, cb); - return; - } - - if (this.getHeader('Content-Length')) { - this.setHeader('Content-Length', this.getHeader('Content-Length') + addLen); - } - - this.__write(livereload); - this.__write(data, enc, cb); - }; - function serveStatic() { serve(req, res, function (err) { if (err) { return done(err); } diff --git a/package.json b/package.json index d14126f..18cfef8 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "finalhandler": "^0.4.0", "httpolyglot": "^0.1.1", "ipify": "^1.1.0", - "livereload": "^0.4.0", + "livereload": "^0.5.0", "localhost.daplie.com-certificates": "^1.2.0", "minimist": "^1.1.1", "redirect-https": "^1.1.0", diff --git a/serve.js b/serve.js index f0c88bf..eb83136 100755 --- a/serve.js +++ b/serve.js @@ -9,6 +9,7 @@ var fs = require('fs'); var path = require('path'); var httpPort = 80; var httpsPort = 443; +var lrPort = 35729; var portFallback = 8443; var insecurePortFallback = 4080; @@ -77,11 +78,19 @@ function createServer(port, pubdir, content, opts) { server.listen(port, function () { opts.port = port; - opts.lrPort = 35729; - var livereload = require('livereload'); - var server2 = livereload.createServer({ https: opts.httpsOptions, port: opts.lrPort }); + if (opts.livereload) { + opts.lrPort = opts.lrPort || lrPort; + var livereload = require('livereload'); + var server2 = livereload.createServer({ + https: opts.httpsOptions + , port: opts.lrPort + , exclusions: [ '.hg', '.git', '.svn', 'node_modules' ] + }); - server2.watch(pubdir); + console.info("[livereload] watching " + pubdir); + console.warn("WARNING: If CPU usage spikes to 100% it's because too many files are being watched"); + server2.watch(pubdir); + } if ('false' !== opts.insecurePort && httpPort !== opts.insecurePort) { return createInsecureServer(opts.insecurePort, pubdir, opts).then(resolve); From aafc101f3e4194aeea78e1143cfab86d71afed80 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 7 Oct 2016 13:26:53 -0600 Subject: [PATCH 051/129] httpsOptions --- serve.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/serve.js b/serve.js index eb83136..3cc4f04 100755 --- a/serve.js +++ b/serve.js @@ -54,7 +54,7 @@ function createInsecureServer(port, pubdir, opts) { function createServer(port, pubdir, content, opts) { return new PromiseA(function (resolve) { - var server = https.createServer(opts); + var server = https.createServer(opts.httpsOptions); var app = require('./app'); var directive = { public: pubdir, content: content, livereload: opts.livereload @@ -140,7 +140,7 @@ function run() { var tls = require('tls'); // letsencrypt - var cert = require('localhost.daplie.com-certificates').merge({}); + var httpsOptions = require('localhost.daplie.com-certificates').merge({}); var secureContext; var opts = { @@ -148,9 +148,9 @@ function run() { , debug: argv.debug , email: argv.email , httpsOptions: { - key: cert.key - , cert: cert.cert - //, ca: cert.ca + key: httpsOptions.key + , cert: httpsOptions.cert + //, ca: httpsOptions.ca } , argv: argv }; From 3737455eedccb8bbee3048a7be484eb92f2b2dc3 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 7 Oct 2016 13:29:50 -0600 Subject: [PATCH 052/129] whitespace --- serve.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/serve.js b/serve.js index 3cc4f04..ad41e7d 100755 --- a/serve.js +++ b/serve.js @@ -151,7 +151,7 @@ function run() { key: httpsOptions.key , cert: httpsOptions.cert //, ca: httpsOptions.ca - } + } , argv: argv }; var peerCa; From 1eb0ddfe3673cd9161af687d3b9583de3c591cf0 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 7 Oct 2016 13:30:49 -0600 Subject: [PATCH 053/129] v1.5.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 18cfef8..657cf0d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "1.5.6", + "version": "1.5.7", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "serve.js", "scripts": { From d79120cac7e27b72747f333d7f4ecc955478f2fa Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 7 Oct 2016 13:46:29 -0600 Subject: [PATCH 054/129] update README --- README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index a05dc92..1ab4008 100644 --- a/README.md +++ b/README.md @@ -23,12 +23,11 @@ Serving /Users/foo/ at https://localhost.daplie.com:8443 Usage ----- -* `-p ` - i.e. `sudo serve-https -p 443` (defaults to 8443) +* `-p ` - i.e. `sudo serve-https -p 443` (defaults to 80+443 or 8443) * `-d ` - i.e. `serve-https -d /tmp/` (defaults to `pwd`) * `-c ` - i.e. `server-https -c 'Hello, World! '` (defaults to directory index) * `--express-app` - path to a file the exports an express-style app (`function (req, res, next) { ... }`) -* `--livereload` - inject livereload into all html pages (see also: [fswatch](http://stackoverflow.com/a/13807906/151312)) -* `--insecure-port ` - run an http server that redirects to https (off by default) +* `--livereload` - inject livereload into all html pages (see also: [fswatch](http://stackoverflow.com/a/13807906/151312)), but be careful if `` has thousands of files it will spike your CPU usage to 100% Specifying a custom HTTPS certificate: @@ -54,7 +53,7 @@ Examples ```bash serve-https -p 1443 -c 'Hello from 1443' & serve-https -p 2443 -c 'Hello from 2443' & -serve-https -p 3443 -d /tmp --insecure-port 4080 & +serve-https -p 3443 -d /tmp & curl https://localhost.daplie.com:1443 > Hello from 1443 @@ -66,8 +65,8 @@ curl https://localhost.daplie.com:3443 > [html index listing of /tmp] ``` -And if you tested in a browser, -it would redirect to . +And if you tested in a browser, +it would redirect to (on the same port). (in curl it would just show an error message) From 77ede0ca59c666942516badacdc1897e2d9ee981 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 7 Oct 2016 13:46:48 -0600 Subject: [PATCH 055/129] v1.6.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 657cf0d..9fadbfe 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "1.5.7", + "version": "1.6.0", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "serve.js", "scripts": { From 9e2b3dbaa58f3d3d2fd0eae67708bee7546f17c2 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 7 Oct 2016 15:28:46 -0600 Subject: [PATCH 056/129] add version flag --- serve.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/serve.js b/serve.js index ad41e7d..bbc71b4 100755 --- a/serve.js +++ b/serve.js @@ -139,6 +139,14 @@ function run() { var letsencryptHost = argv['letsencrypt-certs']; var tls = require('tls'); + if (argv.V || argv.version || argv.v) { + if (argv.v) { + console.warn("flag -v is reserved for future use. Use -V or --version for version information."); + } + console.info('v' + require('./package.json').version); + return; + } + // letsencrypt var httpsOptions = require('localhost.daplie.com-certificates').merge({}); var secureContext; From d192cd8255be2e8e4a361372957e2b101edf3ebe Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 7 Oct 2016 15:28:54 -0600 Subject: [PATCH 057/129] v1.6.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9fadbfe..0d1dcc4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "1.6.0", + "version": "1.6.1", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "serve.js", "scripts": { From 344a3eba41f7976e58db498e908802e2bb7f39f2 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Tue, 11 Oct 2016 10:58:18 -0600 Subject: [PATCH 058/129] minor refactoring --- serve.js | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/serve.js b/serve.js index bbc71b4..aaca97e 100755 --- a/serve.js +++ b/serve.js @@ -26,9 +26,13 @@ function showError(err, port) { } function createInsecureServer(port, pubdir, opts) { - return new PromiseA(function (resolve) { + return new PromiseA(function (realResolve) { var server = http.createServer(); + function resolve() { + realResolve(server); + } + server.on('error', function (err) { if (opts.errorInsecurePort || opts.manualInsecurePort) { showError(err, port); @@ -41,9 +45,7 @@ function createInsecureServer(port, pubdir, opts) { return createInsecureServer(insecurePortFallback, pubdir, opts).then(resolve); }); - server.on('request', require('redirect-https')({ - port: opts.port - })); + server.on('request', opts.redirectApp); server.listen(port, function () { opts.insecurePort = port; @@ -53,15 +55,20 @@ function createInsecureServer(port, pubdir, opts) { } function createServer(port, pubdir, content, opts) { - return new PromiseA(function (resolve) { + return new PromiseA(function (realResolve) { var server = https.createServer(opts.httpsOptions); var app = require('./app'); var directive = { public: pubdir, content: content, livereload: opts.livereload , servername: opts.servername, expressApp: opts.expressApp }; - var redirectApp = require('redirect-https')({ - port: port - }); + var insecureServer; + + function resolve() { + realResolve({ + plainServer: insecureServer + , server: server + }); + } server.on('error', function (err) { if (opts.errorPort || opts.manualPort) { @@ -77,6 +84,7 @@ function createServer(port, pubdir, content, opts) { server.listen(port, function () { opts.port = port; + opts.redirectOptions.port = port; if (opts.livereload) { opts.lrPort = opts.lrPort || lrPort; @@ -93,7 +101,10 @@ function createServer(port, pubdir, content, opts) { } if ('false' !== opts.insecurePort && httpPort !== opts.insecurePort) { - return createInsecureServer(opts.insecurePort, pubdir, opts).then(resolve); + return createInsecureServer(opts.insecurePort, pubdir, opts).then(function (_server) { + insecureServer = _server; + resolve(); + }); } else { opts.insecurePort = opts.port; resolve(); @@ -108,7 +119,7 @@ function createServer(port, pubdir, content, opts) { server.on('request', function (req, res) { if (!req.socket.encrypted) { - redirectApp(req, res); + opts.redirectApp(req, res); return; } @@ -246,6 +257,12 @@ function run() { opts.expressApp = require(path.resolve(process.cwd(), argv['express-app'])); } + // can be changed to tunnel external port + opts.redirectOptions = { + port: opts.port + }; + opts.redirectApp = require('redirect-https')(opts.redirectOptions); + return createServer(port, pubdir, content, opts).then(function () { var msg; var p; From fa0990b02f96b4f86b908de112b88748536956e4 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Tue, 11 Oct 2016 13:41:29 -0600 Subject: [PATCH 059/129] add some tunnel support --- lib/tunnel.js | 30 ++++++++++++++++++++++++++++++ serve.js | 5 ++++- 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 lib/tunnel.js diff --git a/lib/tunnel.js b/lib/tunnel.js new file mode 100644 index 0000000..ea09873 --- /dev/null +++ b/lib/tunnel.js @@ -0,0 +1,30 @@ +'use strict'; + +module.exports.create = function (opts/*, servers*/) { + // servers = { plainserver, server } + var tunnel = require('daplie-tunnel'); + var stunnel = require('stunnel'); + + + return tunnel.token({ + refreshToken: opts.refreshToken + , email: opts.email + , domains: [ opts.servername ] + }).then(function (result) { + // { jwt, tunnelUrl } + stunnel.connect({ + token: result.jwt + , stunneld: result.tunnelUrl + , locals: [ + { protocol: 'https' + , hostname: opts.servername + , port: opts.port + } + , { protocol: 'http' + , hostname: opts.servername + , port: opts.insecurePort || opts.port + } + ] + }); + }); +}; diff --git a/serve.js b/serve.js index a2ec860..b4f7fcd 100755 --- a/serve.js +++ b/serve.js @@ -181,7 +181,7 @@ function createServer(port, pubdir, content, opts) { server.on('request', function (req, res) { console.log('[' + req.method + '] ' + req.url); - if (!req.socket.encrypted) { + if (!req.socket.encrypted && !/\/\.well-known\/acme-challenge\//.test(req.url)) { opts.redirectApp(req, res); return; } @@ -424,6 +424,9 @@ function run() { } }); } + else { + require('./lib/tunnel.js').create(opts); + } Object.keys(opts.ifaces).forEach(function (iname) { var iface = opts.ifaces[iname]; From cd2fda3f2bfa7c862143e66758bb43121a9c8c6d Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Tue, 11 Oct 2016 17:20:10 -0600 Subject: [PATCH 060/129] partial tunnel integration --- lib/tunnel.js | 114 ++++++++++++++++++++++++++++++++++++++++++++++++-- serve.js | 34 +++++++++++---- 2 files changed, 137 insertions(+), 11 deletions(-) diff --git a/lib/tunnel.js b/lib/tunnel.js index ea09873..dc1010f 100644 --- a/lib/tunnel.js +++ b/lib/tunnel.js @@ -1,20 +1,75 @@ 'use strict'; -module.exports.create = function (opts/*, servers*/) { +module.exports.create = function (opts, servers) { // servers = { plainserver, server } - var tunnel = require('daplie-tunnel'); + var Oauth3 = require('oauth3-cli'); + var Tunnel = require('daplie-tunnel').create({ + Oauth3: Oauth3 + , PromiseA: opts.PromiseA + , CLI: { + init: function (/*rs, ws, state, options*/) { + // noop + } + } + }).Tunnel; var stunnel = require('stunnel'); + var killcount = 0; + /* + var Dup = { + write: function (chunk, encoding, cb) { + this.__my_socket.push(chunk, encoding); + cb(); + } + , read: function (size) { + var x = this.__my_socket.read(size); + if (x) { this.push(x); } + } + , setTimeout: function () { + console.log('TODO implement setTimeout on Duplex'); + } + }; - return tunnel.token({ + var httpServer = require('http').createServer(function (req, res) { + console.log('req.socket.encrypted', req.socket.encrypted); + res.end('Hello, tunneled World!'); + }); + + var tlsServer = require('tls').createServer(opts.httpsOptions, function (tlsSocket) { + console.log('tls connection'); + // things get a little messed up here + httpServer.emit('connection', tlsSocket); + + // try again + //servers.server.emit('connection', tlsSocket); + }); + */ + + process.on('SIGINT', function () { + killcount += 1; + console.log('[quit] closing http and https servers'); + if (killcount >= 3) { + process.exit(1); + } + if (servers.server) { + servers.server.close(); + } + if (servers.insecureServer) { + servers.insecureServer.close(); + } + }); + + return Tunnel.token({ refreshToken: opts.refreshToken , email: opts.email , domains: [ opts.servername ] }).then(function (result) { // { jwt, tunnelUrl } - stunnel.connect({ + return stunnel.connect({ token: result.jwt , stunneld: result.tunnelUrl + // XXX TODO BUG // this is just for testing + , insecure: /*opts.insecure*/ true , locals: [ { protocol: 'https' , hostname: opts.servername @@ -25,6 +80,57 @@ module.exports.create = function (opts/*, servers*/) { , port: opts.insecurePort || opts.port } ] + // a simple passthru is proving to not be so simple + , net: require('net') /* + { + createConnection: function (info, cb) { + // data is the hello packet / first chunk + // info = { data, servername, port, host, remoteAddress: { family, address, port } } + + var myDuplex = new (require('stream').Duplex)(); + var myDuplex2 = new (require('stream').Duplex)(); + // duplex = { write, push, end, events: [ 'readable', 'data', 'error', 'end' ] }; + + myDuplex2.__my_socket = myDuplex; + myDuplex.__my_socket = myDuplex2; + + myDuplex2._write = Dup.write; + myDuplex2._read = Dup.read; + + myDuplex._write = Dup.write; + myDuplex._read = Dup.read; + + myDuplex.remoteFamily = info.remoteFamily; + myDuplex.remoteAddress = info.remoteAddress; + myDuplex.remotePort = info.remotePort; + + // socket.local{Family,Address,Port} + myDuplex.localFamily = 'IPv4'; + myDuplex.localAddress = '127.0.01'; + myDuplex.localPort = info.port; + + myDuplex.setTimeout = Dup.setTimeout; + + // this doesn't seem to work so well + //servers.server.emit('connection', myDuplex); + + // try a little more manual wrapping / unwrapping + var firstByte = info.data[0]; + if (firstByte < 32 || firstByte >= 127) { + tlsServer.emit('connection', myDuplex); + } + else { + httpServer.emit('connection', myDuplex); + } + + if (cb) { + process.nextTick(cb); + } + + return myDuplex2; + } + } + //*/ }); }); }; diff --git a/serve.js b/serve.js index b4f7fcd..1c6e082 100755 --- a/serve.js +++ b/serve.js @@ -3,6 +3,7 @@ //var PromiseA = global.Promise; var PromiseA = require('bluebird'); +var tls = require('tls'); var https = require('httpolyglot'); var http = require('http'); var fs = require('fs'); @@ -107,6 +108,7 @@ function createServer(port, pubdir, content, opts) { // returns an instance of node-letsencrypt with additional helper methods var webrootPath = require('os').tmpdir(); var leChallengeFs = require('le-challenge-fs').create({ webrootPath: webrootPath }); + //var leChallengeSni = require('le-challenge-sni').create({ webrootPath: webrootPath }); var leChallengeDns = require('le-challenge-dns').create({ ttl: 1 }); var lex = require('letsencrypt-express').create({ // set to https://acme-v01.api.letsencrypt.org/directory in production @@ -116,10 +118,10 @@ function createServer(port, pubdir, content, opts) { // , challenges: { 'http-01': leChallengeFs - , 'tls-sni-01': leChallengeFs + , 'tls-sni-01': leChallengeFs // leChallengeSni , 'dns-01': leChallengeDns } - , challengeType: 'dns-01' + , challengeType: (opts.tunnel ? 'http-01' : 'dns-01') , store: require('le-store-certbot').create({ webrootPath: webrootPath }) , webrootPath: webrootPath @@ -129,7 +131,20 @@ function createServer(port, pubdir, content, opts) { , approveDomains: approveDomains }); - opts.httpsOptions.SNICallback = lex.httpsOptions.SNICallback; + var secureContext; + opts.httpsOptions.SNICallback = function (servername, cb ) { + console.log('[https] servername', servername); + + if ('localhost.daplie.com' === servername) { + if (!secureContext) { + secureContext = tls.createSecureContext(opts.httpsOptions); + } + cb(null, secureContext); + return; + } + + lex.httpsOptions.SNICallback(servername, cb); + }; var server = https.createServer(opts.httpsOptions); server.on('error', function (err) { @@ -211,7 +226,6 @@ function run() { var pubdir = path.resolve(argv.d || argv._[1] || process.cwd()); var content = argv.c; var letsencryptHost = argv['letsencrypt-certs']; - var tls = require('tls'); if (argv.V || argv.version || argv.v) { if (argv.v) { @@ -239,6 +253,7 @@ function run() { var peerCa; var p; + opts.PromiseA = PromiseA; opts.httpsOptions.SNICallback = function (servername, cb) { if (!secureContext) { secureContext = tls.createSecureContext(opts.httpsOptions); @@ -354,7 +369,7 @@ function run() { }; opts.redirectApp = require('redirect-https')(opts.redirectOptions); - return createServer(port, pubdir, content, opts).then(function () { + return createServer(port, pubdir, content, opts).then(function (servers) { var msg; var p; var httpsUrl; @@ -424,8 +439,13 @@ function run() { } }); } - else { - require('./lib/tunnel.js').create(opts); + else if (!opts.tunnel) { + console.info("External IP address does not match local IP address."); + console.info("Use --tunnel to allow the people of the Internet to access your server."); + } + + if (opts.tunnel) { + require('./lib/tunnel.js').create(opts, servers); } Object.keys(opts.ifaces).forEach(function (iname) { From 5bacbf747feac46e4b4507ef8c4b4075d5082cc9 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Tue, 11 Oct 2016 17:20:37 -0600 Subject: [PATCH 061/129] require tls sooner --- serve.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/serve.js b/serve.js index aaca97e..9404305 100755 --- a/serve.js +++ b/serve.js @@ -3,6 +3,7 @@ //var PromiseA = global.Promise; var PromiseA = require('bluebird'); +var tls = require('tls'); var https = require('httpolyglot'); var http = require('http'); var fs = require('fs'); @@ -148,7 +149,6 @@ function run() { var pubdir = path.resolve(argv.d || argv._[1] || process.cwd()); var content = argv.c; var letsencryptHost = argv['letsencrypt-certs']; - var tls = require('tls'); if (argv.V || argv.version || argv.v) { if (argv.v) { From 7634414d824d047aacfb6125b9fd4515a40b1e82 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 12 Oct 2016 18:22:43 -0600 Subject: [PATCH 062/129] cleanup to lib/ --- local-ip.js => lib/local-ip.js | 0 match-ips.js => lib/match-ips.js | 0 serve.js | 4 ++-- 3 files changed, 2 insertions(+), 2 deletions(-) rename local-ip.js => lib/local-ip.js (100%) rename match-ips.js => lib/match-ips.js (100%) diff --git a/local-ip.js b/lib/local-ip.js similarity index 100% rename from local-ip.js rename to lib/local-ip.js diff --git a/match-ips.js b/lib/match-ips.js similarity index 100% rename from match-ips.js rename to lib/match-ips.js diff --git a/serve.js b/serve.js index 1c6e082..b55f8c7 100755 --- a/serve.js +++ b/serve.js @@ -398,12 +398,12 @@ function run() { if (!(argv.servername && defaultServername !== argv.servername && !(argv.key && argv.cert))) { // ifaces - opts.ifaces = require('./local-ip.js').find(); + opts.ifaces = require('./lib/local-ip.js').find(); promise = PromiseA.resolve(); } else { console.info("Attempting to resolve external connection for '" + argv.servername + "'"); try { - promise = require('./match-ips.js').match(argv.servername, opts); + promise = require('./lib/match-ips.js').match(argv.servername, opts); } catch(e) { console.warn("Upgrade to version 2.x to use automatic certificate issuance for '" + argv.servername + "'"); promise = PromiseA.resolve(); From 1d2aa52b02419386a6efbce227fec491562819b4 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 12 Oct 2016 18:23:39 -0600 Subject: [PATCH 063/129] cleanup to lib/ --- app.js => lib/app.js | 0 serve.js | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename app.js => lib/app.js (100%) diff --git a/app.js b/lib/app.js similarity index 100% rename from app.js rename to lib/app.js diff --git a/serve.js b/serve.js index b55f8c7..5f15d49 100755 --- a/serve.js +++ b/serve.js @@ -92,7 +92,7 @@ function createServer(port, pubdir, content, opts) { } return new PromiseA(function (realResolve) { - var app = require('./app'); + var app = require('./lib/app.js'); var directive = { public: pubdir, content: content, livereload: opts.livereload , servername: opts.servername, expressApp: opts.expressApp }; From 62a2f7d44d413b3847eda7b32231c73a49ae2998 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Mon, 17 Oct 2016 17:40:55 -0600 Subject: [PATCH 064/129] make it better --- lib/ddns.js | 88 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/match-ips.js | 14 ++++++-- package.json | 2 +- serve.js | 5 ++- 4 files changed, 105 insertions(+), 4 deletions(-) create mode 100644 lib/ddns.js diff --git a/lib/ddns.js b/lib/ddns.js new file mode 100644 index 0000000..f860926 --- /dev/null +++ b/lib/ddns.js @@ -0,0 +1,88 @@ +'use strict'; + +module.exports.create = function (opts/*, servers*/) { + var PromiseA = opts.PromiseA; + var dns = PromiseA.promisifyAll(require('dns')); + + return PromiseA.all([ + dns.resolve4Async(opts.servername).then(function (results) { + return results; + }, function () {}) + , dns.resolve6Async(opts.servername).then(function (results) { + return results; + }, function () {}) + ]).then(function (results) { + var ipv4 = results[0] || []; + var ipv6 = results[1] || []; + var record; + + opts.dnsRecords = { + A: ipv4 + , AAAA: ipv6 + }; + + Object.keys(opts.ifaces).some(function (ifacename) { + var iface = opts.ifaces[ifacename]; + + return iface.ipv4.some(function (localIp) { + return ipv4.some(function (remoteIp) { + if (localIp.address === remoteIp) { + record = localIp; + return record; + } + }); + }) || iface.ipv6.some(function (localIp) { + return ipv6.forEach(function (remoteIp) { + if (localIp.address === remoteIp) { + record = localIp; + return record; + } + }); + }); + }); + + if (!record) { + console.info("DNS Record '" + ipv4.concat(ipv6).join(',') + "' does not match any local IP address."); + console.info("Use --ddns to allow the people of the Internet to access your server."); + } + + opts.externalIps.ipv4.some(function (localIp) { + return ipv4.some(function (remoteIp) { + if (localIp.address === remoteIp) { + record = localIp; + return record; + } + }); + }); + + opts.externalIps.ipv6.some(function (localIp) { + return ipv6.some(function (remoteIp) { + if (localIp.address === remoteIp) { + record = localIp; + return record; + } + }); + }); + + if (!record) { + console.info("DNS Record '" + ipv4.concat(ipv6).join(',') + "' does not match any local IP address."); + console.info("Use --ddns to allow the people of the Internet to access your server."); + } + }); +}; + +if (require.main === module) { + var opts = { + servername: 'aj.daplie.me' + , PromiseA: require('bluebird') + }; + // ifaces + opts.ifaces = require('./local-ip.js').find(); + console.log('opts.ifaces'); + console.log(opts.ifaces); + require('./match-ips.js').match(opts.servername, opts).then(function (ips) { + opts.matchingIps = ips.matchingIps || []; + opts.externalIps = ips.externalIps; + module.exports.create(opts); + }); +} diff --git a/lib/match-ips.js b/lib/match-ips.js index 061e2d4..dbb3ff1 100644 --- a/lib/match-ips.js +++ b/lib/match-ips.js @@ -3,10 +3,10 @@ var PromiseA = require('bluebird'); module.exports.match = function (servername, opts) { - return PromiseA.promisify(require('ipify'))().then(function (ip) { + return PromiseA.promisify(require('ipify'))().then(function (externalIp) { var dns = PromiseA.promisifyAll(require('dns')); - opts.externalIps = [ { address: ip, family: 'IPv4' } ]; + opts.externalIps = [ { address: externalIp, family: 'IPv4' } ]; opts.ifaces = require('./local-ip.js').find({ externals: opts.externalIps }); opts.externalIfaces = Object.keys(opts.ifaces).reduce(function (all, iname) { var iface = opts.ifaces[iname]; @@ -101,6 +101,16 @@ module.exports.match = function (servername, opts) { return matchingIps.length; }); + matchingIps.externalIps = { + ipv4: [ + { address: externalIp + , family: 'IPv4' + } + ] + , ipv6: [ + ] + }; + matchingIps.matchingIps = matchingIps; return matchingIps; }); }); diff --git a/package.json b/package.json index e2889e1..cf328fe 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "le-challenge-dns": "^2.0.1", "le-challenge-fs": "^2.0.5", "letsencrypt-express": "^2.0.2", - "livereload": "^0.5.0", + "livereload": "^0.6.0", "localhost.daplie.com-certificates": "^1.2.0", "minimist": "^1.1.1", "redirect-https": "^1.1.0", diff --git a/serve.js b/serve.js index 5f15d49..f020692 100755 --- a/serve.js +++ b/serve.js @@ -169,7 +169,7 @@ function createServer(port, pubdir, content, opts) { var server2 = livereload.createServer({ https: opts.httpsOptions , port: opts.lrPort - , exclusions: [ '.hg', '.git', '.svn', 'node_modules' ] + , exclusions: [ 'node_modules' ] }); console.info("[livereload] watching " + pubdir); @@ -447,6 +447,9 @@ function run() { if (opts.tunnel) { require('./lib/tunnel.js').create(opts, servers); } + else if (opts.ddns) { + require('./lib/ddns.js').create(opts, servers); + } Object.keys(opts.ifaces).forEach(function (iname) { var iface = opts.ifaces[iname]; From ff5857bd27213c00c8da3d74d7762a5372ae3b22 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Mon, 17 Oct 2016 17:46:11 -0600 Subject: [PATCH 065/129] update options --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1ab4008..b26bf42 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,14 @@ Usage * `-p ` - i.e. `sudo serve-https -p 443` (defaults to 80+443 or 8443) * `-d ` - i.e. `serve-https -d /tmp/` (defaults to `pwd`) * `-c ` - i.e. `server-https -c 'Hello, World! '` (defaults to directory index) -* `--express-app` - path to a file the exports an express-style app (`function (req, res, next) { ... }`) +* `--express-app ` - path to a file the exports an express-style app (`function (req, res, next) { ... }`) * `--livereload` - inject livereload into all html pages (see also: [fswatch](http://stackoverflow.com/a/13807906/151312)), but be careful if `` has thousands of files it will spike your CPU usage to 100% +* `--email ` - email to use for Let's Encrypt, Daplie DNS, Daplie Tunnel +* `--agree-tos` - agree to terms for Let's Encrypt, Daplie DNS +* `--servername ` - use `` instead of `localhost.daplie.com` +* `--tunnel` - make world-visible (must use `--servername`) + Specifying a custom HTTPS certificate: * `--key /path/to/privkey.pem` specifies the server private key From 8de4178a7d027e120f557afce57240d4bfb7b723 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Mon, 17 Oct 2016 17:50:17 -0600 Subject: [PATCH 066/129] add example --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index b26bf42..5cf1ddb 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,12 @@ Serving /Users/foo/ at https://localhost.daplie.com:8443 Usage ----- +Examples: + +``` +node serve.js --servername jane.daplie.me --agree-tos --email jane@example.com --tunnel +``` + * `-p ` - i.e. `sudo serve-https -p 443` (defaults to 80+443 or 8443) * `-d ` - i.e. `serve-https -d /tmp/` (defaults to `pwd`) * `-c ` - i.e. `server-https -c 'Hello, World! '` (defaults to directory index) From 31fec862f476eb3e5c29efcb2db221c5d3c5e4fb Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Mon, 17 Oct 2016 17:52:32 -0600 Subject: [PATCH 067/129] add options --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 5cf1ddb..fd66ae9 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,8 @@ Examples: node serve.js --servername jane.daplie.me --agree-tos --email jane@example.com --tunnel ``` +Options: + * `-p ` - i.e. `sudo serve-https -p 443` (defaults to 80+443 or 8443) * `-d ` - i.e. `serve-https -d /tmp/` (defaults to `pwd`) * `-c ` - i.e. `server-https -c 'Hello, World! '` (defaults to directory index) From 0e31557576bb6c2dbe33d46e7fab0fa0889f58c4 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Tue, 18 Oct 2016 12:25:08 -0600 Subject: [PATCH 068/129] add packages from master --- package.json | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index cf328fe..bf97abe 100644 --- a/package.json +++ b/package.json @@ -39,17 +39,21 @@ "homepage": "https://github.com/Daplie/serve-https#readme", "dependencies": { "bluebird": "^3.4.6", + "ddns-cli": "git+https://github.com:Daplie/node-ddns-client.git#master", + "daplie-tunnel": "git+https://github.com:Daplie/daplie-cli-tunnel.git#master", "finalhandler": "^0.4.0", "httpolyglot": "^0.1.1", "ipify": "^1.1.0", - "le-challenge-dns": "^2.0.1", + "le-challenge-ddns": "^2.0.1", "le-challenge-fs": "^2.0.5", "letsencrypt-express": "^2.0.2", "livereload": "^0.6.0", "localhost.daplie.com-certificates": "^1.2.0", "minimist": "^1.1.1", + "oauth3-cli": "git+https://github.com:OAuth3/oauth3-cli.git#master", "redirect-https": "^1.1.0", "serve-index": "^1.7.0", - "serve-static": "^1.10.0" + "serve-static": "^1.10.0", + "stunnel": "git+https://github.com:Daplie/node-tunnel-client.git#master" } } From 89f26753bfa9b4e2712b4a1004d7f532e8ea48cb Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 19 Oct 2016 14:09:10 -0600 Subject: [PATCH 069/129] load oauth3 device by devicename --- lib/tunnel.js | 1 + serve.js | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/tunnel.js b/lib/tunnel.js index dc1010f..353e701 100644 --- a/lib/tunnel.js +++ b/lib/tunnel.js @@ -63,6 +63,7 @@ module.exports.create = function (opts, servers) { refreshToken: opts.refreshToken , email: opts.email , domains: [ opts.servername ] + , device: { hostname: opts.devicename || opts.device } }).then(function (result) { // { jwt, tunnelUrl } return stunnel.connect({ diff --git a/serve.js b/serve.js index f020692..236af8d 100755 --- a/serve.js +++ b/serve.js @@ -109,7 +109,7 @@ function createServer(port, pubdir, content, opts) { var webrootPath = require('os').tmpdir(); var leChallengeFs = require('le-challenge-fs').create({ webrootPath: webrootPath }); //var leChallengeSni = require('le-challenge-sni').create({ webrootPath: webrootPath }); - var leChallengeDns = require('le-challenge-dns').create({ ttl: 1 }); + var leChallengeDdns = require('le-challenge-ddns').create({ ttl: 1 }); var lex = require('letsencrypt-express').create({ // set to https://acme-v01.api.letsencrypt.org/directory in production server: opts.debug ? 'staging' : 'https://acme-v01.api.letsencrypt.org/directory' @@ -119,7 +119,7 @@ function createServer(port, pubdir, content, opts) { , challenges: { 'http-01': leChallengeFs , 'tls-sni-01': leChallengeFs // leChallengeSni - , 'dns-01': leChallengeDns + , 'dns-01': leChallengeDdns } , challengeType: (opts.tunnel ? 'http-01' : 'dns-01') , store: require('le-store-certbot').create({ webrootPath: webrootPath }) @@ -242,6 +242,7 @@ function run() { var opts = { agreeTos: argv.agreeTos || argv['agree-tos'] , debug: argv.debug + , device: argv.device , email: argv.email , httpsOptions: { key: httpsOptions.key From 92de847d2739fd9507c1937647216740500118ef Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 20 Oct 2016 15:02:47 -0600 Subject: [PATCH 070/129] add deps --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index bf97abe..1c73a87 100644 --- a/package.json +++ b/package.json @@ -39,13 +39,14 @@ "homepage": "https://github.com/Daplie/serve-https#readme", "dependencies": { "bluebird": "^3.4.6", - "ddns-cli": "git+https://github.com:Daplie/node-ddns-client.git#master", "daplie-tunnel": "git+https://github.com:Daplie/daplie-cli-tunnel.git#master", + "ddns-cli": "git+https://github.com:Daplie/node-ddns-client.git#master", "finalhandler": "^0.4.0", "httpolyglot": "^0.1.1", "ipify": "^1.1.0", "le-challenge-ddns": "^2.0.1", "le-challenge-fs": "^2.0.5", + "le-challenge-sni": "^2.0.1", "letsencrypt-express": "^2.0.2", "livereload": "^0.6.0", "localhost.daplie.com-certificates": "^1.2.0", From bc81ffa5161805d02f828bcedd3da21c1c5ada08 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 20 Oct 2016 15:04:14 -0600 Subject: [PATCH 071/129] version dump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1c73a87..98a1bfd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "2.0.0", + "version": "1.99.0", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "serve.js", "scripts": { From 4defabcc5aef9e528ee89c1a394efc198a42f974 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 20 Oct 2016 15:04:21 -0600 Subject: [PATCH 072/129] v2.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 98a1bfd..1c73a87 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "1.99.0", + "version": "2.0.0", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "serve.js", "scripts": { From c10ecad62d57c3a73ad7735611154f3d75debecd Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 20 Oct 2016 21:41:37 -0600 Subject: [PATCH 073/129] fix links --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 1c73a87..1667c9f 100644 --- a/package.json +++ b/package.json @@ -39,8 +39,8 @@ "homepage": "https://github.com/Daplie/serve-https#readme", "dependencies": { "bluebird": "^3.4.6", - "daplie-tunnel": "git+https://github.com:Daplie/daplie-cli-tunnel.git#master", - "ddns-cli": "git+https://github.com:Daplie/node-ddns-client.git#master", + "daplie-tunnel": "git+https://github.com/Daplie/daplie-cli-tunnel.git#master", + "ddns-cli": "git+https://github.com/Daplie/node-ddns-client.git#master", "finalhandler": "^0.4.0", "httpolyglot": "^0.1.1", "ipify": "^1.1.0", @@ -51,10 +51,10 @@ "livereload": "^0.6.0", "localhost.daplie.com-certificates": "^1.2.0", "minimist": "^1.1.1", - "oauth3-cli": "git+https://github.com:OAuth3/oauth3-cli.git#master", + "oauth3-cli": "git+https://github.com/OAuth3/oauth3-cli.git#master", "redirect-https": "^1.1.0", "serve-index": "^1.7.0", "serve-static": "^1.10.0", - "stunnel": "git+https://github.com:Daplie/node-tunnel-client.git#master" + "stunnel": "git+https://github.com/Daplie/node-tunnel-client.git#master" } } From 23687056c252c79c50745aacf706bbce5e7c0afc Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 20 Oct 2016 21:41:45 -0600 Subject: [PATCH 074/129] v2.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1667c9f..4d9930b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "2.0.0", + "version": "2.0.1", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "serve.js", "scripts": { From 1dc22cfafcae4e979fb1c2a0c7fcd8ca735e8ec1 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 20 Oct 2016 22:25:31 -0600 Subject: [PATCH 075/129] use git repos for packages --- package.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 4d9930b..778cc79 100644 --- a/package.json +++ b/package.json @@ -44,10 +44,11 @@ "finalhandler": "^0.4.0", "httpolyglot": "^0.1.1", "ipify": "^1.1.0", - "le-challenge-ddns": "^2.0.1", - "le-challenge-fs": "^2.0.5", + "le-challenge-ddns": "git+https://github.com/Daplie/le-challenge-ddns.git#master", + "le-challenge-fs": "git+https://github.com/Daplie/le-challenge-fs.git#master", "le-challenge-sni": "^2.0.1", - "letsencrypt-express": "^2.0.2", + "letsencrypt-express": "git+https://github.com/Daplie/letsencrypt-express.git#master", + "letsencrypt": "git+https://github.com/Daplie/node-letsencrypt.git#master", "livereload": "^0.6.0", "localhost.daplie.com-certificates": "^1.2.0", "minimist": "^1.1.1", From e66d04d6ee5dd12b007b2e3423e4f6adca04203a Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 20 Oct 2016 22:25:39 -0600 Subject: [PATCH 076/129] v2.0.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 778cc79..695eb1a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "2.0.1", + "version": "2.0.2", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "serve.js", "scripts": { From 1cbe94b6103310ff20aa3506265c546c55827f0a Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 20 Oct 2016 22:33:53 -0600 Subject: [PATCH 077/129] move file location --- serve.js => bin/serve-https.js | 0 package.json | 6 +++--- 2 files changed, 3 insertions(+), 3 deletions(-) rename serve.js => bin/serve-https.js (100%) diff --git a/serve.js b/bin/serve-https.js similarity index 100% rename from serve.js rename to bin/serve-https.js diff --git a/package.json b/package.json index 0d1dcc4..862c54d 100644 --- a/package.json +++ b/package.json @@ -2,12 +2,12 @@ "name": "serve-https", "version": "1.6.1", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", - "main": "serve.js", + "main": "bin/serve-https.js", "scripts": { - "test": "node serve.js -p 1443 -d /tmp/" + "test": "node bin/serve-https.js -p 8443 -d /tmp/" }, "bin": { - "serve-https": "serve.js" + "serve-https": "./bin/serve-https.js" }, "repository": { "type": "git", From 945ce26b39ed36b78dd1c1644b10ca69aa47752a Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 20 Oct 2016 22:42:12 -0600 Subject: [PATCH 078/129] v2.0.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6e594c2..307fe62 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "2.0.2", + "version": "2.0.3", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "bin/serve-https.js", "scripts": { From 05ebdfab983a573798d0f668db031adb04ea0470 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 26 Oct 2016 22:41:26 -0600 Subject: [PATCH 079/129] fix paths --- bin/serve-https.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/bin/serve-https.js b/bin/serve-https.js index 236af8d..15f0d1b 100755 --- a/bin/serve-https.js +++ b/bin/serve-https.js @@ -92,7 +92,7 @@ function createServer(port, pubdir, content, opts) { } return new PromiseA(function (realResolve) { - var app = require('./lib/app.js'); + var app = require('../lib/app.js'); var directive = { public: pubdir, content: content, livereload: opts.livereload , servername: opts.servername, expressApp: opts.expressApp }; @@ -231,7 +231,7 @@ function run() { if (argv.v) { console.warn("flag -v is reserved for future use. Use -V or --version for version information."); } - console.info('v' + require('./package.json').version); + console.info('v' + require('../package.json').version); return; } @@ -399,12 +399,12 @@ function run() { if (!(argv.servername && defaultServername !== argv.servername && !(argv.key && argv.cert))) { // ifaces - opts.ifaces = require('./lib/local-ip.js').find(); + opts.ifaces = require('../lib/local-ip.js').find(); promise = PromiseA.resolve(); } else { console.info("Attempting to resolve external connection for '" + argv.servername + "'"); try { - promise = require('./lib/match-ips.js').match(argv.servername, opts); + promise = require('../lib/match-ips.js').match(argv.servername, opts); } catch(e) { console.warn("Upgrade to version 2.x to use automatic certificate issuance for '" + argv.servername + "'"); promise = PromiseA.resolve(); @@ -446,10 +446,10 @@ function run() { } if (opts.tunnel) { - require('./lib/tunnel.js').create(opts, servers); + require('../lib/tunnel.js').create(opts, servers); } else if (opts.ddns) { - require('./lib/ddns.js').create(opts, servers); + require('../lib/ddns.js').create(opts, servers); } Object.keys(opts.ifaces).forEach(function (iname) { From 65bc4ff9f6a631206d7e5edc603bff4cb9b1545f Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 26 Oct 2016 22:41:32 -0600 Subject: [PATCH 080/129] v2.0.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 307fe62..db5c129 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "2.0.3", + "version": "2.0.4", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "bin/serve-https.js", "scripts": { From 77c0fa3c7dc8398fdc02c9e14aae67eeb5a89df3 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 27 Oct 2016 02:07:15 -0600 Subject: [PATCH 081/129] pass homedir --- bin/serve-https.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bin/serve-https.js b/bin/serve-https.js index 15f0d1b..153cf55 100755 --- a/bin/serve-https.js +++ b/bin/serve-https.js @@ -249,6 +249,7 @@ function run() { , cert: httpsOptions.cert //, ca: httpsOptions.ca } + , homedir: argv.homedir , argv: argv }; var peerCa; @@ -351,6 +352,7 @@ function run() { p = DDNS.refreshToken({ email: opts.email , silent: true + , homedir: opts.homedir }, { debug: false , email: opts.argv.email From 24250f82d854cfd12ead3df9682276f46feb63d9 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 27 Oct 2016 02:20:32 -0600 Subject: [PATCH 082/129] run http on standard port 80 --- bin/serve-https.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/serve-https.js b/bin/serve-https.js index 153cf55..e2af24b 100755 --- a/bin/serve-https.js +++ b/bin/serve-https.js @@ -177,7 +177,7 @@ function createServer(port, pubdir, content, opts) { server2.watch(pubdir); } - if ('false' !== opts.insecurePort && httpPort !== opts.insecurePort) { + if ('false' !== opts.insecurePort && httpPort === opts.insecurePort) { return createInsecureServer(opts.insecurePort, pubdir, opts).then(function (_server) { insecureServer = _server; resolve(); From ed47fb80b53df01b7969f8f28569197a72e83f2c Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 27 Oct 2016 02:44:14 -0600 Subject: [PATCH 083/129] specifying insecurePort --- bin/serve-https.js | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/bin/serve-https.js b/bin/serve-https.js index e2af24b..21ae6b1 100755 --- a/bin/serve-https.js +++ b/bin/serve-https.js @@ -177,15 +177,23 @@ function createServer(port, pubdir, content, opts) { server2.watch(pubdir); } - if ('false' !== opts.insecurePort && httpPort === opts.insecurePort) { - return createInsecureServer(opts.insecurePort, pubdir, opts).then(function (_server) { - insecureServer = _server; - resolve(); - }); - } else { - opts.insecurePort = opts.port; - resolve(); + // if we haven't disabled insecure port + if ('false' === opts.insecurePort) { + // and both ports are the default + if ((httpsPort === opts.port && httpPort === opts.insecurePort) + // or other case + || (httpPort !== opts.insecurePort && opts.port !== opts.insecurePort) + ) { + return createInsecureServer(opts.insecurePort, pubdir, opts).then(function (_server) { + insecureServer = _server; + resolve(); + }); + } } + + opts.insecurePort = opts.port; + resolve(); + return; }); if ('function' === typeof app) { From a9b7f5594129e4563639e2c6091542d8f971fd59 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 27 Oct 2016 02:45:08 -0600 Subject: [PATCH 084/129] fix typo --- bin/serve-https.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/serve-https.js b/bin/serve-https.js index 21ae6b1..3d50308 100755 --- a/bin/serve-https.js +++ b/bin/serve-https.js @@ -178,7 +178,7 @@ function createServer(port, pubdir, content, opts) { } // if we haven't disabled insecure port - if ('false' === opts.insecurePort) { + if ('false' !== opts.insecurePort) { // and both ports are the default if ((httpsPort === opts.port && httpPort === opts.insecurePort) // or other case From 795f2a7edc832ff9ea873ba74ffaec3e9b804e85 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 27 Oct 2016 02:47:11 -0600 Subject: [PATCH 085/129] don't output default port --- bin/serve-https.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/serve-https.js b/bin/serve-https.js index 3d50308..73c24ec 100755 --- a/bin/serve-https.js +++ b/bin/serve-https.js @@ -399,7 +399,7 @@ function run() { console.info('\t' + httpsUrl); // Insecure Port - p = ''; + p = opts.insecurePort; if (httpPort !== p) { p = ':' + opts.insecurePort; } From 6ab2ea752745bc41db73fde4aac0b9719bc3caa8 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 27 Oct 2016 02:53:49 -0600 Subject: [PATCH 086/129] more --- bin/serve-https.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/bin/serve-https.js b/bin/serve-https.js index 73c24ec..a83a879 100755 --- a/bin/serve-https.js +++ b/bin/serve-https.js @@ -381,30 +381,30 @@ function run() { opts.redirectApp = require('redirect-https')(opts.redirectOptions); return createServer(port, pubdir, content, opts).then(function (servers) { - var msg; var p; var httpsUrl; + var httpUrl; var promise; + console.info(''); + console.info('Serving ' + pubdir + ' at '); + console.info(''); + // Port - msg = 'Serving ' + pubdir + ' at '; httpsUrl = 'https://' + opts.servername; p = opts.port; if (httpsPort !== p) { httpsUrl += ':' + p; } - console.info(''); - console.info(msg); - console.info(''); console.info('\t' + httpsUrl); // Insecure Port + httpUrl = 'http://' + opts.servername; p = opts.insecurePort; if (httpPort !== p) { - p = ':' + opts.insecurePort; + httpUrl += ':' + p; } - msg = '\thttp://' + opts.servername + p + ' (redirecting to https)'; - console.info(msg); + console.info('\t' + httpUrl + ' (redirecting to https)'); console.info(''); if (!(argv.servername && defaultServername !== argv.servername && !(argv.key && argv.cert))) { From 39e6754b1f49df8d452a471bcf1a9e2ce4360d5d Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 27 Oct 2016 02:57:18 -0600 Subject: [PATCH 087/129] pass homedir --- bin/serve-https.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/serve-https.js b/bin/serve-https.js index a83a879..44f4120 100755 --- a/bin/serve-https.js +++ b/bin/serve-https.js @@ -122,7 +122,7 @@ function createServer(port, pubdir, content, opts) { , 'dns-01': leChallengeDdns } , challengeType: (opts.tunnel ? 'http-01' : 'dns-01') - , store: require('le-store-certbot').create({ webrootPath: webrootPath }) + , store: require('le-store-certbot').create({ webrootPath: webrootPath, homedir: opts.homedir }) , webrootPath: webrootPath // You probably wouldn't need to replace the default sni handler From dedb59e4133563a655d9823988f5da66acb24b37 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 27 Oct 2016 03:00:40 -0600 Subject: [PATCH 088/129] pass homedir --- bin/serve-https.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bin/serve-https.js b/bin/serve-https.js index 44f4120..dd665ff 100755 --- a/bin/serve-https.js +++ b/bin/serve-https.js @@ -122,7 +122,11 @@ function createServer(port, pubdir, content, opts) { , 'dns-01': leChallengeDdns } , challengeType: (opts.tunnel ? 'http-01' : 'dns-01') - , store: require('le-store-certbot').create({ webrootPath: webrootPath, homedir: opts.homedir }) + , store: require('le-store-certbot').create({ + webrootPath: webrootPath + , configDir: path.join((opts.homedir || '~'), 'letsencrypt', 'etc') + , homedir: opts.homedir + }) , webrootPath: webrootPath // You probably wouldn't need to replace the default sni handler From 5d9bb2389928ec349f2bfa291e718bbaf1901a41 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 27 Oct 2016 14:46:38 -0600 Subject: [PATCH 089/129] v2.0.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index db5c129..107f626 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "2.0.4", + "version": "2.0.5", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "bin/serve-https.js", "scripts": { From cb5984210fa284bffcf6da4122ceab178f23c3fa Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 25 Nov 2016 10:20:39 -0700 Subject: [PATCH 090/129] Update README.md --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index fd66ae9..c9789f6 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,13 @@ +Daplie is Taking Back the Internet! +-------------- + +[![](https://daplie.github.com/igg/images/ad-developer-rpi-white-890x275.jpg?v2)](https://daplie.com/preorder/) + +Stop serving the empire and join the rebel alliance! + +* [Invest in Daplie on Wefunder](https://daplie.com/invest/) +* [Pre-order Cloud](https://daplie.com/preorder/), The World's First Home Server for Everyone + serve-https =========== From c63379c02f9c387eb24fcdeaa836bfdaa3aa6c96 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 30 Dec 2016 00:53:29 -0700 Subject: [PATCH 091/129] auto-update ad --- README.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c9789f6..85db3c0 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,17 @@ -Daplie is Taking Back the Internet! + + +About Daplie: We're taking back the Internet! -------------- -[![](https://daplie.github.com/igg/images/ad-developer-rpi-white-890x275.jpg?v2)](https://daplie.com/preorder/) +Down with Google, Apple, and Facebook! -Stop serving the empire and join the rebel alliance! +We're re-decentralizing the web and making it read-write again - one home cloud system at a time. -* [Invest in Daplie on Wefunder](https://daplie.com/invest/) -* [Pre-order Cloud](https://daplie.com/preorder/), The World's First Home Server for Everyone +Tired of serving the Empire? Come join the Rebel Alliance: + +jobs@daplie.com | [Invest in Daplie on Wefunder](https://daplie.com/invest/) | [Pre-order Cloud](https://daplie.com/preorder/), The World's First Home Server for Everyone + + serve-https =========== From 735c6615a739fbc3cd5652e6733cfe099cb9d721 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 30 Dec 2016 02:41:04 -0700 Subject: [PATCH 092/129] auto-update banner --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 85db3c0..cb6aa53 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ - + About Daplie: We're taking back the Internet! -------------- @@ -11,7 +11,7 @@ Tired of serving the Empire? Come join the Rebel Alliance: jobs@daplie.com | [Invest in Daplie on Wefunder](https://daplie.com/invest/) | [Pre-order Cloud](https://daplie.com/preorder/), The World's First Home Server for Everyone - + serve-https =========== From 0810e23511771f8b1d7a91350c821dde5b6ef629 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Sat, 7 Jan 2017 23:43:45 +0000 Subject: [PATCH 093/129] Update README.md --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cb6aa53..4d27d51 100644 --- a/README.md +++ b/README.md @@ -27,11 +27,14 @@ Install ------- ```bash -npm install --global serve-https +npm install --global serve-https@1.x +``` + +```bash serve-https ``` -``` +```bash Serving /Users/foo/ at https://localhost.daplie.com:8443 ``` From 2cbb41c3741a3565cc03a7d1d1373188e7c91b4d Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Sat, 7 Jan 2017 23:46:08 +0000 Subject: [PATCH 094/129] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 4d27d51..b9b2d3f 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,8 @@ Serving /Users/foo/ at https://localhost.daplie.com:8443 Usage ----- +**Note**: these examples show features of version 2.x which is currently blocked by a bug. + Examples: ``` From 20d86154c0835a0fb81035cdfbbac10ef1710cf5 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Sat, 7 Jan 2017 23:46:54 +0000 Subject: [PATCH 095/129] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b9b2d3f..1b2bdfb 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Serving /Users/foo/ at https://localhost.daplie.com:8443 Usage ----- -**Note**: these examples show features of version 2.x which is currently blocked by a bug. +**Note**: these examples also show features of version 2.x which is currently blocked by a bug. Examples: From 07cffcf598762b1cbf4093583d2ed5501d6ca3d4 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Sat, 7 Jan 2017 17:14:02 -0700 Subject: [PATCH 096/129] update dependencies --- package.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 107f626..028d708 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/Daplie/serve-https.git" + "url": "git+https://git.daplie.com/Daplie/serve-https.git" }, "keywords": [ "https", @@ -34,28 +34,28 @@ "author": "AJ ONeal (https://coolaj86.com/)", "license": "Apache-2.0", "bugs": { - "url": "https://github.com/Daplie/server-https/issues" + "url": "https://git.daplie.com/Daplie/server-https/issues" }, - "homepage": "https://github.com/Daplie/serve-https#readme", + "homepage": "https://git.daplie.com/Daplie/serve-https#readme", "dependencies": { "bluebird": "^3.4.6", - "daplie-tunnel": "git+https://github.com/Daplie/daplie-cli-tunnel.git#master", - "ddns-cli": "git+https://github.com/Daplie/node-ddns-client.git#master", + "daplie-tunnel": "git+https://git.daplie.com/Daplie/daplie-cli-tunnel.git#master", + "ddns-cli": "git+https://git.daplie.com/Daplie/node-ddns-client.git#master", "finalhandler": "^0.4.0", "httpolyglot": "^0.1.1", "ipify": "^1.1.0", - "le-challenge-ddns": "git+https://github.com/Daplie/le-challenge-ddns.git#master", - "le-challenge-fs": "git+https://github.com/Daplie/le-challenge-fs.git#master", + "le-challenge-ddns": "git+https://git.daplie.com/Daplie/le-challenge-ddns.git#master", + "le-challenge-fs": "git+https://git.daplie.com/Daplie/le-challenge-fs.git#master", "le-challenge-sni": "^2.0.1", - "letsencrypt-express": "git+https://github.com/Daplie/letsencrypt-express.git#master", - "letsencrypt": "git+https://github.com/Daplie/node-letsencrypt.git#master", + "greenlock-express": "git+https://git.daplie.com/Daplie/greenlock-express.git#master", + "greenlock": "git+https://git.daplie.com/Daplie/node-greenlock.git#master", "livereload": "^0.6.0", "localhost.daplie.com-certificates": "^1.2.0", "minimist": "^1.1.1", - "oauth3-cli": "git+https://github.com/OAuth3/oauth3-cli.git#master", + "oauth3-cli": "git+https://git.daplie.com/OAuth3/oauth3-cli.git#master", "redirect-https": "^1.1.0", "serve-index": "^1.7.0", "serve-static": "^1.10.0", - "stunnel": "git+https://github.com/Daplie/node-tunnel-client.git#master" + "stunnel": "git+https://git.daplie.com/Daplie/node-tunnel-client.git#master" } } From 3f9c0b7b0c964f1e9f063136b5a3171bd639d31a Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Sat, 7 Jan 2017 17:21:12 -0700 Subject: [PATCH 097/129] how to install from git --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 1b2bdfb..710bf04 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,17 @@ Install ------- ```bash +# v2.x +npm install --global serve-https@2.x + +# v1.x npm install --global serve-https@1.x + +# master in git (via ssh) +npm install -g git+ssh://git@git.daplie.com:Daplie/serve-https + +# master in git (unauthenticated) +npm install -g git+https://git@git.daplie.com:Daplie/serve-https ``` ```bash From 9098c9b0d3be876507c59358037cab1984d5b51c Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Sat, 7 Jan 2017 17:26:22 -0700 Subject: [PATCH 098/129] le-challenge-fs -> le-challenge-webroot --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 028d708..9d3d7fd 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "httpolyglot": "^0.1.1", "ipify": "^1.1.0", "le-challenge-ddns": "git+https://git.daplie.com/Daplie/le-challenge-ddns.git#master", - "le-challenge-fs": "git+https://git.daplie.com/Daplie/le-challenge-fs.git#master", + "le-challenge-fs": "git+https://git.daplie.com/Daplie/le-challenge-webroot.git#master", "le-challenge-sni": "^2.0.1", "greenlock-express": "git+https://git.daplie.com/Daplie/greenlock-express.git#master", "greenlock": "git+https://git.daplie.com/Daplie/node-greenlock.git#master", From 2f04da9bc2ac029772e98dc5b15ac2835afe049d Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Sat, 7 Jan 2017 17:54:56 -0700 Subject: [PATCH 099/129] at minimum return raw ws --- lib/tunnel.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/tunnel.js b/lib/tunnel.js index 353e701..2bc135a 100644 --- a/lib/tunnel.js +++ b/lib/tunnel.js @@ -7,8 +7,9 @@ module.exports.create = function (opts, servers) { Oauth3: Oauth3 , PromiseA: opts.PromiseA , CLI: { - init: function (/*rs, ws, state, options*/) { + init: function (rs, ws/*, state, options*/) { // noop + return ws; } } }).Tunnel; From ecb73d58e2147dccfad65dedbaf60a39412d4ace Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Tue, 10 Jan 2017 10:30:42 -0700 Subject: [PATCH 100/129] v2.0.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9d3d7fd..c2abdf5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "2.0.5", + "version": "2.0.6", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "bin/serve-https.js", "scripts": { From 9f48cc57802ae6ffc20f423d02bf5864636c873a Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Tue, 10 Jan 2017 18:24:54 -0700 Subject: [PATCH 101/129] pass oauth3 provider --- bin/serve-https.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bin/serve-https.js b/bin/serve-https.js index dd665ff..ab42faf 100755 --- a/bin/serve-https.js +++ b/bin/serve-https.js @@ -255,6 +255,7 @@ function run() { agreeTos: argv.agreeTos || argv['agree-tos'] , debug: argv.debug , device: argv.device + , provider: (argv.provider && 'false' !== argv.provider) ? argv.provider : 'oauth3.org' , email: argv.email , httpsOptions: { key: httpsOptions.key @@ -363,6 +364,7 @@ function run() { } p = DDNS.refreshToken({ email: opts.email + , providerUrl: opts.provider , silent: true , homedir: opts.homedir }, { From cee067bcaf7dafc22a39ba01f89bc46ee972bfaa Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Tue, 10 Jan 2017 18:25:11 -0700 Subject: [PATCH 102/129] v2.0.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c2abdf5..2d1a92f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "2.0.6", + "version": "2.0.7", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "bin/serve-https.js", "scripts": { From 6fa035df981407ea7cd13493a96210ae471fc65f Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 12 Jan 2017 11:16:50 -0700 Subject: [PATCH 103/129] v2.x works again --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 710bf04..53d94e8 100644 --- a/README.md +++ b/README.md @@ -51,8 +51,6 @@ Serving /Users/foo/ at https://localhost.daplie.com:8443 Usage ----- -**Note**: these examples also show features of version 2.x which is currently blocked by a bug. - Examples: ``` From e91b00c5faa007832ba00fdab6c3a2d43684f781 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 20 Jan 2017 20:13:41 +0000 Subject: [PATCH 104/129] update example --- README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 53d94e8..01cd287 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,15 @@ Usage Examples: ``` -node serve.js --servername jane.daplie.me --agree-tos --email jane@example.com --tunnel +# Install +npm install -g git+https://git@git.daplie.com:Daplie/serve-https + +# Use tunnel +serve-https --servername jane.daplie.me --agree-tos --email jane@example.com --tunnel + +# BEFORE you access in a browser for the first time, use curl +# (because there's a concurrency bug in the greenlock setup) +curl https://jane.daplie.me ``` Options: From 6242a48fd0a0f7066e4d1ab3749254d5dacf8e99 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 20 Jan 2017 14:27:23 -0700 Subject: [PATCH 105/129] v2.0.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2d1a92f..1691187 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "2.0.7", + "version": "2.0.8", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", "main": "bin/serve-https.js", "scripts": { From 5654ef3fe22493b06e022366fd6c5d129bb2317f Mon Sep 17 00:00:00 2001 From: Thomas Ingram Date: Fri, 20 Jan 2017 17:47:50 -0500 Subject: [PATCH 106/129] Typo fix --- bin/serve-https.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/serve-https.js b/bin/serve-https.js index ab42faf..cde8fca 100755 --- a/bin/serve-https.js +++ b/bin/serve-https.js @@ -23,7 +23,7 @@ function showError(err, port) { } else if ('EADDRINUSE' === err.code) { console.warn("Another server is already running on '" + port + "'."); - console.warn("You can probably fix that by rebooting your comupter (or stopping it if you know what it is)."); + console.warn("You can probably fix that by rebooting your computer (or stopping it if you know what it is)."); } } From 8c67ef5702f3f8d9a47f37a36013b05cb467ebab Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Tue, 31 Jan 2017 20:31:57 -0700 Subject: [PATCH 107/129] WIP handle multiple servers --- bin/serve-https.js | 48 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/bin/serve-https.js b/bin/serve-https.js index cde8fca..76592b5 100755 --- a/bin/serve-https.js +++ b/bin/serve-https.js @@ -95,7 +95,9 @@ function createServer(port, pubdir, content, opts) { var app = require('../lib/app.js'); var directive = { public: pubdir, content: content, livereload: opts.livereload - , servername: opts.servername, expressApp: opts.expressApp }; + , servername: opts.servername + , servers: opts.servers + , expressApp: opts.expressApp }; var insecureServer; function resolve() { @@ -135,18 +137,35 @@ function createServer(port, pubdir, content, opts) { , approveDomains: approveDomains }); - var secureContext; + + var secureContexts = { + 'localhost.daplie.me': null + , 'localhost.daplie.com': null + }; opts.httpsOptions.SNICallback = function (servername, cb ) { console.log('[https] servername', servername); + // Deprecated Static Certs if ('localhost.daplie.com' === servername) { - if (!secureContext) { - secureContext = tls.createSecureContext(opts.httpsOptions); + // TODO deprecate + if (!secureContexts[servername]) { + secureContexts[servername] = tls.createSecureContext(require('localhost.daplie.com-certificates').merge({})); } - cb(null, secureContext); + cb(null, secureContexts[servername]); return; } + // Static Certs + if ('localhost.daplie.me' === servername) { + // TODO implement + if (!secureContexts[servername]) { + secureContexts[servername] = tls.createSecureContext(require('localhost.daplie.me-certificates').merge({})); + } + cb(null, secureContexts[servername]); + return; + } + + // Dynamic Certs lex.httpsOptions.SNICallback(servername, cb); }; var server = https.createServer(opts.httpsOptions); @@ -230,6 +249,7 @@ function createServer(port, pubdir, content, opts) { module.exports.createServer = createServer; function run() { + // TODO switch to localhost.daplie.me var defaultServername = 'localhost.daplie.com'; var minimist = require('minimist'); var argv = minimist(process.argv.slice(2)); @@ -282,6 +302,7 @@ function run() { argv.cert = argv.cert || '/etc/letsencrypt/live/' + letsencryptHost + '/fullchain.pem'; argv.root = argv.root || argv.chain || ''; argv.servername = argv.servername || letsencryptHost; + argv.servers = argv.servers || [ { name: argv.servername || letsencryptHost , path: '.' } ]; argv['serve-root'] = argv['serve-root'] || argv['serve-chain']; // argv[express-app] } @@ -331,10 +352,27 @@ function run() { } } + opts.servername = defaultServername; + opts.servers = [ { name: defaultServername , path: '.' } ]; + if (argv.servername) { opts.servername = argv.servername; + if (!argv.servers) { + opts.servers = [ { name: argv.servername, path: '.' } ]; + } } + if (argv.servers) { + opts.servers = argv.servers.split(',').map(function (servername) { + var serverparts = servername.split('|'); + // TODO allow reverse proxy + return { + name: serverparts.shift() + , paths: serverparts + }; + }); + } + if (argv.p || argv.port || argv._[0]) { opts.manualPort = true; } From b9662e3deb9a4c2d19ff7c402deddcde873e3e91 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 1 Feb 2017 15:47:08 -0700 Subject: [PATCH 108/129] add --sites option for multiple domains #10 and use localhost.daplie.me --- README.md | 14 ++++---- bin/serve-https.js | 32 ++++++------------- lib/app.js | 80 +++++++++++++++++++++++++++++++++++++--------- package.json | 4 +-- stages/01-serve.js | 4 +-- test-chain.sh | 13 ++++---- 6 files changed, 92 insertions(+), 55 deletions(-) diff --git a/README.md b/README.md index 01cd287..4fc13ce 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ serve-https A simple HTTPS static file server with valid TLS (SSL) certs. -Comes bundled a valid certificate for localhost.daplie.com, +Comes bundled a valid certificate for localhost.daplie.me, which is great for testing and development, and you can specify your own. Also great for testing ACME certs from letsencrypt.org. @@ -45,7 +45,7 @@ serve-https ``` ```bash -Serving /Users/foo/ at https://localhost.daplie.com:8443 +Serving /Users/foo/ at https://localhost.daplie.me:8443 ``` Usage @@ -75,7 +75,7 @@ Options: * `--email ` - email to use for Let's Encrypt, Daplie DNS, Daplie Tunnel * `--agree-tos` - agree to terms for Let's Encrypt, Daplie DNS -* `--servername ` - use `` instead of `localhost.daplie.com` +* `--servername ` - use `` instead of `localhost.daplie.me` * `--tunnel` - make world-visible (must use `--servername`) Specifying a custom HTTPS certificate: @@ -104,18 +104,18 @@ serve-https -p 1443 -c 'Hello from 1443' & serve-https -p 2443 -c 'Hello from 2443' & serve-https -p 3443 -d /tmp & -curl https://localhost.daplie.com:1443 +curl https://localhost.daplie.me:1443 > Hello from 1443 curl --insecure https://localhost:2443 > Hello from 2443 -curl https://localhost.daplie.com:3443 +curl https://localhost.daplie.me:3443 > [html index listing of /tmp] ``` -And if you tested in a browser, -it would redirect to (on the same port). +And if you tested in a browser, +it would redirect to (on the same port). (in curl it would just show an error message) diff --git a/bin/serve-https.js b/bin/serve-https.js index 76592b5..494a9d6 100755 --- a/bin/serve-https.js +++ b/bin/serve-https.js @@ -96,7 +96,7 @@ function createServer(port, pubdir, content, opts) { var directive = { public: pubdir, content: content, livereload: opts.livereload , servername: opts.servername - , servers: opts.servers + , sites: opts.sites , expressApp: opts.expressApp }; var insecureServer; @@ -132,7 +132,7 @@ function createServer(port, pubdir, content, opts) { , webrootPath: webrootPath // You probably wouldn't need to replace the default sni handler - // See https://github.com/Daplie/le-sni-auto if you think you do + // See https://git.daplie.com/Daplie/le-sni-auto if you think you do //, sni: require('le-sni-auto').create({}) , approveDomains: approveDomains @@ -140,21 +140,10 @@ function createServer(port, pubdir, content, opts) { var secureContexts = { 'localhost.daplie.me': null - , 'localhost.daplie.com': null }; opts.httpsOptions.SNICallback = function (servername, cb ) { console.log('[https] servername', servername); - // Deprecated Static Certs - if ('localhost.daplie.com' === servername) { - // TODO deprecate - if (!secureContexts[servername]) { - secureContexts[servername] = tls.createSecureContext(require('localhost.daplie.com-certificates').merge({})); - } - cb(null, secureContexts[servername]); - return; - } - // Static Certs if ('localhost.daplie.me' === servername) { // TODO implement @@ -249,8 +238,7 @@ function createServer(port, pubdir, content, opts) { module.exports.createServer = createServer; function run() { - // TODO switch to localhost.daplie.me - var defaultServername = 'localhost.daplie.com'; + var defaultServername = 'localhost.daplie.me'; var minimist = require('minimist'); var argv = minimist(process.argv.slice(2)); var port = parseInt(argv.p || argv.port || argv._[0], 10) || httpsPort; @@ -268,7 +256,7 @@ function run() { } // letsencrypt - var httpsOptions = require('localhost.daplie.com-certificates').merge({}); + var httpsOptions = require('localhost.daplie.me-certificates').merge({}); var secureContext; var opts = { @@ -302,7 +290,7 @@ function run() { argv.cert = argv.cert || '/etc/letsencrypt/live/' + letsencryptHost + '/fullchain.pem'; argv.root = argv.root || argv.chain || ''; argv.servername = argv.servername || letsencryptHost; - argv.servers = argv.servers || [ { name: argv.servername || letsencryptHost , path: '.' } ]; + argv.sites = argv.sites || [ { name: argv.servername || letsencryptHost , path: '.' } ]; argv['serve-root'] = argv['serve-root'] || argv['serve-chain']; // argv[express-app] } @@ -354,16 +342,16 @@ function run() { opts.servername = defaultServername; - opts.servers = [ { name: defaultServername , path: '.' } ]; + opts.sites = [ { name: defaultServername , path: '.' } ]; if (argv.servername) { opts.servername = argv.servername; - if (!argv.servers) { - opts.servers = [ { name: argv.servername, path: '.' } ]; + if (!argv.sites) { + opts.sites = [ { name: argv.servername, path: '.' } ]; } } - if (argv.servers) { - opts.servers = argv.servers.split(',').map(function (servername) { + if (argv.sites) { + opts.sites = argv.sites.split(',').map(function (servername) { var serverparts = servername.split('|'); // TODO allow reverse proxy return { diff --git a/lib/app.js b/lib/app.js index db54571..316d5dd 100644 --- a/lib/app.js +++ b/lib/app.js @@ -4,9 +4,47 @@ module.exports = function (opts) { var finalhandler = require('finalhandler'); var serveStatic = require('serve-static'); var serveIndex = require('serve-index'); - var serve = serveStatic(opts.public); - var index = serveIndex(opts.public); + + var hostsMap = {}; + var pathsMap = {}; var content = opts.content; + var server; + + function addServer(hostname) { + console.log('add server:', hostname); + + if (hostsMap[hostname]) { + return hostsMap[hostname]; + } + + var tmp = { }; + + opts.sites.forEach(function (site) { + if (hostname !== site.name) { + return; + } + + console.log('add server for reals', tmp); + + site.path = site.path || site.paths[0] || '.'; + + if (!pathsMap[site.path]) { + pathsMap[site.path] = { + serve: serveStatic(site.path) + // TODO option for dotfiles + , index: serveIndex(site.path) + }; + } + + hostsMap[hostname] = { + serve: pathsMap[site.path].serve + , index: pathsMap[site.path].index + , app: site.app + }; + + }); + + } function _reloadWrite(data, enc, cb) { /*jshint validthis: true */ @@ -28,6 +66,11 @@ module.exports = function (opts) { this.__write(data, enc, cb); } + + opts.servername = opts.servername || opts.sites[0].name; + + addServer(opts.sites[0].name); + return function (req, res) { if (content && '/' === req.url) { // res.setHeader('Content-Type', 'application/octet-stream'); @@ -35,10 +78,24 @@ module.exports = function (opts) { return; } var done = finalhandler(req, res); + var host = req.headers.host; + var hostname = (host||'').split(':')[0] || opts.servername; + + function serveStatic(server) { + if (server.expressApp) { + server.expressApp(req, res, serveStatic); + return; + } + + server.serve(req, res, function (err) { + if (err) { return done(err); } + server.index(req, res, done); + }); + } if (opts.livereload) { res.__my_livereload = ''; res.__my_addLen = res.__my_livereload.length; @@ -47,18 +104,11 @@ module.exports = function (opts) { res.write = _reloadWrite; } - function serveStatic() { - serve(req, res, function (err) { - if (err) { return done(err); } - index(req, res, done); - }); - } + console.log('hostname:', hostname); + + addServer(hostname); + server = hostsMap[hostname] || hostsMap[opts.sites[0].name]; + serveStatic(server); - if (opts.expressApp) { - opts.expressApp(req, res, serveStatic); - } - else { - serveStatic(); - } }; }; diff --git a/package.json b/package.json index 1691187..a8690a3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "serve-https", "version": "2.0.8", - "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.com - great for testing and development.", + "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.me - great for testing and development.", "main": "bin/serve-https.js", "scripts": { "test": "node bin/serve-https.js -p 8443 -d /tmp/" @@ -50,7 +50,7 @@ "greenlock-express": "git+https://git.daplie.com/Daplie/greenlock-express.git#master", "greenlock": "git+https://git.daplie.com/Daplie/node-greenlock.git#master", "livereload": "^0.6.0", - "localhost.daplie.com-certificates": "^1.2.0", + "localhost.daplie.me-certificates": "^1.2.0", "minimist": "^1.1.1", "oauth3-cli": "git+https://git.daplie.com/OAuth3/oauth3-cli.git#master", "redirect-https": "^1.1.0", diff --git a/stages/01-serve.js b/stages/01-serve.js index ebb483d..8f92791 100644 --- a/stages/01-serve.js +++ b/stages/01-serve.js @@ -1,7 +1,7 @@ 'use strict'; var https = require('httpolyglot'); -var httpsOptions = require('localhost.daplie.com-certificates').merge({}); +var httpsOptions = require('localhost.daplie.me-certificates').merge({}); var httpsPort = 8443; var redirectApp = require('redirect-https')({ port: httpsPort @@ -19,5 +19,5 @@ server.on('request', function (req, res) { }); server.listen(httpsPort, function () { - console.log('https://' + 'localhost.daplie.com' + (443 === httpsPort ? ':' : ':' + httpsPort)); + console.log('https://' + 'localhost.daplie.me' + (443 === httpsPort ? ':' : ':' + httpsPort)); }); diff --git a/test-chain.sh b/test-chain.sh index a5fb322..396d286 100755 --- a/test-chain.sh +++ b/test-chain.sh @@ -2,17 +2,16 @@ node serve.js \ --port 8443 \ - --key node_modules/localhost.daplie.com-certificates/certs/server/my-server.key.pem \ - --cert node_modules/localhost.daplie.com-certificates/certs/server/my-server.crt.pem \ - --chain node_modules/localhost.daplie.com-certificates/certs/ca/intermediate.crt.pem \ - --chain node_modules/localhost.daplie.com-certificates/certs/ca/root.crt.pem \ - -c "$(cat node_modules/localhost.daplie.com-certificates/certs/ca/root.crt.pem)" & + --key node_modules/localhost.daplie.me-certificates/privkey.pem \ + --cert node_modules/localhost.daplie.me-certificates/fullchain.pem \ + --root node_modules/localhost.daplie.me-certificates/root.pem \ + -c "$(cat node_modules/localhost.daplie.me-certificates/root.pem)" & PID=$! sleep 1 -curl -s --insecure http://localhost.daplie.com:8443 > ./root.pem -curl -s https://localhost.daplie.com:8443 --cacert ./root.pem +curl -s --insecure http://localhost.daplie.me:8443 > ./root.pem +curl -s https://localhost.daplie.me:8443 --cacert ./root.pem rm ./root.pem kill $PID 2>/dev/null From f6f6232f0c845317234e9c3a8633287ac6834bce Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 1 Feb 2017 15:47:23 -0700 Subject: [PATCH 109/129] v2.1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a8690a3..3fc7450 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "2.0.8", + "version": "2.1.0", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.me - great for testing and development.", "main": "bin/serve-https.js", "scripts": { From 653f121192337e3b53fa41b90f2f33e65af0bf0a Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 1 Feb 2017 15:56:40 -0700 Subject: [PATCH 110/129] change --servername to --sites --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 4fc13ce..27ed2e5 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ Examples: npm install -g git+https://git@git.daplie.com:Daplie/serve-https # Use tunnel -serve-https --servername jane.daplie.me --agree-tos --email jane@example.com --tunnel +serve-https --sites jane.daplie.me --agree-tos --email jane@example.com --tunnel # BEFORE you access in a browser for the first time, use curl # (because there's a concurrency bug in the greenlock setup) @@ -75,8 +75,8 @@ Options: * `--email ` - email to use for Let's Encrypt, Daplie DNS, Daplie Tunnel * `--agree-tos` - agree to terms for Let's Encrypt, Daplie DNS -* `--servername ` - use `` instead of `localhost.daplie.me` -* `--tunnel` - make world-visible (must use `--servername`) +* `--sites ` - use `` instead of `localhost.daplie.me` +* `--tunnel` - make world-visible (must use `--sites`) Specifying a custom HTTPS certificate: @@ -93,7 +93,7 @@ Note: `--root` may specify single cert or a bundle, and may be used multiple tim Other options: * `--serve-root true` alias for `-c` with the contents of root.pem -* `--servername example.com` changes the servername logged to the console +* `--sites example.com` changes the servername logged to the console * `--letsencrypt-certs example.com` sets and key, fullchain, and root to standard letsencrypt locations Examples @@ -139,7 +139,7 @@ which is equilavent to ```bash sudo serve-https -p 8443 \ - --servername test.mooo.com + --sites test.mooo.com --key /etc/letsencrypt/live/test.mooo.com/privkey.pem \ --cert /etc/letsencrypt/live/test.mooo.com/fullchain.pem \ --root /etc/letsencrypt/live/test.mooo.com/root.pem \ From 8dd879cb539344b7fcc34c75cd335a9ba6a4600f Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 1 Feb 2017 15:56:49 -0700 Subject: [PATCH 111/129] v2.1.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3fc7450..6a212cc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "2.1.0", + "version": "2.1.1", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.me - great for testing and development.", "main": "bin/serve-https.js", "scripts": { From 094c5aed261e402dffcbb550471dd35beeb2b2ae Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 1 Feb 2017 18:27:28 -0700 Subject: [PATCH 112/129] should require greenlock-express, not letsencrypt-express --- bin/serve-https.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/serve-https.js b/bin/serve-https.js index 494a9d6..c69ce48 100755 --- a/bin/serve-https.js +++ b/bin/serve-https.js @@ -112,7 +112,7 @@ function createServer(port, pubdir, content, opts) { var leChallengeFs = require('le-challenge-fs').create({ webrootPath: webrootPath }); //var leChallengeSni = require('le-challenge-sni').create({ webrootPath: webrootPath }); var leChallengeDdns = require('le-challenge-ddns').create({ ttl: 1 }); - var lex = require('letsencrypt-express').create({ + var lex = require('greenlock-express').create({ // set to https://acme-v01.api.letsencrypt.org/directory in production server: opts.debug ? 'staging' : 'https://acme-v01.api.letsencrypt.org/directory' From dfd0c1a35599bf1154bcb1290fb19ccdb1870385 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 1 Feb 2017 18:27:56 -0700 Subject: [PATCH 113/129] v2.1.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3fc7450..6a212cc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "2.1.0", + "version": "2.1.1", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.me - great for testing and development.", "main": "bin/serve-https.js", "scripts": { From afdf0920cab7b8a18128cb4488f5c588c6ea602f Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 1 Feb 2017 18:29:27 -0700 Subject: [PATCH 114/129] v2.1.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6a212cc..bcbf9fa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "2.1.1", + "version": "2.1.2", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.me - great for testing and development.", "main": "bin/serve-https.js", "scripts": { From 929f555d733115e1c579f746cc07e38c3fa29ab0 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 1 Feb 2017 20:00:00 -0700 Subject: [PATCH 115/129] fix bug tunnel bug with --sites --- bin/serve-https.js | 52 +++++++++++++++++++++++----------------------- lib/app.js | 9 ++------ lib/ddns.js | 8 +++---- lib/tunnel.js | 28 +++++++++++++++---------- 4 files changed, 49 insertions(+), 48 deletions(-) diff --git a/bin/serve-https.js b/bin/serve-https.js index c69ce48..d8f482b 100755 --- a/bin/serve-https.js +++ b/bin/serve-https.js @@ -95,7 +95,6 @@ function createServer(port, pubdir, content, opts) { var app = require('../lib/app.js'); var directive = { public: pubdir, content: content, livereload: opts.livereload - , servername: opts.servername , sites: opts.sites , expressApp: opts.expressApp }; var insecureServer; @@ -141,21 +140,21 @@ function createServer(port, pubdir, content, opts) { var secureContexts = { 'localhost.daplie.me': null }; - opts.httpsOptions.SNICallback = function (servername, cb ) { - console.log('[https] servername', servername); + opts.httpsOptions.SNICallback = function (sni, cb ) { + console.log('[https] sni', sni); // Static Certs - if ('localhost.daplie.me' === servername) { + if ('localhost.daplie.me' === sni) { // TODO implement - if (!secureContexts[servername]) { - secureContexts[servername] = tls.createSecureContext(require('localhost.daplie.me-certificates').merge({})); + if (!secureContexts[sni]) { + secureContexts[sni] = tls.createSecureContext(require('localhost.daplie.me-certificates').merge({})); } - cb(null, secureContexts[servername]); + cb(null, secureContexts[sni]); return; } // Dynamic Certs - lex.httpsOptions.SNICallback(servername, cb); + lex.httpsOptions.SNICallback(sni, cb); }; var server = https.createServer(opts.httpsOptions); @@ -277,7 +276,7 @@ function run() { var p; opts.PromiseA = PromiseA; - opts.httpsOptions.SNICallback = function (servername, cb) { + opts.httpsOptions.SNICallback = function (sni, cb) { if (!secureContext) { secureContext = tls.createSecureContext(opts.httpsOptions); } @@ -286,11 +285,11 @@ function run() { }; if (letsencryptHost) { + // TODO remove in v3.x (aka goldilocks) argv.key = argv.key || '/etc/letsencrypt/live/' + letsencryptHost + '/privkey.pem'; argv.cert = argv.cert || '/etc/letsencrypt/live/' + letsencryptHost + '/fullchain.pem'; argv.root = argv.root || argv.chain || ''; - argv.servername = argv.servername || letsencryptHost; - argv.sites = argv.sites || [ { name: argv.servername || letsencryptHost , path: '.' } ]; + argv.sites = argv.sites || (argv.servername || letsencryptHost); argv['serve-root'] = argv['serve-root'] || argv['serve-chain']; // argv[express-app] } @@ -341,18 +340,17 @@ function run() { } - opts.servername = defaultServername; opts.sites = [ { name: defaultServername , path: '.' } ]; - if (argv.servername) { - opts.servername = argv.servername; - if (!argv.sites) { - opts.sites = [ { name: argv.servername, path: '.' } ]; + // TODO remove in v3.x (aka goldilocks) + if (argv.sites) { + throw new Error('specify only --sites, not --servername'); } + opts.sites = [ { name: argv.servername, path: '.' } ]; } if (argv.sites) { - opts.sites = argv.sites.split(',').map(function (servername) { - var serverparts = servername.split('|'); + opts.sites = argv.sites.split(',').map(function (name) { + var serverparts = name.split('|'); // TODO allow reverse proxy return { name: serverparts.shift() @@ -360,6 +358,8 @@ function run() { }; }); } + // TODO use arrays in all things + opts._old_server_name = opts.sites[0].name; if (argv.p || argv.port || argv._[0]) { opts.manualPort = true; @@ -380,7 +380,7 @@ function run() { opts.expressApp = require(path.resolve(process.cwd(), argv['express-app'])); } - if (opts.email || opts.servername) { + if (opts.email || argv.sites || argv.servername) { if (!opts.agreeTos) { console.warn("You may need to specify --agree-tos to agree to both the Let's Encrypt and Daplie DNS terms of service."); } @@ -423,7 +423,7 @@ function run() { console.info(''); // Port - httpsUrl = 'https://' + opts.servername; + httpsUrl = 'https://' + opts._old_server_name; p = opts.port; if (httpsPort !== p) { httpsUrl += ':' + p; @@ -431,7 +431,7 @@ function run() { console.info('\t' + httpsUrl); // Insecure Port - httpUrl = 'http://' + opts.servername; + httpUrl = 'http://' + opts._old_server_name; p = opts.insecurePort; if (httpPort !== p) { httpUrl += ':' + p; @@ -439,16 +439,16 @@ function run() { console.info('\t' + httpUrl + ' (redirecting to https)'); console.info(''); - if (!(argv.servername && defaultServername !== argv.servername && !(argv.key && argv.cert))) { + if (!((argv.sites || argv.servername) && defaultServername !== (argv.sites || argv.servername) && !(argv.key && argv.cert))) { // ifaces opts.ifaces = require('../lib/local-ip.js').find(); promise = PromiseA.resolve(); } else { - console.info("Attempting to resolve external connection for '" + argv.servername + "'"); + console.info("Attempting to resolve external connection for '" + opts._old_server_name + "'"); try { - promise = require('../lib/match-ips.js').match(argv.servername, opts); + promise = require('../lib/match-ips.js').match(opts._old_server_name, opts); } catch(e) { - console.warn("Upgrade to version 2.x to use automatic certificate issuance for '" + argv.servername + "'"); + console.warn("Upgrade to version 2.x to use automatic certificate issuance for '" + opts._old_server_name + "'"); promise = PromiseA.resolve(); } } @@ -456,7 +456,7 @@ function run() { return promise.then(function (matchingIps) { if (matchingIps) { if (!matchingIps.length) { - console.info("Neither the attached nor external interfaces match '" + argv.servername + "'"); + console.info("Neither the attached nor external interfaces match '" + opts._old_server_name + "'"); } } opts.matchingIps = matchingIps || []; diff --git a/lib/app.js b/lib/app.js index 316d5dd..742b7ab 100644 --- a/lib/app.js +++ b/lib/app.js @@ -11,7 +11,6 @@ module.exports = function (opts) { var server; function addServer(hostname) { - console.log('add server:', hostname); if (hostsMap[hostname]) { return hostsMap[hostname]; @@ -24,8 +23,6 @@ module.exports = function (opts) { return; } - console.log('add server for reals', tmp); - site.path = site.path || site.paths[0] || '.'; if (!pathsMap[site.path]) { @@ -67,8 +64,6 @@ module.exports = function (opts) { } - opts.servername = opts.servername || opts.sites[0].name; - addServer(opts.sites[0].name); return function (req, res) { @@ -79,7 +74,7 @@ module.exports = function (opts) { } var done = finalhandler(req, res); var host = req.headers.host; - var hostname = (host||'').split(':')[0] || opts.servername; + var hostname = (host||'').split(':')[0] || opts.sites[0].name; function serveStatic(server) { if (server.expressApp) { @@ -95,7 +90,7 @@ module.exports = function (opts) { if (opts.livereload) { res.__my_livereload = ''; res.__my_addLen = res.__my_livereload.length; diff --git a/lib/ddns.js b/lib/ddns.js index f860926..2ed1cca 100644 --- a/lib/ddns.js +++ b/lib/ddns.js @@ -5,10 +5,10 @@ module.exports.create = function (opts/*, servers*/) { var dns = PromiseA.promisifyAll(require('dns')); return PromiseA.all([ - dns.resolve4Async(opts.servername).then(function (results) { + dns.resolve4Async(opts._old_server_name).then(function (results) { return results; }, function () {}) - , dns.resolve6Async(opts.servername).then(function (results) { + , dns.resolve6Async(opts._old_server_name).then(function (results) { return results; }, function () {}) ]).then(function (results) { @@ -73,14 +73,14 @@ module.exports.create = function (opts/*, servers*/) { if (require.main === module) { var opts = { - servername: 'aj.daplie.me' + _old_server_name: 'aj.daplie.me' , PromiseA: require('bluebird') }; // ifaces opts.ifaces = require('./local-ip.js').find(); console.log('opts.ifaces'); console.log(opts.ifaces); - require('./match-ips.js').match(opts.servername, opts).then(function (ips) { + require('./match-ips.js').match(opts._old_server_name, opts).then(function (ips) { opts.matchingIps = ips.matchingIps || []; opts.externalIps = ips.externalIps; module.exports.create(opts); diff --git a/lib/tunnel.js b/lib/tunnel.js index 2bc135a..a4ea58c 100644 --- a/lib/tunnel.js +++ b/lib/tunnel.js @@ -63,25 +63,31 @@ module.exports.create = function (opts, servers) { return Tunnel.token({ refreshToken: opts.refreshToken , email: opts.email - , domains: [ opts.servername ] + , domains: opts.sites.map(function (site) { + return site.name; + }) , device: { hostname: opts.devicename || opts.device } }).then(function (result) { // { jwt, tunnelUrl } + var locals = []; + opts.sites.map(function (site) { + locals.push({ + protocol: 'https' + , hostname: site.name + , port: opts.port + }); + locals.push({ + protocol: 'http' + , hostname: site.name + , port: opts.insecurePort || opts.port + }); + }); return stunnel.connect({ token: result.jwt , stunneld: result.tunnelUrl // XXX TODO BUG // this is just for testing , insecure: /*opts.insecure*/ true - , locals: [ - { protocol: 'https' - , hostname: opts.servername - , port: opts.port - } - , { protocol: 'http' - , hostname: opts.servername - , port: opts.insecurePort || opts.port - } - ] + , locals: locals // a simple passthru is proving to not be so simple , net: require('net') /* { From 6526b2075ef06a4c147071ebef997d3bc267866e Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 1 Feb 2017 20:02:25 -0700 Subject: [PATCH 116/129] clarify --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 27ed2e5..e935ada 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,8 @@ Options: * `--email ` - email to use for Let's Encrypt, Daplie DNS, Daplie Tunnel * `--agree-tos` - agree to terms for Let's Encrypt, Daplie DNS -* `--sites ` - use `` instead of `localhost.daplie.me` +* `--sites ` comma-separated list of domains to respond to (default is `localhost.daplie.me`) + * optionally you may include the path to serve with `|` such as `example.com|/tmp,example.net/srv/www` * `--tunnel` - make world-visible (must use `--sites`) Specifying a custom HTTPS certificate: From 8c0a2634b3bbd21c5138207a143513405ab14518 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 1 Feb 2017 20:02:28 -0700 Subject: [PATCH 117/129] v2.1.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bcbf9fa..37f3a85 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "2.1.2", + "version": "2.1.3", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.me - great for testing and development.", "main": "bin/serve-https.js", "scripts": { From c900aa1727e3a63ea6ffd036ba3227edee68ec5d Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 1 Feb 2017 20:23:56 -0700 Subject: [PATCH 118/129] fix --servername / --sites parse bug --- bin/serve-https.js | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/bin/serve-https.js b/bin/serve-https.js index d8f482b..d360ad9 100755 --- a/bin/serve-https.js +++ b/bin/serve-https.js @@ -253,6 +253,10 @@ function run() { console.info('v' + require('../package.json').version); return; } + if (argv.servername && argv.sites) { + throw new Error('specify only --sites, not --servername'); + } + argv.sites = argv.sites || argv.servername; // letsencrypt var httpsOptions = require('localhost.daplie.me-certificates').merge({}); @@ -289,7 +293,7 @@ function run() { argv.key = argv.key || '/etc/letsencrypt/live/' + letsencryptHost + '/privkey.pem'; argv.cert = argv.cert || '/etc/letsencrypt/live/' + letsencryptHost + '/fullchain.pem'; argv.root = argv.root || argv.chain || ''; - argv.sites = argv.sites || (argv.servername || letsencryptHost); + argv.sites = argv.sites || letsencryptHost; argv['serve-root'] = argv['serve-root'] || argv['serve-chain']; // argv[express-app] } @@ -341,23 +345,17 @@ function run() { opts.sites = [ { name: defaultServername , path: '.' } ]; - if (argv.servername) { - // TODO remove in v3.x (aka goldilocks) - if (argv.sites) { - throw new Error('specify only --sites, not --servername'); - } - opts.sites = [ { name: argv.servername, path: '.' } ]; - } if (argv.sites) { opts.sites = argv.sites.split(',').map(function (name) { - var serverparts = name.split('|'); + var nameparts = name.split('|'); // TODO allow reverse proxy return { - name: serverparts.shift() - , paths: serverparts + name: nameparts.shift() + , paths: nameparts }; }); } + console.log('opts.sites', opts.sites); // TODO use arrays in all things opts._old_server_name = opts.sites[0].name; @@ -380,7 +378,7 @@ function run() { opts.expressApp = require(path.resolve(process.cwd(), argv['express-app'])); } - if (opts.email || argv.sites || argv.servername) { + if (opts.email || argv.sites) { if (!opts.agreeTos) { console.warn("You may need to specify --agree-tos to agree to both the Let's Encrypt and Daplie DNS terms of service."); } @@ -439,7 +437,7 @@ function run() { console.info('\t' + httpUrl + ' (redirecting to https)'); console.info(''); - if (!((argv.sites || argv.servername) && defaultServername !== (argv.sites || argv.servername) && !(argv.key && argv.cert))) { + if (!(argv.sites && (defaultServername !== argv.sites) && !(argv.key && argv.cert))) { // ifaces opts.ifaces = require('../lib/local-ip.js').find(); promise = PromiseA.resolve(); From fa02f05b9adc0802ca6ac0e9366504cd8a6c64f0 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 1 Feb 2017 20:23:59 -0700 Subject: [PATCH 119/129] v2.1.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 37f3a85..939a20e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "2.1.3", + "version": "2.1.4", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.me - great for testing and development.", "main": "bin/serve-https.js", "scripts": { From f0bea933f9d697ee6079605a1bbbd91dabbfa6ff Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 2 Feb 2017 17:56:35 -0700 Subject: [PATCH 120/129] make -d, pubdir, and public all defaultWebRoot --- bin/serve-https.js | 28 ++++++++++++++++------------ lib/app.js | 5 ++--- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/bin/serve-https.js b/bin/serve-https.js index d360ad9..14b54c5 100755 --- a/bin/serve-https.js +++ b/bin/serve-https.js @@ -27,7 +27,7 @@ function showError(err, port) { } } -function createInsecureServer(port, pubdir, opts) { +function createInsecureServer(port, _delete_me_, opts) { return new PromiseA(function (realResolve) { var server = http.createServer(); @@ -44,7 +44,7 @@ function createInsecureServer(port, pubdir, opts) { opts.errorInsecurePort = err.toString(); - return createInsecureServer(insecurePortFallback, pubdir, opts).then(resolve); + return createInsecureServer(insecurePortFallback, null, opts).then(resolve); }); server.on('request', opts.redirectApp); @@ -56,7 +56,7 @@ function createInsecureServer(port, pubdir, opts) { }); } -function createServer(port, pubdir, content, opts) { +function createServer(port, _delete_me_, content, opts) { function approveDomains(params, certs, cb) { // This is where you check your database and associated // email addresses with domains and agreements and such @@ -94,7 +94,7 @@ function createServer(port, pubdir, content, opts) { return new PromiseA(function (realResolve) { var app = require('../lib/app.js'); - var directive = { public: pubdir, content: content, livereload: opts.livereload + var directive = { content: content, livereload: opts.livereload , sites: opts.sites , expressApp: opts.expressApp }; var insecureServer; @@ -167,7 +167,7 @@ function createServer(port, pubdir, content, opts) { opts.errorPort = err.toString(); - return createServer(portFallback, pubdir, content, opts).then(resolve); + return createServer(portFallback, null, content, opts).then(resolve); }); server.listen(port, function () { @@ -183,9 +183,10 @@ function createServer(port, pubdir, content, opts) { , exclusions: [ 'node_modules' ] }); - console.info("[livereload] watching " + pubdir); + console.info("[livereload] watching " + opts.pubdir); console.warn("WARNING: If CPU usage spikes to 100% it's because too many files are being watched"); - server2.watch(pubdir); + // TODO create map of directories to watch from opts.sites and iterate over it + server2.watch(opts.pubdir); } // if we haven't disabled insecure port @@ -195,7 +196,7 @@ function createServer(port, pubdir, content, opts) { // or other case || (httpPort !== opts.insecurePort && opts.port !== opts.insecurePort) ) { - return createInsecureServer(opts.insecurePort, pubdir, opts).then(function (_server) { + return createInsecureServer(opts.insecurePort, null, opts).then(function (_server) { insecureServer = _server; resolve(); }); @@ -242,7 +243,7 @@ function run() { var argv = minimist(process.argv.slice(2)); var port = parseInt(argv.p || argv.port || argv._[0], 10) || httpsPort; var livereload = argv.livereload; - var pubdir = path.resolve(argv.d || argv._[1] || process.cwd()); + var defaultWebRoot = path.resolve(argv.d || argv._[1] || process.cwd()); var content = argv.c; var letsencryptHost = argv['letsencrypt-certs']; @@ -351,13 +352,15 @@ function run() { // TODO allow reverse proxy return { name: nameparts.shift() - , paths: nameparts + // there should always be a path + , paths: nameparts.length && nameparts || [ defaultWebRoot ] }; }); } console.log('opts.sites', opts.sites); // TODO use arrays in all things opts._old_server_name = opts.sites[0].name; + opts.pubdir = defaultWebRoot; if (argv.p || argv.port || argv._[0]) { opts.manualPort = true; @@ -410,14 +413,15 @@ function run() { }; opts.redirectApp = require('redirect-https')(opts.redirectOptions); - return createServer(port, pubdir, content, opts).then(function (servers) { + return createServer(port, null, content, opts).then(function (servers) { var p; var httpsUrl; var httpUrl; var promise; + // TODO show all sites console.info(''); - console.info('Serving ' + pubdir + ' at '); + console.info('Serving ' + opts.pubdir + ' at '); console.info(''); // Port diff --git a/lib/app.js b/lib/app.js index 742b7ab..9169c95 100644 --- a/lib/app.js +++ b/lib/app.js @@ -16,14 +16,13 @@ module.exports = function (opts) { return hostsMap[hostname]; } - var tmp = { }; - opts.sites.forEach(function (site) { if (hostname !== site.name) { return; } - site.path = site.path || site.paths[0] || '.'; + // path should exist before it gets to this point + site.path = site.path || site.paths[0]; if (!pathsMap[site.path]) { pathsMap[site.path] = { From e12164d3dc41ab776688eb4e1a82980b4ca5cd30 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 2 Feb 2017 18:15:54 -0700 Subject: [PATCH 121/129] don't output agree-tos and email message for localhost --- bin/serve-https.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/bin/serve-https.js b/bin/serve-https.js index 14b54c5..e4fa3c5 100755 --- a/bin/serve-https.js +++ b/bin/serve-https.js @@ -347,17 +347,19 @@ function run() { opts.sites = [ { name: defaultServername , path: '.' } ]; if (argv.sites) { + opts._externalHost = false; opts.sites = argv.sites.split(',').map(function (name) { var nameparts = name.split('|'); + var servername = nameparts.shift(); + opts._externalHost = opts._externalHost || !/(^|\.)localhost\./.test(servername); // TODO allow reverse proxy return { - name: nameparts.shift() + name: servername // there should always be a path , paths: nameparts.length && nameparts || [ defaultWebRoot ] }; }); } - console.log('opts.sites', opts.sites); // TODO use arrays in all things opts._old_server_name = opts.sites[0].name; opts.pubdir = defaultWebRoot; @@ -381,7 +383,7 @@ function run() { opts.expressApp = require(path.resolve(process.cwd(), argv['express-app'])); } - if (opts.email || argv.sites) { + if (opts.email || opts._externalHost) { if (!opts.agreeTos) { console.warn("You may need to specify --agree-tos to agree to both the Let's Encrypt and Daplie DNS terms of service."); } @@ -442,6 +444,9 @@ function run() { console.info(''); if (!(argv.sites && (defaultServername !== argv.sites) && !(argv.key && argv.cert))) { + // TODO what is this condition actually intending to test again? + // (I think it can be replaced with if (!opts._externalHost) { ... } + // ifaces opts.ifaces = require('../lib/local-ip.js').find(); promise = PromiseA.resolve(); From e7022c8bd445498f79bd879e8c834f49c773a089 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 2 Feb 2017 18:16:01 -0700 Subject: [PATCH 122/129] v2.1.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 939a20e..6b14625 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "2.1.4", + "version": "2.1.5", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.me - great for testing and development.", "main": "bin/serve-https.js", "scripts": { From 98dac060850f9cb6dcf9e7e6e7ad6e169e739fd7 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 3 Feb 2017 10:50:33 -0700 Subject: [PATCH 123/129] allow templating --- README.md | 3 +++ bin/serve-https.js | 8 +++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e935ada..0120cdd 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,9 @@ Options: * `-p ` - i.e. `sudo serve-https -p 443` (defaults to 80+443 or 8443) * `-d ` - i.e. `serve-https -d /tmp/` (defaults to `pwd`) + * you can use `:hostname` as a template for multiple directories + * Example A: `serve-https -d /srv/www/:hostname --sites localhost.foo.daplie.me,localhost.bar.daplie.me` + * Example B: `serve-https -d ./:hostname/public/ --sites localhost.foo.daplie.me,localhost.bar.daplie.me` * `-c ` - i.e. `server-https -c 'Hello, World! '` (defaults to directory index) * `--express-app ` - path to a file the exports an express-style app (`function (req, res, next) { ... }`) * `--livereload` - inject livereload into all html pages (see also: [fswatch](http://stackoverflow.com/a/13807906/151312)), but be careful if `` has thousands of files it will spike your CPU usage to 100% diff --git a/bin/serve-https.js b/bin/serve-https.js index e4fa3c5..6fde3bf 100755 --- a/bin/serve-https.js +++ b/bin/serve-https.js @@ -243,7 +243,7 @@ function run() { var argv = minimist(process.argv.slice(2)); var port = parseInt(argv.p || argv.port || argv._[0], 10) || httpsPort; var livereload = argv.livereload; - var defaultWebRoot = path.resolve(argv.d || argv._[1] || process.cwd()); + var defaultWebRoot = path.resolve(argv['default-web-root'] || argv.d || argv._[1] || process.cwd()); var content = argv.c; var letsencryptHost = argv['letsencrypt-certs']; @@ -356,13 +356,15 @@ function run() { return { name: servername // there should always be a path - , paths: nameparts.length && nameparts || [ defaultWebRoot ] + , paths: nameparts.length && nameparts || [ + defaultWebRoot.replace(/(:hostname|:servername)/g, servername) + ] }; }); } // TODO use arrays in all things opts._old_server_name = opts.sites[0].name; - opts.pubdir = defaultWebRoot; + opts.pubdir = defaultWebRoot.replace(/(:hostname|:servername).*/, ''); if (argv.p || argv.port || argv._[0]) { opts.manualPort = true; From d0c922ca729cfaae260d707dafc14d5c28345f44 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 3 Feb 2017 10:50:50 -0700 Subject: [PATCH 124/129] v2.1.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6b14625..b69b347 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "2.1.5", + "version": "2.1.6", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.me - great for testing and development.", "main": "bin/serve-https.js", "scripts": { From 260e53ee3aee81e0b3eb6cdc0521924cfcb7fd9c Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 3 Feb 2017 11:47:40 -0700 Subject: [PATCH 125/129] update localhost.daplie.me-certificates version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b69b347..cece1b8 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "greenlock-express": "git+https://git.daplie.com/Daplie/greenlock-express.git#master", "greenlock": "git+https://git.daplie.com/Daplie/node-greenlock.git#master", "livereload": "^0.6.0", - "localhost.daplie.me-certificates": "^1.2.0", + "localhost.daplie.me-certificates": "^1.3.0", "minimist": "^1.1.1", "oauth3-cli": "git+https://git.daplie.com/OAuth3/oauth3-cli.git#master", "redirect-https": "^1.1.0", From f539feb37a7d5fc854fae5fb32905826f5ec6c3d Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 3 Feb 2017 11:47:43 -0700 Subject: [PATCH 126/129] v2.1.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cece1b8..8e4a6ae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "2.1.6", + "version": "2.1.7", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.me - great for testing and development.", "main": "bin/serve-https.js", "scripts": { From 658b0952541925543b74855bdab064cda8125a5c Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 3 Feb 2017 11:55:17 -0700 Subject: [PATCH 127/129] use any available *localhost*.daplie.me certificate --- bin/serve-https.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/bin/serve-https.js b/bin/serve-https.js index 6fde3bf..b0cc66f 100755 --- a/bin/serve-https.js +++ b/bin/serve-https.js @@ -141,13 +141,17 @@ function createServer(port, _delete_me_, content, opts) { 'localhost.daplie.me': null }; opts.httpsOptions.SNICallback = function (sni, cb ) { + var tlsOptions; console.log('[https] sni', sni); // Static Certs - if ('localhost.daplie.me' === sni) { + if (/.*localhost.*\.daplie\.me/.test(sni.toLowerCase())) { // TODO implement if (!secureContexts[sni]) { - secureContexts[sni] = tls.createSecureContext(require('localhost.daplie.me-certificates').merge({})); + tlsOptions = require('localhost.daplie.me-certificates').mergeTlsOptions(sni, {}); + } + if (tlsOptions) { + secureContexts[sni] = tls.createSecureContext(tlsOptions); } cb(null, secureContexts[sni]); return; From 52036f463c441faa023c8b13b9f0dbf29421fa8c Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 3 Feb 2017 11:55:19 -0700 Subject: [PATCH 128/129] v2.1.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8e4a6ae..b4cac80 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serve-https", - "version": "2.1.7", + "version": "2.1.8", "description": "Serves HTTPS using TLS (SSL) certs for localhost.daplie.me - great for testing and development.", "main": "bin/serve-https.js", "scripts": { From 9948fccf71b4987d86c3ae5b03820bb85b8c3ad5 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Mon, 6 Feb 2017 11:15:18 -0700 Subject: [PATCH 129/129] remind to check before issuing with greenlock --- bin/serve-https.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bin/serve-https.js b/bin/serve-https.js index b0cc66f..b5adef5 100755 --- a/bin/serve-https.js +++ b/bin/serve-https.js @@ -363,6 +363,8 @@ function run() { , paths: nameparts.length && nameparts || [ defaultWebRoot.replace(/(:hostname|:servername)/g, servername) ] + // TODO check for existing custom path before issuing with greenlock + , _hasCustomPath: !!nameparts.length }; }); }