Perl AnyEvent::HTTP request using Proxy fails - perl

I tried using the perl module AnyEvent::HTTP to make asynchronous HTTP requests by following this post: http://www.windley.com/archives/2012/03/asynchronous_http_requests_in_perl_using_anyevent.shtml
However, I'm not able to get it working through proxies...
my $request;
my $host = '<userid>:<pswd>#<proxyip>';
my $port = '<proxyport>';
my $headers = { ...
'Accept-Language'=> 'en-us,en;q=0.5',
'Accept-Charset'=> 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
'Keep-Alive' => 300,
};
$request = http_request(
GET => $url,
timeout => 120, # seconds
headers => $headers,
proxy => [$host, $port],
mymethod
);
$cv->end;
$cv->recv;
I get the following error for the above code (after substituting with authentication details for the proxy)
{
'Reason' => 'No such device or address',
'URL' => 'www.google.com',
'Status' => 595
};
Without the proxy argument of the request, it works. From the CPAN page http://metacpan.org/pod/AnyEvent::HTTP,
595 - errors during connection establishment, proxy handshake
Please help me identify the problem with this code. Thanks!

You cant put your username and password in the $host itself. You need to first encode them in base64 by hand and add the resulting string in the Proxy-Authorization header.
$ echo -n user:pass | openssl enc -a
dXNlcjpwYXNz
Then add this line to your header:
my $request;
my $host = '<proxyip>'; #EDITED
my $port = '<proxyport>';
my $headers = { ...
'Accept-Language'=> 'en-us,en;q=0.5',
'Accept-Charset'=> 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
'Keep-Alive' => 300,
'Proxy-Authorization'=>'Basic dXNlcjpwYXNz' #EDITED
};
$request = http_request(
GET => $url,
timeout => 120, # seconds
headers => $headers,
proxy => [$host, $port],
mymethod
It should work then!

Related

How to Retrieve HTTP Status Code with Guzzle?

New to Guzzle/Http.
I have a API rest url login that answer with 401 code if not authorized, or 400 if missing values.
I would get the http status code to check if there is some issues, but cannot have only the code (integer or string).
This is my piece of code, I did use instruction here ( http://docs.guzzlephp.org/en/stable/quickstart.html#exceptions )
namespace controllers;
use GuzzleHttp\Psr7;
use GuzzleHttp\Exception\ClientException;
$client = new \GuzzleHttp\Client();
$url = $this->getBaseDomain().'/api/v1/login';
try {
$res = $client->request('POST', $url, [
'form_params' => [
'username' => 'abc',
'password' => '123'
]
]);
} catch (ClientException $e) {
//echo Psr7\str($e->getRequest());
echo Psr7\str($e->getResponse());
}
You can use the getStatusCode function.
$response = $client->request('GET', $url);
$statusCode = $response->getStatusCode();
Note: If your URL redirects to some other URL then you need to set false value for allow_redirects property to be able to detect initial status code for parent URL.
// On client creation
$client = new GuzzleHttp\Client([
'allow_redirects' => false
]);
// Using with request function
$client->request('GET', '/url/with/redirect', ['allow_redirects' => false]);
If you want to check status code in catch block, then you need to use $exception->getCode()
More about responses
More about allow_redirects
you can also use this code :
$client = new \GuzzleHttp\Client(['base_uri' 'http://...', 'http_errors' => false]);
hope help you

php 5.6 mail and SSL

I found myself unable to send mails since I upgraded to php5.6.
$to = "Test1 <*******#gmail.com>";
$body = "Hi,\n\n this is just test email";
$headers = array(
'From' => '*******#gmail.com',
'To' => $to,
'Subject' => 'test email'
);
$smtp = Mail::factory('smtp', array(
'host' => 'smtp.sendgrid.com',
'port' => '587',
'auth' => 'login',
'username' => '*****',
'password' => '*****',
));
$mail = $smtp->send($to, $headers, $body);
if (PEAR::isError($mail)) {
echo $mail->getMessage();
} else {
echo "<p> Message successfully sent!</p>";
}
login authentication failure [SMTP: STARTTLS failed (code: 220, response: Begin TLS negotiation now)]
If I use my Gmail account with this code, i get an error too
$smtp = Mail::factory('smtp',array (
'host' => 'ssl://smtp.googlemail.com',
'port' => '465',
'auth' => 'login',
'username' => '******#gmail.com',
'password' => '*******'
));
authentication failure [SMTP: Invalid response code received from server (code: 534, response: 5.7.14 Please log in via your web browser and 5.7.14 then try again. 5.7.14 Learn more at 5.7.14 https://support.google.com/mail/answer/78754 jz4sm22875767wjb.16 - gsmtp)]
I have an oid application running with ZF1, and I found that there was a problem on this call Zend_Mail_Protocol_Smtp :
stream_socket_enable_crypto($this->_socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)
I've read that some changes had been made in php 5.6 concerning OpenSSL, but I don't know what changes I need to do.
I had the same trouble and stumbled upon the solution, and these are clearly related to changes in PHP 5.6 (which I'm not all together happy about).
The verify_peer and verify_peer_name are now by default set to true - requiring an extra level of security between the two machines involved in a streamed port. I don't want this when I'm dealing with SMTP, the STARTTLS encryption is enough for me. So turn these off I added some code to the Net/SMTP.php file
$options = array('ssl' => array('verify_peer_name' => false, 'verify_peer' => false));
$result = $this->_socket->connect($this->host, $this->port, $persistent, $timeout, $options);
The socket timeout default specified in php.ini is not being used by this function. So I changed the default in 'smtp.php' to:
$timeout = 60; // previously null;
Hope that helps somebody else. Cheers Murray
I know that this question is kinda old but I will leave the answer here, maybe someone else will find it useful: https://stackoverflow.com/a/34090707/5639805

PERL Get_Server_Certificate certificate verify failed error

I'm receiving a certificate error when trying to send a POST message to a website.
The error I'm receiving:
LWP::Protocol::https::Socket: SSL connect attempt failed error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed at /usr/lib/perl5/site_perl/5.8.8/LWP/Protocol/http.pm line 49
The code that I'm using is:
my $webpage = "";
my $ua = LWP::UserAgent->new( );
$ua->agent('Mozilla');
$webpage = "https://mysite:444/myapp/app.aspx";
my $msg = 'An XML Message';
my $req = POST $webpage,
Content_Type => 'text/xml',
Content => $msg;
So far I've tried a few "fixes" that I've found online:
Tried disabling verify hostname through environment variable:
$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME}=0;
Tried disabling verify hostname through ssl_opts:
my $ua = LWP::UserAgent->new( ssl_opts => { verify_hostname => 0 }, );
Tried using the Mozilla CA and setting HTTPS_CA_FILE to /usr/lib/perl5/site_perl/5.8.8/Mozilla/CA/cacert.pem?
At this point I'm out of options to try so I'm hoping someone has run into this problem before and can provide assistance.
It's just a typo, use "verify_hostname" without the "s":
my $ua = LWP::UserAgent->new( ssl_opts => { verify_hostname => 0 }, );

Perl and LWP not authenticating

I'm trying to get an LWP request working to an https server. I have been given a user & pass, advised to use basic authentication. I've tried various chunks of code, and all seem to get an authentication error. My current code is...
use warnings;
use strict;
use Data::Dumper;
use LWP;
my $ua = LWP::UserAgent->new( keep_alive => 1 );
##also tried by $ua->credentials('domain','','user','pass');
##not sure if I need 'realm' or how I get it, as no popup on screen.
my $request = HTTP::Request->new( GET => "https://my.url.com/somepath/" );
$request->authorization_basic('myuser','mypass');
$request->header( 'Cache-Control' => 'no-cache' );
print $response->content;
print Dumper $response;
The server gives a security error, but if I look at a dump of $response, I see the following...
'_rc' => '401',
'_headers' => bless( { .... lots of stuff
'title' => 'Security Exception',
'client-warning' => 'Missing Authenticate header',
'client-ssl-socket-class' => 'IO::Socket::SSL',
...
'expires' => '-1'
}, 'HTTP::Headers' ),
'_msg' => 'Unauthorized',
'_request' => bless( {
'_content' => '',
'_uri' => bless( do{\(my $o = 'https:theurlabove')}, 'URI::https' ),
'_method' => 'GET',
'_uri_canonical' => $VAR1->{'_request'}{'_uri'}
'_headers' => bless( {
'user-agent' => 'libwww-perl/6.04',
'cache-control' => 'no-cache',
'authorization' => 'Basic dzx..........'
}, 'HTTP::Headers' ),
I'm trying to understand whats happening, it looks like in the original request, it has the headers in there, but in the response, its saying I'm 'Missing Authenticate Header'.
Is there something amiss with the code, or something I'm misunderstanding with the request/respinse ?
Thanks.
The "Missing Authenticate header" message is coming from LWP itself. This means that it couldn't find an authenticate header in the target response. This might mean that your proxy settings are misconfigured, if you have anything like that.
I don't know if this is what you are looking for but I came across the same problem trying to authenticate to a webpage and had to solve it with WWW::Mechanize. I had to go to the first page and login then request the page I wanted.
use WWW::Mechanize;
my $loginPage = "http://my.url.com/login.htm"; # Authentication page
my $mech = WWW::Mechanize->new(); # Create new brower object
$mech->get($loginPage); # Go to login page
$mech->form_name('LogonForm'); # Search form named LogonForm
$mech->field("username", myuser); # Fill out username field
$mech->field("password", mypass); # Fill out password field
$mech->click("loginloginbutton"); # submit form
$mech->get("http://my.url.com/somepath/"); # Get webpage
# Some more code here with $mech->content()

Logging into Jenkins via Perl script

I am able to change a build's description with the following program. This will change the build's description to "FOO FOO FOO". Unfortunately, my login doesn't work. Right now, this test Jenkins build server has no security on it. However, on our regular Jenkins server, you need to be logged in to change a build's description.:
#! /usr/bin/env perl
use 5.12.0;
use warnings;
use LWP::UserAgent;
use HTTP::Request::Common qw(POST);
use Data::Dumper;
use constant {
JENKINS_BASE => "http://build.vegibank.com/",
USER_ID => "buildguy",
PASSWORD => "swordfish",
};
use constant {
LOGIN_URL => JENKINS_BASE . '/j_acegi_security_check',
JOB_URL => JENKINS_BASE . '/job',
SUBMIT_DESCRIPTION => 'submitDescription',
};
my $job_number = 4;
my $job_name = "proginator-2.0";
my $description = "FOO FOO FOO";
my $user_agent = LWP::UserAgent->new or die qq(Can't get User Agent);
#
# My Login Stuff (but it doesn't do anything w/ security off
#
my $response = $user_agent->request (
POST LOGIN_URL,
[
j_username => USER_ID,
j_password => PASSWORD,
],
);
$response = $user_agent->request (
POST "#{[JOB_URL]}/$job_name/$job_number/#{[SUBMIT_DESCRIPTION]}",
[
description => "$description",
],
);
I'm trying to connect to the Jenkins login session, but I don't believe I'm doing it quite right. When I attempt to login, I get a 302 response and the following dump of my response object:
$VAR1 = bless( {
'_protocol' => 'HTTP/1.1',
'_content' => '',
'_rc' => '302',
'_headers' => bless( {
'connection' => 'close',
'client-response-num' => 1,
'set-cookie' => 'JSESSIONID=1D5DF6FAF8714B2ACA4D496FBFE6E983; Path=/jenkins/; HttpOnly',
'location' => 'http://build.vegicorp.com/;jsessionid=1D5DF6FAF8714B2ACA4D496FBFE6E983',
'date' => 'Mon, 13 May 2013 20:02:35 GMT',
'client-peer' => '10.10.21.96:80',
'content-length' => '0',
'client-date' => 'Mon, 13 May 2013 20:02:35 GMT',
'content-type' => 'text/plain; charset=UTF-8',
'server' => 'Apache-Coyote/1.1'
}, 'HTTP::Headers' ),
'_msg' => 'Moved Temporarily',
'_request' => bless( {
'_content' => 'j_username=buildguy&j_password=swordfish',
'_uri' => bless( do{\(my $o = 'http://build.vegicorp.com/j_acegi_security_check')}, 'URI::http' ),
'_headers' => bless( {
'user-agent' => 'libwww-perl/6.03',
'content-type' => 'application/x-www-form-urlencoded',
'content-length' => 42
}, 'HTTP::Headers' ),
'_method' => 'POST',
'_uri_canonical' => $VAR1->{'_request'}{'_uri'}
}, 'HTTP::Request' )
}, 'HTTP::Response' );
I figure I must be hitting a valid page since I'm getting a 302 code, but my fields might not be correct (or I'm going to the wrong page).
Can anyone help?
My authorization is failing because ...what is the technical term? Oh yeah... "doing it all wrong."
After Googling and getting a lot of unhelpful junk, I, on a lark, decided to see if the Jenkins website might have something on this. And, it did right under a page called Authenticating scripted clients. In fact, they even give a Perl LWP example for a scripted client.
Ha ha, I was trying too hard. It seems that Jenkins will use the basic HTTP authentication mechanism, and I don't have to go through conniptions trying to figure out how their login form works. Apparently, Jenkins is simplifying the basic authentication mechanism for you even if your authentication mechanism is far from basic -- like a good program should do.
So, all I had to do was use the basic authentication mechanism.
my $browser = LWP::UserAgent->new or die qq(Cannot get User Agent);
my $request = HTTP::Request->new;
$request->authorization_basic(USER_ID, PASSWORD);
$request->method("GET");
$request->url("$jenkins_url");
my $response = $browser->request($request);
if ( not $response->is_success ) {
die qq(Something went horribly wrong...);
}
I've seen the redirect when the login is successful -- it sets the session cookie and redirects you to the main page.
Your post might be failing because the UA object isn't persisting the session cookie. Per the documentation, 'The default is to have no cookie_jar, i.e. never automatically add "Cookie" headers to the requests.' Try:
my $ua = LWP::UserAgent->new( cookie_jar => HTTP::Cookies->new() );
To store and reuse your session for the description change post.
(Also, credentials are visible in your header dump, may want to edit... Edit: I'm an idiot, they're in your constants too and're likely fake.)