Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister

Relative URI

by choroba (Chancellor)
on Apr 21, 2011 at 22:26 UTC ( #900729=perlquestion: print w/replies, xml ) Need Help??
choroba has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks. Can anyone explain the following behaviour?
use strict; use warnings; use feature "say"; use URI; my $base = URI->new("http://a.b.c/d/../e/"); my $uri = URI->new("http://a.b.c/y"); say $uri->rel($base); # ../../../y
The only explanation I can think of is that /../ are only understood in relative URI's, not in absolute ones. But why? Can you enlighten me?

Replies are listed 'Best First'.
Re: Relative URI
by Anonymous Monk on Apr 21, 2011 at 23:48 UTC

      He expects http://a.b.c/d/../e/ to be the same as http://a.b.c/e/.

      use strict; use warnings; use Test::More tests => 1; use URI qw( ); my $base1 = URI->new("http://a.b.c/d/../e/"); my $base2 = URI->new_abs("../e/", URI->new("http://a.b.c/d/")); my $uri = URI->new("http://a.b.c/y"); is($uri->rel($base1), $uri->rel($base2)); 1;
      1..1 not ok 1 # Failed test at line 12. # got: '../../../y' # expected: '../y' # Looks like you failed 1 test of 1.

      I don't see anything in that covers this case.

      The equality definitely doesn't hold up in file systems (due to links both soft and hard), but ../../../y is much less likely to be correct.

      Update: Improved test a bit.

        He expects http://a.b.c/d/../e/ to be the same as http://a.b.c/e/.
        If I read section 5.2 of RFC 3986 correctly, the OP quite rightly expects that to be.
      #!/usr/bin/perl -- use strict; use warnings; use URI; Main( @ARGV ); exit( 0 ); sub Main { ABT(); } sub ABT { require Test::More; Test::More->import(qw' no_plan '); my $base = URI->new("http://a/d/../e/"); my $uri = URI->new("http://a/y"); is( $base, ( "http://a/d/../e/" ) x 2 ); is( $base->path, ( "/d/../e/" ) x 2 ); is( $uri, ( "http://a/y" ) x 2 ); is( $uri->path, ( "/y" ) x 2 ); diag("should the following be equivalent??"); is( $uri->rel($base), "??", q~$uri->rel($base)~ ); is( URI->new( $uri->path )->rel( $base->path ), $uri->rel($base), q~URI->new( $uri->path )->rel( $base->path ) +~ ); is( URI->new("/y")->rel("/d/../e/"), $uri->rel($base), q~URI->new("/y")->rel("/d/../e/") ~ ); } __END__ ok 1 - http://a/d/../e/ ok 2 - /d/../e/ ok 3 - http://a/y ok 4 - /y # should the following be equivalent?? not ok 5 - $uri->rel($base) # Failed test '$uri->rel($base)' # at - line 27. # got: '../../../y' # expected: '??' not ok 6 - URI->new( $uri->path )->rel( $base->path ) # Failed test 'URI->new( $uri->path )->rel( $base->path )' # at - line 28. # got: '/y' # expected: '../../../y' not ok 7 - URI->new("/y")->rel("/d/../e/") # Failed test 'URI->new("/y")->rel("/d/../e/") ' # at - line 30. # got: '/y' # expected: '../../../y' 1..7 # Looks like you failed 3 tests of 7.
Re: Relative URI
by Khen1950fx (Canon) on Apr 22, 2011 at 03:47 UTC
    Using Test::URI, ../../../y seems relatively correct:
    #!/usr/bin/perl use strict; use warnings; use URI; my $uri_string1 = 'http://a.b.c/d/../e/'; my $uri_string2 = 'http://a.b.c/y'; my $base = URI->new($uri_string1); my $uri = URI->new($uri_string2); print $base->abs($uri), "\n"; print $uri->abs($base), "\n"; print $base->rel($uri), "\n"; print $uri->rel($base), "\n"; print "\n"; use Test::URI; use Test::More tests => 4; use_ok( 'Test::URI' ); uri_scheme_ok( $uri_string2, 'http' ); uri_host_ok( $uri_string2, 'a.b.c' ); uri_path_ok( $uri_string2, '/y' );
      What do you think you're testing? Your code in no way supports your conclusion.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://900729]
Approved by ww
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (5)
As of 2017-02-25 03:53 GMT
Find Nodes?
    Voting Booth?
    Before electricity was invented, what was the Electric Eel called?

    Results (365 votes). Check out past polls.