Get access token in perl - perl

There is a working sample of getting token in bash
response=$(curl --fail --silent --insecure --data "username=test&password=test" \
--header "Authorization: Basic Y2xvdWQtYmVzcG9rZTo=" \
-X POST "https://lab7.local:8071/auth/token?grant_type=password")
token=`echo "$response" | awk '/access_token/{print $NF}' |sed 's/\"//g'`
echo $token
I'm trying to translate it in perl, but getting code 400
#!/usr/bin/env perl
use strict;
use warnings;
use HTTP::Request;
use LWP::UserAgent;
use LWP::Simple;
use JSON::XS;
use Try::Tiny;
my $ua = LWP::UserAgent->new;
my $req = HTTP::Request->new(POST => "https://lab7.local:8071/auth/token?grant_type=password");
my $post_data = "username=test&password=test";
$req->content($post_data);
my $resp = $ua->request($req);
if ($resp->is_success) {
my $mess = $resp->decoded_content;
print "$mess\n";
} else {
my $code = $resp->code;
print $code;
}

Your curl version is sending an Authentication header that is missing from the Perl version. You should add that.
$req->header(Authorization => 'Basic Y2xvdWQtYmVzcG9rZTo=');

You're adding a basic auth header, with a username. That string is just the base 64 encoded equivalent.
So you should probably include this in your LWP:
$req -> authorization_basic ( 'cloud-bespoke' );
And it should work.

Related

Curl to Perl HTTP Request

Guys I need this curl request be translated to LWP::UserAgent HTTP Request
echo 'test{test="test"} 3' | curl -v --data-binary #- http://localhost:9090/api/metrics
What I've tried is this :
my $ua = LWP::UserAgent->new;
my $res = $ua->post('http://localhost:9090/api/metrics', ['test{test="test"}' => 3]);
die Dumper $res
But the response says
'_rc' => '400',
'_msg' => 'Bad Request',
'_content' => 'text format parsing error in line 1: unexpected end of input stream
You can try use the following POST request:
use feature qw(say);
use strict;
use warnings;
use LWP::UserAgent;
my $ua = LWP::UserAgent->new();
my $res = $ua->post('http://localhost:9090/api/metrics', Content => 'test{test="test"} 3');
if ($res->is_success) {
say $res->decoded_content;
}
else {
die $res->status_line;
}
And, since you didn't ask, here's a Mojo example:
use v5.10;
use Mojo::UserAgent;
my $ua = Mojo::UserAgent->new();
my $tx = $ua->post(
'http://httpbin.org/post',
=> 'test{test="test"} 3'
);
if ($tx->result->is_success) {
say $tx->result->body;
}
else {
die $tx->result->code;
}
It's basically the same as LWP except that Mojo returns a transaction object so you can play with the request too. It's something I wanted in LWP even before Mojo existed.

Correct way of rewriting `curl ...` to perl

