-
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
Make http.request correctly parse {host: "hostname:port"} #2271
Conversation
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, | ||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
// USE OR OTHER DEALINGS IN THE SOFTWARE. |
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.
Doesn't need this license.
Also, 'use strict';
here please! :)
Oh, and two things I forgot to mention:
|
@Fishrock123 thanks, I just pushed a new commit that I believe addresses everything you pointed out. If you want, I'll rebase it into one. |
@@ -57,8 +57,10 @@ function ClientRequest(options, cb) { | |||
const defaultPort = options.defaultPort || | |||
self.agent && self.agent.defaultPort; | |||
|
|||
var port = options.port = options.port || defaultPort || 80; | |||
var host = options.host = options.hostname || options.host || 'localhost'; | |||
const hostParts = (options.host && options.host.split(':')) || []; |
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 will fail on IPv6 address and port, e.g. [::]:80
. Could use url
here like url.parse('fake://' + str)
.
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.
Good point. I'll add a test for that.
-1
|
I'm also feeling this is probably too magical, so I have to -1 as well here. |
@sam-github just before you posted, I switched to using |
There is a bug here, but I agree that this is starting to get a little silly and definitely don't want to make things worse. What would you guys say to a proper |
Actually, there's already an (undocumented) Although using it directly on the options object would change the behavior of ...It also leaves the brackets around ipv6 addresses, which also breaks dns lookups, so probably not a good option. |
Even with url parsing, I'm personally still -1, I just don't think this is reasonable for the HTTP library, which should focus on getting HTTP right, and let npm add API/use-case sugar. And its trivial to add this on top of |
And doesn't the change to test-http-dns-error.js mean this is a little bit backwards incompatible? |
To give a real-world example of where this bug makes node.js/io.js behave unexpectedly, I have a library that connects to a remote server. When testing, I mock the remote server with one running on localhost:8080, I then change the Yes, I can work around it easily enough, but that doesn't change the fact that it's a bug, or at the very least, doesn't work as expected. In the As for the test-http-dns-error.js, that test is expecting an error. With this patch, it would get a different error, but I think that's an acceptable change. That said, I'd be willing to rework it further to avoid that if it's important to you. |
The issue: http.request() treats host as an alternate form of hostname, which it sort of is, except that host is (normally) allowed to contain a port number. Before this change, if host contains a port number and there isn't a hostname field to override it, http.request() attempts a DNS lookup on the entire host field, including the port number. This always fails. The fix: If a host field is present, use the url lib to parse it and use the parsed hostname nad port values as fallbacks if options.hostname and options.port are unset. Includes tests for localhost:12346 and [::1]:12346.
3d0adbc
to
f1622f8
Compare
Here we go, I gave it one more shot. This one uses I added two lines to unwrap bracketed ipv6 addresses, based on the equivalent lines in I also rebased everything into a single commit to clean up the history. What do you guys say? If it's still a stack of -1's then I'll give up... |
@sam-github @silverwind .. looks like the conversation on this one stalled out. There was an updated commit that was never reviewed. Mind taking a look? |
@nodejs/http |
I think this doesn't play nice with IPv6 function parse(s) {
var parsedHost = {host: s};
if (s) {
url.Url.prototype.parseHost.call(parsedHost);
// unwrap brackets from ipv6 ip addresses
const hostname = parsedHost.hostname;
if (hostname[0] === '[' && hostname[hostname.length - 1] === ']') {
parsedHost.hostname = hostname.substr(1, hostname.length - 2);
}
}
}
console.dir(parse('::1'));
// displays:
// { host: '::1', port: '1', hostname: ':' } |
:-) @mscdex .. you read my mind. I had that same kind of test queued up on my todo list. I'm leaning towards a -1 on this particular change |
I agree with the concept, but not sure about the particular implementation. Of course, the string |
For some reason, I can't get this particular example to work at all here, any ideas? > url.Url.prototype.parseHost.call({host: '::1'})
undefined As for this issue: It has some value I'd say. |
@dougwilson I'd bet that most people just use
So I could easily see people using values like |
@silverwind The reason is that |
Hi @mscdex , it's a good thing I noted that it would be too confusing to actually enforce that in my post already :) |
Closing given the discussion. |
The issue:
http.request()
treatshost
as an alternate form ofhostname
, which it sort of is, except thathost
is (normally) allowed to contain a port number.Before this change, if
host
contains a port number and there isn't ahostname
field to override it,http.request()
attempts a DNS lookup on the entire host field, including the port number. This always fails.The fix:
If a host field is present, split it around
':'
and use the first portion as a fallbackhostname
and the second (if present) as a fallbackport
. ("Fallback" meaning that the values from thehost
field are only used when thehostname
andport
fields aren't set.)Includes a test to verify the correct behavior.
I originally filed an issue on joyent/node and submitted a patch there, but @jasnell said that this might be a better fit for nodejs/io.js or nodejs/node, so I'm sending the same patch to each. (The node patch is at #72) Please merge into whichever repo is appropriate and close the other one.