4.3. Converting Absolute URLs to Relative

A relative URL path assumes you're in a directory and the path elements are relative to that directory. For example, if you're in /staff/, these are the same:

roster/search.cgi
/staff/roster/search.cgi

If you're in /students/, this is the path to /staff/roster/search.cgi:

../staff/roster/search.cgi

The URI class includes a method rel( ), which creates a relative URL out of an absolute goal URI object. The newly created relative URL is how you could get to that original URL, starting from the absolute base URL.

$relative = $absolute_goal->rel(absolute_base);

The absolute_base is the URL path in which you're assumed to be; it can be a string, or a real URI object. But $absolute_goal must be a URI object. The rel( ) method returns a URI object.

For example:

use URI;
my $base = URI->new('http://phee.phye.phoe.fm/thingamajig/zing.xml');
my $goal = URI->new('http://phee.phye.phoe.fm/hi_there.jpg');
print $goal->rel($base), "\n";
../hi_there.jpg

If you start with normal strings, simplify this to URI->new($abs_goal)->rel($base), as shown here:

use URI;
my $base = 'http://phee.phye.phoe.fm/thingamajig/zing.xml';
my $goal = 'http://phee.phye.phoe.fm/hi_there.jpg';
print URI->new($goal)->rel($base), "\n";
../hi_there.jpg

Incidentally, the trailing slash in a base URL can be very important. Consider:

use URI;
my $base = 'http://phee.phye.phoe.fm/englishmen/blood';
my $goal = 'http://phee.phye.phoe.fm/englishmen/tony.jpg';
print URI->new($goal)->rel($base), "\n";
tony.jpg

But add a slash to the base URL and see the change:

use URI;
my $base = 'http://phee.phye.phoe.fm/englishmen/blood/';
my $goal = 'http://phee.phye.phoe.fm/englishmen/tony.jpg';
print URI->new($goal)->rel($base), "\n";
../tony.jpg

That's because in the first case, "blood" is not considered a directory, whereas in the second case, it is. You may be accustomed to treating /blood and /blood/ as the same, when blood is a directory. Web servers maintain your illusion by invisibly redirecting requests for /blood to /blood/, but you can't ever tell when this is actually going to happen just by looking at a URL.