Skip to content
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

How /..//bar should be resolved aganst scheme:? #8

Closed
lo48576 opened this issue Jan 9, 2022 · 6 comments
Closed

How /..//bar should be resolved aganst scheme:? #8

lo48576 opened this issue Jan 9, 2022 · 6 comments

Comments

@lo48576
Copy link
Owner

lo48576 commented Jan 9, 2022

In the current implementation, resolving ./..//bar against scheme:foo1/foo2 results in scheme://bar.
However, this is not desired, since bar in //bar should be a path segment but bar in scheme://bar is authority.

How should this be treated? Can resolve() result in error?

Details

merge("foo1/foo2", "./..//bar") is "foo1/./..//bar".

STEP   OUTPUT BUFFER         INPUT BUFFER

 1 :                         foo1/./..//bar
 2E:   foo1                  /./..//bar
 2B:   foo1                  /..//bar
 2C:                         //bar
 2E:   /                     /bar
 2E:   //bar
@lo48576
Copy link
Owner Author

lo48576 commented Jan 9, 2022

rfc3986 library of Python:

$ python
Python 3.9.9 (main, Nov 18 2021, 09:18:43)
[GCC 11.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from rfc3986 import uri_reference
>>> b = uri_reference('scheme:foo1/foo2')
>>> r = uri_reference('./..//bar')
>>> t = r.resolve_with(b)
>>> b
URIReference(scheme='scheme', authority=None, path='foo1/foo2', query=None, fragment=None)
>>> r
URIReference(scheme=None, authority=None, path='./..//bar', query=None, fragment=None)
>>> t
URIReference(scheme='scheme', authority=None, path='/bar', query=None, fragment=None)
>>> t.unsplit()
'scheme:/bar'
>>>
$ python
Python 3.9.9 (main, Nov 18 2021, 09:18:43)
[GCC 11.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from rfc3986 import uri_reference
>>> b = uri_reference('scheme:foo1/foo2/foo3/foo4')
>>> r = uri_reference('./..//bar')
>>> t = r.resolve_with(b)
>>> t
URIReference(scheme='scheme', authority=None, path='foo1/foo2//bar', query=None, fragment=None)
>>> t.unsplit()
'scheme:foo1/foo2//bar'
>>>

@lo48576
Copy link
Owner Author

lo48576 commented Jan 10, 2022

More simple examples:

  • base=scheme: and reference=..///bar.
  • base=scheme: and reference=/..//bar.
STEP   OUTPUT BUFFER         INPUT BUFFER

 1 :                         ..///bar
 2A:                         //bar
 2E:   /                     /bar
 2E:   //bar
STEP   OUTPUT BUFFER         INPUT BUFFER

 1 :                         /..//bar
 2C:                         //bar
 2E:   /                     /bar
 2E:   //bar

Resulting strings will be scheme://bar but is this acceptable?

@lo48576 lo48576 changed the title How ./..//bar should be resolved aganst scheme:foo1/foo2? How ..//bar should be resolved aganst scheme:foo1/foo2? Jan 10, 2022
@lo48576 lo48576 changed the title How ..//bar should be resolved aganst scheme:foo1/foo2? How /..//bar should be resolved aganst scheme:? Jan 10, 2022
@lo48576
Copy link
Owner Author

lo48576 commented Jan 10, 2022

Reported python-hyper/rfc3986#84 and python-hyper/rfc3986#85.

@lo48576
Copy link
Owner Author

lo48576 commented Jan 10, 2022

I'm going to make resolve() fallible (by other than OOM reason), but I'm not 100% sure whether RFC 3986 allows IRI resolution to fail...

@lo48576
Copy link
Owner Author

lo48576 commented Jan 11, 2022

Already implemented and tests are added
(Current develop is 3d8e81d.)

I'll refine docs and doc tests, and then will release.
(Possibly I'll wait for Rust 1.58 to be released.)

@lo48576 lo48576 closed this as completed Jan 11, 2022
@lo48576
Copy link
Owner Author

lo48576 commented Jan 28, 2022

Maybe related: servo/servo#28386

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=edcbb194959cc1ce16dacc45d237ad5b

use url;

use url::Url;

fn main() {
    let base = Url::parse("foo:/bar").unwrap();
    println!("base = {:?}", base);

    let resolved = base.join("./..//baz").unwrap();
    println!("resolved = {:?}", resolved);
    assert_eq!(resolved.host(), None);
    assert_eq!(resolved.path(), "//baz");
    let resolved_s = resolved.to_string();
    assert_eq!(resolved_s, "foo://baz");

    let roundtrip = Url::parse(&resolved_s).unwrap();
    println!("roundtrip = {:?}", roundtrip);
    assert_eq!(resolved, roundtrip); // OK
    assert_eq!(resolved.host(), roundtrip.host()); // Oops
}

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

No branches or pull requests

1 participant