http://qs321.pair.com?node_id=1167006

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

I hate this. Everything should be right but just isn't. The line right after "# Show this #!? cookie" displays the cookie fine. But the next request fails... Aaargh. I hate those stupid OO modules. Doing the "ugly hack way" works perfectly, see the second code snippet.

#!/usr/bin/perl use strict; use warnings; use 5.10.0; use Getopt::Long; use JSON::XS; use LWP::UserAgent; use HTTP::Cookies; use Term::ReadKey; use Data::Dumper; my $option; Getopt::Long::Configure('no_ignore_case'); unless ( GetOptions( 'help|h' => \$option->{help}, 'verbose|v' => \$option->{verbose}, 'username|U=s' => \$option->{username}, 'password|W=s' => \$option->{password}, 'api-key|k=s' => \$option->{apikey}, 'hostname|H=s' => \$option->{hostname}, ) ) { die "Fatal: invalid option \n"; } if ( $option->{help} ) { print <<EOL $0 options: --help | -h show this help --verbose | -v verbose --hostname | -H host to connect to (required) --api-key | -k API key to use (required) --username | -U username (required) --password | -W password --archive | -a archive name to search --arch-id | -A archive ID to display --metadata | -m metadata to search for EOL ; exit; } foreach my $param (qw(username apikey hostname)) { die "required option: $param\n" if not $option->{$param}; } if ( not $option->{password} ) { ReadMode('noecho'); print "Enter Password: "; chomp( $option->{password} = <STDIN> ); ReadMode('restore'); say ''; } my $cookie = HTTP::Cookies->new(); my $ua = LWP::UserAgent->new; $ua->ssl_opts( verify_hostname => 0 ); $ua->cookie_jar($cookie); my $credentials = encode_json( { 'login' => $option->{username}, 'password' => $option->{password}, 'apikey' => $option->{apikey} } ); say $credentials if $option->{verbose}; # Authentication my $request = HTTP::Request->new( POST => "https://$option->{hostname}/storiqone-backend/api/v1/auth +/" ); $request->content_type('application/json'); $request->content($credentials); my $result = $ua->request($request); if ( $result->is_success ) { say $result->decoded_content; } else { die "Error: " . $result->decoded_content . "\n" . $result->status_line . "\n"; } # Show this #!? cookie print Dumper $cookie if $option->{verbose}; # list archives $request = HTTP::Request->new( GET => "https://$option->{hostname}/storiqone-backend/api/v1/archi +ve/" ); $request->content_type('application/json'); $result = $ua->request($request); if ( $result->is_success ) { say $result->decoded_content; } else { die "Error: " . $result->decoded_content . "\n" . $result->status_line . "\n"; }

Here is the code snippet without HTTP::Cookies, that just frigging works :

# Save cookie my ( $cookie ) = ($result->header('Set-Cookie') =~ m((PHPSESSID=\w+);) +); say $cookie if $option->{verbose} ; # list archives $request = HTTP::Request->new( GET => "https://$option->{hostname}/storiqone-backend/api/v1/archi +ve/" ); $request->content_type('application/json'); $request->header('Cookie' => $cookie);

Replies are listed 'Best First'.
Re: LWP::UserAgent doesn't send my HTTP::Cookies
by shmem (Chancellor) on Jul 01, 2016 at 18:49 UTC

    The difference between the version which doesn't

    # Show this #!? cookie print Dumper $cookie if $option->{verbose}; # list archives $request = HTTP::Request->new( GET => "https://$option->{hostname}/storiqone-backend/api/v1/archi +ve/" ); $request->content_type('application/json');

    and the version which just frigging works

    # list archives $request = HTTP::Request->new( GET => "https://$option->{hostname}/storiqone-backend/api/v1/archi +ve/" ); $request->content_type('application/json'); $request->header('Cookie' => $cookie);

    is that in the former you don't add the cookie to the request header, but in the latter you do. What do you expect? Do you expect that $ua shoehorns its cookie-jar into the new HTTP::Request object? You are expecting too much magic, I guess ;-)

    perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'

      What do you expect? Do you expect that $ua shoehorns its cookie-jar into the new HTTP::Request object? You are expecting too much magic, I guess ;-)

      Yeah, $ua will absolutely take cookies from the cookiejar and add them to any requests, if they exist

        That's why I mention that the cookie is displayed, therefore it exists :)

      The LWP::UserAgent and lwpcook documentations seem to imply that yes, cookies are automagically inserted in headers if the cookie_jar has been set up.

      Of course adding explicitly the cookie object to the headers has absolutely no effect...

Re: LWP::UserAgent doesn't send my HTTP::Cookies (trace/debug)
by Anonymous Monk on Jul 01, 2016 at 19:40 UTC

    This is how you debug "LWP" stuff, run a program like this, study the output, share the output here , omit everything that isn't LWP related

    use WWW::Mechanize 1.75; my %urls = ( login => "https://$option->{hostname}/storiqone-backend/api/v1/auth/ +", list_archive => "https://$option->{hostname}/storiqone-backend/api/v +1/archive/", ); my $ua = WWW::Mechanize->new; $ua->add_handler("request_send", sub { shift->dump; return }); $ua->add_handler("response_done", sub { shift->dump; return }); $ua->post( $urls{login},, content_type => 'application/json', content => $credentials, ); print $ua->content, "\n"; $ua->post( $auth_url, content_type => 'application/json', content => $urls{list_archive}, ); print $ua->content, "\n"; __END__ ... output here ...