Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

url: fix/8722 #8755

Closed
wants to merge 4 commits into from
Closed

url: fix/8722 #8755

wants to merge 4 commits into from

Conversation

yorkie
Copy link

@yorkie yorkie commented Nov 20, 2014

This patch attempts to close this issue #8722:

  • feature
  • test
  • documentation
  • fix some style conflicts with jshint in test-url.js

R=@indutny, @chrisdickinson 🍒

@@ -389,6 +389,18 @@ Url.prototype.format = function() {
host = false,
query = '';

if (this.path) {
var qm = this.path.indexOf('?');
pathname = pathname || (function(idx, path) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we handle it without creating closure?

@yorkie
Copy link
Author

yorkie commented Nov 20, 2014

Removed closure function 🌸

query = this.path.slice(qm);
pathname = pathname || this.path.slice(0, qm);
} else {
pathname = pathname || this.path;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If path is given:

  1. if it contains "?...", that replaces the current query
  2. if it does not contain "?...", the current query is used
  3. if search is given, it always wins
  4. if hash is given, it always wins

I suppose my confusion is: for some attributes, the more specific attribute "wins" versus the more general attribute, while in the "path" case, the less specific version wins:

query is more specific than search is more specific than path -> search wins
pathname is more specific than path -> path wins
hash is more specific than path -> hash wins

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pathname is more specific than path -> path wins
hash is more specific than path -> hash wins

hey @chrisdickinson they are not consistent because you say:

the less specific version wins

i guess in hash line, it should be "path wins"?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and for given pseudocode by last last comment, in path case, we should only touch one of query or search, because in path they are overlapped, so i choose query, search will be reassigned next code, so i propose the program will be:

  1. if it contains "?...", than replaces the current query
  2. if it doesn't, the current query is used of course included search
  3. if it contains "#...", then replaces the current hash
  4. if it doesn't, the current hash is used

query is more specific than search is more specific than path -> search wins

from my above statement, i guess we shouldn't touch search any more, just follow the step 1.
@chrisdickinson how do you think about my idea?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm. I think we should try to mirror how host (vs. hostname + port) operates with path -- that is:

If path is given, it is assumed to include search/query and pathname. If those are not present in path, and path is given, then they will be omitted from the output of format.

So:

// we're matching this behavior: (port is omitted from "host" but "host" overrides port)
assert.equal(url.format({host: 'some.host.com', hostname: 'example.com', port: 8080}), '//some.host.com');
assert.equal(url.format({hostname: 'example.com', port: 8080}), '//example.com:8080');

// "auth" is not considered part of "host"
assert.equal(url.format({auth: 'a:b', host: 'some.host.com', hostname: 'example.com', port: 8080}), '//a:b@some.host.com');
assert.equal(url.format({auth: 'a:b', hostname: 'example.com', port: 8080}), '//a:b@example.com:8080');

// "path" does not include "hash", but does include "search" and "pathname"
assert.equal(url.parse('http://example.com/path/to/thing?q=1#hash').path, '/path/to/thing?q=1')
// "path" overrides pathname
assert.equal(url.format({host: "example.com", path: "/path/to/thing?q=1", pathname: "/anythingelse"}), '//example.com/path/to/thing?q=1') 
// "path" overrides search/query
assert.equal(url.format({host: "example.com", path: "/path/to/thing?q=1", search: "?p=2"}), '//example.com/path/to/thing?q=1')
// "path" overrides search/query even if not given in "path"
assert.equal(url.format({host: "example.com", path: "/path/to/thing", search: "?p=2"}), '//example.com/path/to/thing')
// similarly, "path" overrides "pathname" even if not given:
assert.equal(url.format({host: "example.com", path: "?p=2", pathname: "/anything"}), '//example.com?p=2')

to illustrate:

+-----------------------------------------------------------------------------------+
| href                                                                              |
+----------+--+-----------+--------------------+-----------------------------+------+
| protocol |* | auth      | host               | path                        | hash |
|          |  |           +-------------+------+----------+------------------+      |
|          |  |           | hostname    | port | pathname | search           |      |
|          |  |           |             |      |          +-+----------------+      |
|          |  |           |             |      |          | | query          |      |
" http:     //   user:pass@some.host.com:65535 /path/name ? search=1&continues#hash "
|          |  |           |             |      |          | |                |      |
+----------+--+-----------+-------------+------+----------+-+----------------+------+
(all spaces in the "" line should be ignored -- they're purely for formatting)
*: given by "slashes" key

Setting a key at the higher level should cause url.format to ignore all keys at a "lower" level, whether or not that lower key is present in the text of the higher level key (even though "port" may not be present in "host", setting "host" ignores all values for "port").

@yorkie
Copy link
Author

yorkie commented Nov 22, 2014

ah, gotcha, i was just getting it backwards!!!
Fixed now, please review again @chrisdickinson thank you

search = '?' + query;
pathname = this.path.slice(0, qm);
} else {
pathname = this.path;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's one last case to check here -- path is present, but has no ?..., so the output url should have no ?... -- i.e., the query, search, and pathname keys are ignored if path is given.

@yorkie
Copy link
Author

yorkie commented Nov 23, 2014

@chrisdickinson reset this.query and this.set for now :)

query: {foo: 'bar'}
},

// path vs. search, search wins

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should probably read "path wins" here and on line 1154 now -- but I can fix that up on merge.

@chrisdickinson
Copy link

This is great. Thanks! LGTM /cc @indutny, if nobody has any qualms, I'll merge this tomorrow evening.

- pathname vs. path, pathname wins
- pathname with query/search
- path vs. query, query wins
- path vs. search, search wins
@yorkie
Copy link
Author

yorkie commented Nov 23, 2014

Fixed comments now
/cc @chrisdickinson @indutny 🍒

@yorkie
Copy link
Author

yorkie commented Nov 25, 2014

ping @chrisdickinson 🎅

@yorkie
Copy link
Author

yorkie commented Dec 2, 2014

struggle for pinging @chrisdickinson (This PR should has such a long delay?)

@chrisdickinson
Copy link

Ack! Sorry this took so long for me to pick up again. Looking now.

chrisdickinson pushed a commit that referenced this pull request Dec 2, 2014
this adds support for a "path" field that overrides
"query", "search", and "pathname" if given.

Fixes: #8722
PR-URL: #8755
Reviewed-by: Chris Dickinson <christopher.s.dickinson@gmail.com>
@chrisdickinson
Copy link

Thanks for your patience! Merged in d312b6d.

chrisdickinson pushed a commit to nodejs/node that referenced this pull request Dec 2, 2014
this adds support for a "path" field that overrides
"query", "search", and "pathname" if given.

Fixes: nodejs/node-v0.x-archive#8722
PR-URL: nodejs/node-v0.x-archive#8755
Reviewed-by: Chris Dickinson <christopher.s.dickinson@gmail.com>
@yorkie yorkie deleted the fix/8722 branch December 3, 2014 03:55
@yorkie
Copy link
Author

yorkie commented Dec 3, 2014

np 🍒

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants