-
Notifications
You must be signed in to change notification settings - Fork 29.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
http: allow HTTP to return an HTTPS server #1101
http: allow HTTP to return an HTTPS server #1101
Conversation
This commit allows the http module to create a HTTPS server if TLS options are passed to createServer() or the Server() constructor.
@@ -213,8 +213,25 @@ ServerResponse.prototype.writeHeader = function() { | |||
}; | |||
|
|||
|
|||
function Server(requestListener) { | |||
if (!(this instanceof Server)) return new Server(requestListener); | |||
var TLS_ARGS = ['pfx', 'key', 'passphrase', 'cert', 'ca', 'crl', 'ciphers', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this seems brittle to me, perhaps we could consider connecting it with the https module such that when the options are modified there we don't run the risk of this falling out of sync?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would be a better solution than what is already there, but I don't think there is a global list in tls
for options that we could hook into, so the only difference that would be made is changing the location for the list.
As sort of a counter proposal, I'd say we don't check for the TLS option names, rather just assume its TLS if there is an object, because before this it would just throw an error anyways.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 to instantiating an HTTPS server just if the first argument is an object instead of also checking for explicit object properties.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW, when I originally wrote this patch, that is how I implemented it. However, @hueniverse, who I wrote this for, asked me to explicitly check for the TLS options.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The recently added dhparam
option for PFS is missing in this list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hah, point proven, this is a risk then.
I'm also not convinced that just using the existence of the options object is good API either--what if we want to add options that http.Server cares about? Then we're stuck with having to break API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we're planning on adding an options
for http.createServer()
in the future, then if nothing else we could just check for one of the required https config options (e.g. pfx
and key
) to determine if an https.Server
should be created.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The minimum would be either pfx
or both key
and cert
. Certainly better than the full list in terms of maintainability.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about accepting a { tls: true }
parameter in the options?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about accepting a { tls: true } parameter in the options?
That! No spooky action at a distance please...
What's the motivation for adding this? I'm not sure it's good to mix up if (secure)
require("https").createServer(options, listener);
else
require("http").createServer(listener); I could see require(secure ? "https" : "http").createServer(options, listener); |
@silverwind the basis of it all started here. It especially got my attention when I read this comment - I would eventually like to merge the Both modules do basically the same thing, and if a wrapper of TLS is all that the other offers (with a relatively tiny amount of developer-side configuration), I see no reason that they shouldn't be implemented in the same core module. The best example of this is the |
Sounds resonable. We should also think on how we integrate I could see |
@silverwind actually, that does make sense, since from the looks of the http2 discussion most everyone would like it to stay in the same module. I'd say http2 would default to on, and you could disable it with something like |
Probably safer to use As for this PR, my vote is for |
In general, in favor of merging of the http and https modules. |
This commit does various changes to cleanup and prep the 8ff6b81 for merging, which include updating the commit to follow new codebase guidelines. The following are the changes: doc/api/http.markdown: - document options lib/http.js: - no changes lib/_http_server.js - changes regarding isObject (nodejs#647) and hasOwnProperty (nodejs#635) - take tls option rather than guessing based on options test/simple/test-https-from-http.js: - moved to parallel directory, crypto test, removed copyright banner test/parallel/test-http-server.js: - adjust for tls option
b6be981
to
b3b6b24
Compare
Changed to accept an @piscisaureus I think I may open an issue on NG for that, with a checklist and stuff. |
I'm +0 on this because the API still seems a little clumsy but that's mainly because we're retrofitting rather than defining something new. |
Implementation looks fine. I think the API is a good compromise. |
I don't hate the |
In addition to |
My choice would be to ditch |
My stance is that a explicit option is cleaner than relying on magic options, and we're going to need one for http2 later too. |
I think we should do whatever will cause the least future issues in light of the entire http2 thing. |
I'd say that to keep in the vein of a future HTTP2 (which I envision as It would be possible to log a warning to the console if options are passed without a |
I think someone who uses So, LGTM |
Any more opinions here? To summarize the issue at hand, we have two proposals on how to discern http from https when doing it through a single module: require("http").createServer({tls: true, /* https options */}, listener); or without an explicit option (by detecting the required args require("http").createServer({/* https options */}, listener); |
This breaks the following: new http.Server({ tls: true }) instanceof http.Server Edit: But that did trow before this change, so it should not be a problem. |
My understanding is that HTTP/2 requires TLS to be enabled. As such, I'm -1 on this. Let's just consolidate all of this in to |
@Fishrock123 I'm no HTTP2 master, but you do seem to be at least partially right according to the wikipedia page. However, just because HTTP2 requires (or may not?) TLS from the client perspective, the server must still be handled differently. Currently, many setups use some sort of TLS terminator, such as nginx, which I would say be enough reason to allow for non-TLS HTTP2 servers created. The option of built-in TLS isn't going to become outdated - through that same path, the entire HTTPS module will also become outdated. Plus, it'd be backwards compatibility to support non-HTTPS connections over HTTP1.1, anyways. |
Regarding encryption: https://http2.github.io/faq/#does-http2-require-encryption I've searched through https://tools.ietf.org/html/draft-ietf-httpbis-http2-17 but couldn't find any information regarding tls/encryption in general. Maybe this is covered elsewhere? Maybe in the upcoming RFC? |
@silverwind The spec allows unencrypted HTTP/2 but I believe all browser vendors have stated they won't support that. Encryption is effectively mandatory. |
The spec does not require you to use TLS. But if you do, then it has some requirements to the configuration section 9.2. We actually will need tre different http/2 modes:
The http/2 protocol does start with a sequence of 24 octets (the string With this preface it should be enough to determine between tls mode and plain text mode. Including the new Edit: This is a +1 from me to add the |
Noted. +1 then. I don't really have an option on |
I'm for using the Also, if some wrapper code (eg. a library) which adds some default options (eg. adding |
@Fishrock123 my stance on the "tls might become a little redundant" is that, yes, it would be redundant - but it is better than magical parsing, as you have a way to override a guess. At the moment, only two people are for an explicit option (not including me), and one is for magic options. Would anyone else like to volunteer their opinion? |
Maybe the inclusion of the |
Well, do we have anyone who isn't for the |
@Fishrock123, @cjihrig is for the magic options - he originally wrote the patch, which used magic options. |
Ah. As a 3rd (weird) case, |
@Fishrock123 I think that'd be awkward, personally. IMHO, I think the best solution to this would be rather: var server = require('http').createServer(function() {});
server.listen(443, {tls: true, ca: ...}); That would require a big structural change to the whole thing, though. |
What about HTTP/2 also introduces a pseudo header field named |
At the TC meeting it was suggested to pass all the options to the |
Based on the TC feedback, this PR looks like it'll need some work. It's still a WIP on my part, but if someone wants to take it over before I get to it, feel free. |
I don't see how this can be easily implemented good without breaking something. I propose we work towards an api like this. var server = http.createServer({ /* accept options here for backwards compatibility */ })
// either this
server.listen({ port: 80 })
server.listen({ port: 443, tls: true, http2: true, cert: '...', key: '...' })
// or like this
server.listen([ { port: 80 }, { port: 443, tls: true, http2: true, cert: '...', key: '...' } ])
// and when you want to stop incoming connections
server.close() // closes all To do this we need to break If we think this is to much suggar, I think we should let userland deal with this and keep the separation between |
@tellnes I agree it can't be implemented through |
Maybe we can bring this back to the tsc and they can make a decision if we can break |
@tellnes to be honest, I don't think it should break that (it seems like a logical place to use inheritance), and still think we should consider other ways (if there are any?). |
This commit allows the
http
module to create a HTTPS serverif TLS options are passed to
createServer()
or theServer()
constructor.
Adoption of joyent/node#8738. /cc @cjihrig
The second commit contains rebase edits, code style edits, etc that has happened in the past few months.