I wrote a program that requests the source and the response header of a webpage, now I need it to run cross platform. I used the external command curl (in linux) to achieve it. I get the source like this::
#!/usr/bin/perl -w
use strict;
#declaring variables here#
my $result = `curl 'https://$host$request' -H 'Host: $host' -H 'User-Agent: $useragent' -H 'Accept: $accept' -H 'Accept-Language: $acceptlanguage' --compressed -H 'Cookie: $cookie' -H 'DNT: $dnt' -H 'Connection: $connection' -H 'Upgrade-Insecure-Requests: $upgradeinsecure' -H 'Cache-Control: $cachecontrol'`;
print "$result\n";
And the response header like this:
#!/usr/bin/perl -w
use strict;
#declaring variables here#
my $result = `curl -I 'https://$host$request' -H 'Host: $host' -H 'User-Agent: $useragent' -H 'Accept: $accept' -H 'Accept-Language: $acceptlanguage' --compressed -H 'Cookie: $cookie' -H 'DNT: $dnt' -H 'Connection: $connection' -H 'Upgrade-Insecure-Requests: $upgradeinsecure' -H 'Cache-Control: $cachecontrol'`;
print "$result\n";
These work fine, but I need to call these in perl and not as external commands.
I wrote some code using LWP::UserAgent to get the source:
#!/usr/bin/perl -w
use strict;
use LWP::UserAgent;
#declaring variables here#
my $ua = LWP::UserAgent->new;
my $req = HTTP::Request->new(GET => "https://$host$request HTTP/1.1");
$req->header('Host' => "$host");
$req->header('User-Agent' => "$useragent");
$req->header('Accept' => "$accept");
$req->header('Accept-Language' => "$acceptlanguage");
$req->header('Accept-Encoding' => "$acceptencoding");
$req->header('Cookie' => "$cookie");
$req->header('DNT' => "$dnt");
$req->header('Connection' => "$connection");
$req->header('Upgrade-Insecure-Requests' => "$upgradeinsecure");
$req->header('Cache-Control' => "$cachecontrol");
my $resp = $ua->request($req);
if ($resp->is_success) {
my $message = $resp->decoded_content;
print "$message\n";
}
This sometimes runs fine, but sometimes decoded_content returns nothing, I do get a response and i can print it using content, but its still encoded.
And requesting response headers using LWP::UserAgent is not possible so I wrote the request using Net::HTTP:
#!/usr/bin/perl -w
use strict;
use Net::HTTP;
#declaring variables here#
my $s = Net::HTTP->new(Host => "$host") || die $#;
$s->write_request(GET => "$request", 'Host' => "$host", 'User-Agent' => "$useragent", 'Accept' => "$accept", 'Accept-Language' => "$acceptlanguage", 'Accept-Encoding' => "$acceptencoding", 'Cookie' => "$cookie", 'DNT' => "$dnt", 'Connection' => "$connection", 'Upgrade-Insecure-Requests' => "$upgradeinsecure", 'Cache-Control' => "$cachecontrol");
my #headers;
while(my $line = <$s>) {
last unless $line =~ /\S/;
push #headers, $line;
}
print #headers;
This returns
HTTP/1.1 302 Found
Content-Type: text/html; charset=UTF-8
Connection: close
Content-Length: 0
Is the problem with my syntax of am I using the wrong tools? I know that WWW::Curl::Easy can request the source and the header at the same time, but I don't know how to pass my variables to its request. Could someone tell me what the problem is or just rewrite these requests correctly using the same variables with WWW:Curl::Easy? I'd appreciate a solution using WWW::Curl::Easy. Thanks in advance.
You can get the response headers in a couple of ways with LWP. Demonstrated here:
use LWP::UserAgent;
my($host,$request) = ('example.com', '/my/request');
my #header=( [Host => $host],
['User-Agent' => 'James Bond 2.0'],
[Accept => 'text/plain'],
[Cookie => 'cookie=x'],
);
my $ua = LWP::UserAgent->new;
my $req = HTTP::Request->new(GET => "https://$host$request"); #dont add HTTP/1.1
$req->header(#$_) for #header;
my $resp = $ua->request($req);
if ($resp->is_success) {
my %h; $resp->headers->scan( sub{ $h{shift()}=shift() } );
printf "Header name: %-30s Value: %-30s\n", $_, $h{$_} for sort keys %h;
print "\n<<<".$resp->headers()->as_string.">>>\n\n"; #all header lines in one big string
print $resp->header('Content-Type'),"\n\n"; #get one specific header line
my $content = $resp->decoded_content;
print "$content\n";
}
Note: "HTTP/1.1" should not be a part of the string after GET =>.
And with calling curl as a sub process you don't need to call it twice. You can get both headers and content at once by using -i like this:
my $response = ` curl -s -i "http://somewhere.com/path" -H 'User-Agent: Yes' `;
my($headers,$content) = split /\cM?\cJ\cM?\cJ/, $response, 2;
print "Headers: <<<$headers>>>\n\n";
print "Content: <<<$content>>>\n\n";

How to make the post request in BOX API using LWP::UserAgent?

I have tried the following code
my $url = "https://api.box.com/2.0/users/";
use strict;
use warnings;
use LWP::UserAgent;
use HTTP::Request::Common qw{ POST };
use CGI;
my $ua = LWP::UserAgent->new();
my $request = POST( $url, [ 'name' => 'mkhun', 'is_platform_access_only' => 'true',"Authorization" => "Bearer <ACC TOK>" ] );
my $content = $ua->request($request)->as_string();
my $cgi = CGI->new();
print $cgi->header(), $content;
The above code always give the 400 error. And throwing the
{"type":"error","status":400,"code":"bad_request","context_info":{"errors":[{"reason":"invalid_parameter","name":"entity-body","message":"Invalid value 'is_platform_access_only=true&Authorization=Bearer+WcpZasitJWVDQ87Vs1OB9dQedRVyOrs6&name=mkhun'. Entity body should be a correctly nested resource attribute name\/value pair"}]},
I don't know what is the issue. The same thing with Linux curl is working.
curl https://api.box.com/2.0/users \
-H "Authorization: Bearer <TOKEN>" \
-d '{"name": "Ned Stark", "is_platform_access_only": true}' \
-X POST
The Box API documentation says:
Both request body data and response data are formatted as JSON.
Your code is sending form-encoded data instead.
Also, it looks like Authorization is supposed to be an HTTP header, not a form field.
Try this instead:
use strict;
use warnings;
use LWP::UserAgent;
use JSON::PP;
my $url = "https://api.box.com/2.0/users/";
my $payload = {
name => 'mkhun',
is_platform_access_only => \1,
};
my $ua = LWP::UserAgent->new;
my $response = $ua->post(
$url,
Authorization => 'Bearer <TOKEN>',
Content => encode_json($payload),
);

Send a file with payload using curl in Perl

I am trying to post an image to tinyping.com, but I need this to be done inside PERL without shelling out to curl. This command works great.
curl -i --user api:****** --data-binary #myImage.png https://api.tinypng.com/shrink
How would I express this using LWP library in Perl? I am very basic in Perl.
So far I have:
use LWP::UserAgent;
use MIME::Base64;
my $img_target_dir = ...;
my $imgname = ...;
####
#not sure if i need to convert to BASE64
open (IMAGE, "$img_target_dir$imgname") or die "$!";
$raw_string = do{ local $/ = undef; <IMAGE>; };
$encoded = MIME::Base64::encode_base64( $raw_string );
####
my $content = post(
"https://api:***************************\#api.tinypng.com/shrink",
Content_Type => 'image/png',
Content =>[
]
) or die print "failure\n";
I ended up just shelling out to curl. Works great.
###### tinyPNG.com ######
my #file = "$img_target_dir$imgname";
print "Sending the PNG for compression at tinyPNG.com\n";
my $curl = `/usr/local/bin/curl -ki --user api:**************** --data-binary #"#file" https://api.tinypng.com/shrink`;
$curl=~ /Location: (.*)/;
my $url = "$1";
print "Image Compressed At: $url</b>\n";
my $curl2 = `/usr/local/bin/curl -k "$url" > "#file"`;
chmod(0775, "#file");
#########################

net::oauth return 401 unauthorized even though curl works

I am attempting to request a token from https://launchpad.net, according to the docs all it wants is a POST to /+request-token with the form encoded values of oauth_consumer_key, oauth_signature, and oauth_signature_method. Providing those items via curl works as expected:
curl --data "oauth_consumer_key=test-app&oauth_signature=%26&oauth_signature_method=PLAINTEXT" https://launchpad.net/+request-token
However, when i attempt to do it through my perl script it is giving me a 401 unauthorized error.
#!/usr/bin/env perl
use strict;
use YAML qw(DumpFile);
use Log::Log4perl qw(:easy);
use LWP::UserAgent;
use Net::OAuth;
$Net::OAuth::PROTOCOL_VERSION = Net::OAuth::PROTOCOL_VERSION_1_0A;
use HTTP::Request::Common;
use Data::Dumper;
use Browser::Open qw(open_browser);
my $ua = LWP::UserAgent->new;
my ($home) = glob '~';
my $cfg = "$home/.lp-auth.yml";
my $access_token_url = q[https://launchpad.net/+access-token];
my $authorize_path = q[https://launchpad.net/+authorize-token];
sub consumer_key { 'lp-ua-browser' }
sub request_url {"https://launchpad.net/+request-token"}
my $request = Net::OAuth->request('consumer')->new(
consumer_key => consumer_key(),
consumer_secret => '',
request_url => request_url(),
request_method => 'POST',
signature_method => 'PLAINTEXT',
timestamp => time,
nonce => nonce(),
);
$request->sign;
print $request->to_url;
my $res = $ua->request(POST $request->to_url, Content $request->to_post_body);
my $token;
my $token_secret;
print Dumper($res);
if ($res->is_success) {
my $response =
Net::OAuth->response('request token')->from_post_body($res->content);
$token = $response->token;
$token_secret = $response->token_secret;
print "request token ", $token, "\n";
print "request token secret", $token_secret, "\n";
open_browser($authorize_path . "?oauth_token=" . $token);
}
else {
die "something broke ($!)";
}
I tried both with $request->sign and without it as i dont think that is required during the request token phase. Anyway any help with this would be appreciated.
Update, switched to LWP::UserAgent and had to pass in both POST and Content :
my $res = $ua->request(POST $request->to_url, Content $request->to_post_body);
Thanks
Sorry I'm not able to verify from my tablet but with recent Perl you should install and use
use LWP::Protocol::https;
http://blogs.perl.org/users/brian_d_foy/2011/07/now-you-need-lwpprotocolhttps.html