Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things

URL resolve (operations on path etc.)

by bliako (Monsignor)
on Jul 31, 2022 at 07:37 UTC ( [id://11145863]=perlquestion: print w/replies, xml ) Need Help??

bliako has asked for the wisdom of the Perl Monks concerning the following question:

Esteemed Monks,

I am trying to translate the following Node.js fragment to Perl (it takes a URL and sort of chdir to it, clever enough to remove endpoint if a file and query):

const url = require('url'); const x = 'http:/'; const y = '../../../'; console.log(url.resolve(x, y));

result is : http:/

Now, if x='http:/'; (i.e. the path points to a "directory" rather than to a "file") the result is http:/ (as expected IMO)

I tried to do this with URI but failed:

use URI; my $x = 'http:/'; my $y = '../../../'; my $u = URI->new($x); my $p = $u->path().'/'.$y; $u->path($p); print $u; <c> <p>With this result: <c>http:/

The Node.js version seems to be able to understand that the last segment before the query is a "file" and removes it. Then it does the merging of the two paths including successful relative operations (../). What is the safest way to achieve that behaviour in Perl? The last resort would be to shell-out to Node.js ...

bw, bliako

Replies are listed 'Best First'.
Re: URL resolve (operations on path etc.)
by haukex (Archbishop) on Jul 31, 2022 at 07:52 UTC
    use warnings; use strict; use URI; my $x = ''; my $y = '../../../'; my $u = URI->new($y); print $u->abs($x), "\n"; __END__

      Thanks haukex++ (I swear last night abs was not working!!!!!!)

      EDIT!: ouchhhh I was doing the reverse!!!!!:

      # this is wrong, note new($x)!! abs($y) it should be the reverse my $u = URI->new($x); # this is wrong print $u->abs($y), "\n"; # this is wrong

      Edit2: that's definetely an X-Y problem hehe

      Could this be resolved with a regex maybe? Like for example:

      #!/usr/bin/perl use strict; use warnings; my $PATH = '' . '/' . '/../../../ +'; $PATH =~ tr|/||s; my $PREV = 0; my $LEN; for (;;) { $PATH =~ s/\/[^\/]+\/\.\.//; $LEN = length($PATH); last if ($PREV == $LEN); $PREV = $LEN; } print $PATH;

      I put the regex in a for(;;) loop, because adding global flag didn't do what I want:

      $PATH =~ s/\/[^\/]+\/\.\.//g;

Re: URL resolve (operations on path etc.)
by Your Mother (Archbishop) on Jul 31, 2022 at 17:27 UTC

    haukex already solved it but this is the way I generally handle these. It lends itself to bulk changes; URI.

    ~>perl -MURI -E '$x = ""; $y = "../ +../../"; say URI->new_abs($y,$x);'

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11145863]
Approved by haukex
Front-paged by Corion
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (4)
As of 2024-04-25 14:14 GMT
Find Nodes?
    Voting Booth?

    No recent polls found