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

How do I do this in Perl 5?

curl -s "http://usa.kaspersky.com/files/?file=kis&program=one&lang=en& +track=pu_kiskis_usen" -w %{redirect_url}

Replies are listed 'Best First'.
Re: URL Redirect
by Corion (Patriarch) on Sep 04, 2016 at 18:29 UTC

    If you want to eliminate the dependency on the curl executable, maybe take a look at Net::Curl (closest to Curl) or WWW::Mechanize (closer to emulating a real webbrowser) or HTTP::Tiny (make a simple HTTP request).

Re: URL Redirect
by hippo (Archbishop) on Sep 04, 2016 at 11:49 UTC

    You can run arbitrary commands with system:

    system ('curl -s "http://usa.kaspersky.com/files/?file=kis&program=one +&lang=en&track=pu_kiskis_usen" -w %{redirect_url}');
Re: URL Redirect
by Todd Chester (Scribe) on Sep 06, 2016 at 01:34 UTC

    Hi All, Thank you for the suggestions! I have never been able to figure out Net::Perl I should have been more specific. I use LWP::UserAgent a lot and would like to master redirect URL's with it. Problem: it just times out on me. And not the 20 seconds I asked for either. More like several minutes. And "$res->redirects" returns what looks like an reference address pointer I am doing something wrong. cat Url.Redirest.Test.pl

    #!/usr/bin/perl use strict; use warnings; #use diagnostics; #use diagnostics "-verbose"; use constant MaxTime1 => 20; # Seconds # use Net::Nslookup qw ( nslookup ); use LWP::UserAgent; # use LWP::Protocol qw ( https ); use Term::ANSIColor qw ( BOLD BLUE RED GREEN RESET ); my $Debug="yes"; sub GetUrlRedirect ( $$ ) { # Return $Url's redirected web page. Black string if none if locat +ed # Reference: http://stackoverflow.com/questions/26087546/perl-print +-the-redirected-url # system ('curl -s "SomeUrl" -w %{redirect_url}'); my $IAm = ( caller(0) )[3]; # Incoming: my $Url = $_[0]; my $Caller = "$_[1]" . "$IAm"; my $ua = LWP::UserAgent->new; $ua->timeout ( MaxTime1 ); $ua->show_progress; my $req = new HTTP::Request(GET => $Url); print STDERR "$Caller requesting $Url\n"; my $res = $ua->request($req); print STDERR "$Url redirects to $res->redirects\n"; if ( ! $res->is_success ) { print STDERR BOLD RED " ERROR ${Caller}: unable to obtain a redirect web page f +or ", $Url, RESET, "\n"; return ""; } else { if ( "$Debug" eq "yes" ) { print STDERR "RedirectUrl = <$res-> +redirects>\n"; } return $res->redirects; } } my $IAm = "UrlRedirectTest.pl "; my $WebSite = 'http://usa.kaspersky.com/files/?file=kis&program=on +e&lang=en&track=pu_kiskis_usen'; my $RedirectUrl = GetUrlRedirect ( $WebSite, $IAm ); print "WebSite $WebSite\nredirects to\n$RedirectUrl\n"; END

    UrlRedirectTest.pl main::GetUrlRedirect requesting http://usa.kaspersky.com/files/?file=kis&program=one&lang=en&track=pu_kiskis_usen http://usa.kaspersky.com/files/?file=kis&program=one&lang=en&track=pu_kiskis_usen redirects to HTTP::Response=HASH(0x24e9808)->redirects RedirectUrl = <HTTP::Response=HASH(0x24e9808)->redirects> WebSite http://usa.kaspersky.com/files/?file=kis&program=one&lang=en&track=pu_kiskis_usen redirects to 1

      and "$res->redirects" returns what looks like an reference address pointer I am doing something wrong

      You are trying to invoke a method call within a string. The method call will not execute and what you see displayed instead is the reference to the object ($res) on which the method would otherwise have been called. You could write it like this:

      print STDERR "$Url redirects to " . $res->redirects . "\n";

      which would be a general solution. However, we can see from the documentation that calling redirects on an HTTP::Response object returns a list, not a scalar. How you treat that will depend upon what you actually want this line of code to display. And what you want is not at all clear to me from the code you have provided.

      Maybe take a step back and explain precisely what it is you are trying to achieve here?

Re: URL Redirect
by Todd Chester (Scribe) on Sep 06, 2016 at 11:01 UTC

    Hi Hippo,

    I do not understand from your response why the LWP call takes five minutes to time out, instead of directly giving me the redirect URL

    What I am after is achieving with LWP what I can achieve with curl's "-w %{redirect_url}" function. I want to know what the redirect url is

    $ curl -s "http://usa.kaspersky.com/files/?file=kis&program=one&lang=e +n&track=pu_kiskis_usen" -w %{redirect_url}

    The response from curl is:

    https://klamericas.s3.amazonaws.com/files/one/en/kis17.0.0.611en_10755 +.exe

    and that response is precisely what I want from LWP.

    I have redone my code a bit, but am still getting the same time out and wrong answer back

    #!/usr/bin/perl use strict; use warnings; #use diagnostics; #use diagnostics "-verbose"; use constant MaxTime1 => 20; # Seconds # use Net::Nslookup qw ( nslookup ); use LWP::UserAgent; # use LWP::Protocol qw ( https ); use Term::ANSIColor qw ( BOLD BLUE RED GREEN RESET ); my $Debug="yes"; sub GetUrlRedirect ( $$ ) { # Return $Url's redirected web page. Black string if none if locat +ed # Reference: http://stackoverflow.com/questions/26087546/perl-print +-the-redirected-url # http://search.cpan.org/~ether/libwww-perl-6.15/lib/LWP +/UserAgent.pm # http://stackoverflow.com/questions/2470053/how-can-i-g +et-the-ultimate-url-without-fetching-the-pages-using-perl-and-lwp # https://metacpan.org/pod/HTTP%3A%3AResponse # system ('curl -s "SomeUrl" -w %{redirect_url}'); my $IAm = ( caller(0) )[3]; # Incoming: my $Url = $_[0]; my $Caller = "$_[1]" . "$IAm"; my $request; my $result; my $redirect = ""; my $ua = LWP::UserAgent->new; $ua->timeout ( MaxTime1 ); $ua->show_progress; # $ua->requests_redirectable( ); # to read $request = new HTTP::Request(GET => "$Url"); $result = $ua->request($request); $redirect = $result->redirects; print STDERR "result = <$result>\nredirect = <$redirect>\n"; if ( ! $result->is_success ) { print STDERR BOLD RED " ERROR ${Caller}: unable to obtain a redirect web page f +or ", $Url, RESET, "\n"; return ""; } else { if ( "$Debug" eq "yes" ) { print STDERR "RedirectUrl = <$redir +ect>\n"; } return $redirect; } } my $IAm = "UrlRedirectTest.pl "; my $WebSite = 'http://usa.kaspersky.com/files/?file=kis&program=on +e&lang=en&track=pu_kiskis_usen'; my $RedirectUrl = GetUrlRedirect ( $WebSite, $IAm ); print "\nWebSite $WebSite\nredirects to\n$RedirectUrl\n"; END

    $ ./Url.Redirest.Test.pl
    result = <HTTP::Response=HASH(0x289cb60)>
    redirect = <1>
    RedirectUrl = <1>

    WebSite http://usa.kaspersky.com/files/?file=kis&program=one&lang=en&track=pu_kiskis_usen redirects to
    1

      Here is a simplified script which prints the first redirect of a URL (because in the absense of any statement to the contrary this is what I think you are asking for).

      #!/usr/bin/env perl use strict; use warnings; use LWP::UserAgent; my $ua = LWP::UserAgent->new; my $src = 'http://google.com/'; my $res = $ua->get($src); my ($redirect) = $res->redirects; if (defined $redirect) { print "$src redirects to " . $redirect->header('Location') . "\n"; } else { print "$src has no redirect. It returned: " . $res->status_line . +"\n"; }

      I've used Google as the source because it works whereas your provided source has issues (which you could take up with them). I think that this is pretty clear and shows how the various methods may be used to obtain information of relevance to the programmer. Do read the documentation of the modules you are using.

Re: URL Redirect
by Todd Chester (Scribe) on Sep 06, 2016 at 11:45 UTC

    Thank you! I am about to try it.

    Question: what does the () in "my ($redirect) = $res->redirects;" do?

      HTTP::Response->redirects returns a list of redirects. You can either assign that list to an array or another list. The parentheses around $redirect tell Perl that you want $redirect to be seen as list as you in fact are only interested in the first redirect.

        I am still confused as to what
        my ( $NewUrl ) = $res->header('Location');
        exactly is.

        What exactly is "$res->header('Location')"? Is it a reference pointing to an array inside LWP?

        If I wanted to see the whole potato, why does
        my @Headres = @$res->header('Location')
        not work?

        How would I assign the whole potato to @Headers?

        I am confused.

        Many thanks,
        -T

Re: URL Redirect
by Todd Chester (Scribe) on Sep 06, 2016 at 11:59 UTC

    Hi Hippo,

    Would you subsitute "http://usa.kaspersky.com/files/?file=kis&program=one&lang=en&track=pu_kiskis_usen" for Google and see if there is a way around the extreme timeout? (curl is almost instant.)

    Many thanks,
    -T

      Please can you not start a new subthread when you are actually replying to someone else's post? See how each post has its own "reply" link on the right side? That's what you should be doing.

      The long time is taken on the redirected page. If you're not interested in that then make sure LWP never tries to load it. eg:

      #!/usr/bin/env perl use strict; use warnings; use LWP::UserAgent; my $ua = LWP::UserAgent->new; $ua->requests_redirectable ([]); my $src = 'http://usa.kaspersky.com/files/?file=kis&program=one&lang=e +n&track=pu_kiskis_usen'; my $res = $ua->get($src); if ($res->is_redirect) { print "$src redirects to " . $res->header('Location') . "\n"; } else { print "$src has no redirect. It returned: " . $res->status_line . +"\n"; }

      This returns in a second or two. I once more encourage you to read the documentation for LWP::UserAgent where all of this is explained.

        That did the trick. I was missing
        $ua->requests_redirectable ([]);
        Thank you!

        I do read the docs. I just don't understand what I am seeing, which I why I appreciate your help. (You will notice that I include my references in my code's comments)

        #!/usr/bin/perl use strict; use warnings; #use diagnostics; #use diagnostics "-verbose"; use constant MaxTime1 => 20; # Seconds use LWP::UserAgent; use Term::ANSIColor qw ( BOLD BLUE RED GREEN RESET ); my $Debug = "yes"; my $RedirectUrl; my $IAm = "UrlRedirectTest.pl "; my $WebSite; sub GetUrlRedirect ( $$ ) { # Return $Url's redirected web page. Black string if none if locat +ed # References: # http://stackoverflow.com/questions/26087546/perl-print-the-redi +rected-url # http://search.cpan.org/~ether/libwww-perl-6.15/lib/LWP/UserAgen +t.pm # http://stackoverflow.com/questions/2470053/how-can-i-get-the-ul +timate-url-without-fetching-the-pages-using-perl-and-lwp # https://metacpan.org/pod/HTTP%3A%3AResponse # $r->redirects # Returns the list of redirect responses that lead up to this + response # by following the $r->previous chain. The list order is olde +st first. # In scalar context return the number of redirect responses l +eading up # to this one. # # system ('curl -s "SomeUrl" -w %{redirect_url}'); my $IAm = ( caller(0) )[3]; # Incoming: my $Url = $_[0]; my $Caller = "$_[1]" . "$IAm"; # supposting variables my $ua; my $res; # my $redirect; # my $NewUrl; $ua = LWP::UserAgent->new; $ua->timeout ( MaxTime1 ); $ua->show_progress; $ua->requests_redirectable ([]); $res = $ua->get($Url); # The parentheses around $redirect tell Perl that you want $redirec +t # to be seen as list as you in fact are only interested in the firs +t redirec if ($res->is_redirect) { my ( $NewUrl ) = $res->header('Location'); # my $NewUrl = ( $res->header('Location') ) [1]; if ( "$Debug" eq "yes" ) { print STDERR "Redirect Url = <${NewUrl}>\n"; } return ${NewUrl}; } else { print STDERR "${Caller}: ${Url} has no redirect\n"; return ""; } } $WebSite = 'http://gbis.com'; $RedirectUrl = GetUrlRedirect ( $WebSite, $IAm ); print "WebSite <$WebSite> redirects to <$RedirectUrl>\n\n"; $WebSite = 'http://google.com'; $RedirectUrl = GetUrlRedirect ( $WebSite, $IAm ); print "WebSite <$WebSite> redirects to <$RedirectUrl>\n\n"; $WebSite = 'http://usa.kaspersky.com/files/?file=kis&program=one&lang= +en&track=pu_kiskis_usen'; $RedirectUrl = GetUrlRedirect ( $WebSite, $IAm ); print "WebSite <$WebSite> redirects to <$RedirectUrl>\n\n"; END $ ./Url.Redirest.Test.pl UrlRedirectTest.pl main::GetUrlRedirect: http://gbis.com has no redire +ct WebSite <http://gbis.com> redirects to <> Redirect Url = <http://www.google.com/> WebSite <http://google.com> redirects to <http://www.google.com/> Redirect Url = <https://klamericas.s3.amazonaws.com/files/one/en/kis17 +.0.0.611en_10755.exe> WebSite <http://usa.kaspersky.com/files/?file=kis&program=one&lang=en& +track=pu_kiskis_usen> redirects to <https://klamericas.s3.amazonaws.c +om/files/one/en/kis17.0.0.611en_10755.exe>
Re: URL Redirect
by Todd Chester (Scribe) on Sep 06, 2016 at 12:29 UTC

    Hi Hippo,

    The answer does come back correct, but it takes five minutes to time out.

    -T