Curl api parsing - perl

Am trying to parse curl api
but am getting this error 401 Unauthorized
i don't know where is the problem comes from.
because the authentication details are ok
this is the curl
curl 'https://api.twilio.com/2010-04-01/Accounts/SID/Messages.json' \
-X POST \
--data-urlencode 'To=whatsapp:+123456789' \
--data-urlencode 'From=whatsapp:+1234567890' \
--data-urlencode 'Body=Your Yummy Cupcakes Company order of 1 dozen frosted cupcakes has shipped and should be delivered on July 10, 2019. Details: http://www.yummycupcakes.com/' \
-u SID:[AuthToken]
#!/usr/bin/perl
use strict;
use warnings;
use HTTP::Tiny;
use JSON;
use Data::Dumper;
my $url = "https://api.twilio.com/2010-04-01/Accounts/SID/Messages.json";
my $json = encode_json {
To => 'whatsapp:+256775562361',
From => 'whatsapp:+14155238886',
Body => 'new test msg',
};
my $http = HTTP::Tiny->new(
default_headers => {
Authorization => 'SID:TOKEN',
}
);
my $response = $http->post( $url => {
content => $json,
headers => { 'Content-Type' => 'application/json' },
});
if ( $response->{'is_success'} ) {
print Dumper( decode_json $response->{'content'} );
} else {
print "$response->{'status'} $response->{'reason'}\n";
}

The format of the "Authorization" header isn't <user>:<pass> -- it's <auth-scheme> <authorization-parameters>. curl is doing this for you, but for this it's basically:
Authorization: Basic <mime-encoded "<user>:<pass>">
I use the URI module for this:
my $uri = URI->new("https://api.twilio.com/...");
$uri->userinfo("$sid:$auth");
$http->post( $uri => ... );

Related

CURL example to Invoke-RestMethod

I am trying to convert curl command to powershell Invoke-RestMethod
Command from MobileIron (in case someone will google that topic)
curl --user <username>:<password> --header 'Content-Type: application/json' --request PUT 'https://
<mobileiron_core>/api/v2/devices/wakeup?adminDeviceSpaceId=1' --data '{"deviceUuids": ["af0cea8bf56c-
49f5-b615-76cc34936b2f"], "note": "something"}'
Ok, my code (based on https://gist.github.com/rayterrill/e83a1bd877547eccfd59b656e7f91b48#file-mobileiron-addremovelabels-ps1 )
$url = $mi_server + "/api/v2/devices/wakeup?adminDeviceSpaceId=1"
$contentType = "application/json"
$headers = #{
Authorization=("Basic {0}" -f $regase64AuthInfo)
}
$data = #{
note = "test";
deviceUuids = $guid
};
$json = $data | ConvertTo-Json;
Invoke-RestMethod -Method PUT -Uri $url -ContentType $contentType -Headers $headers -Body $data;
But i am getting 400 error - so,as i understand - something wrong with --data , but what ?
MobileIron 400 is a general error: 400 Bad request, Meaning the request was invalid.
The accompanying error message (That follows the the error code) explains the reason.
Can you post the rest of the error message?
You cannot use --data or -Body with a PUT request.
You must make a query string for the data.
The query string must be url encoded.
Because it is HTTPS transfer you may need -k (--insecure)
The PUT request may work, I believe MobileIron prefers GET, There is no real difference between the two. I tested both.
I tried (I did my testing with PHP)
A PUT Request
Request Headers
Content-Type: application/json
Accept: application/json
POST DATA was the same as the Query String
I checked with and without the POST DATA and no change.
I also sent the POST DATA with no query string and it was if not data was sent.
URL and Query
$query = urlencode('{"deviceUuids": ["af0cea8bf56c-49f5-b615-76cc34936b2f"], "note": "something"}');
$url = https://<domain>/api/v2/devices/wakeup? . $query
URL was changed to my server to an app that returns the request header, and parameters.
Which returned this on the server:
Request Headers:
Content-Type: application/json
Accept: application/json
Accept-Encoding: deflate, gzip, br
Expect: 100-continue
Host: mydomain.com
Transfer-Encoding: chunked
The server GET and server REQUEST values
$_GET
array (
'{"deviceUuids":_' =>
array (
'"af0cea8bf56c-49f5-b615-76cc34936b2f"' => '',
),
)
$_REQUEST
array (
'{"deviceUuids":_' =>
array (
'"af0cea8bf56c-49f5-b615-76cc34936b2f"' => '',
),
)
The Request Query
$_SERVER['QUERY_STRING']) (url decoded)
{"deviceUuids": ["af0cea8bf56c-49f5-b615-76cc34936b2f"], "note": "something"}
Notice above the JSON query string was cut off.
But was in the arguments
argv array (url decoded)
0 = {"deviceUuids":
1 = ["af0cea8bf56c-49f5-b615-76cc34936b2f"],
2 = "note":
3 = "something"}
I removed the Content-Type: application/json from the request header and there was no change.
I changed the PUT to GET, no change
When a I started sending the Content=Type: application/json
With a POST request, and no Query String, the POS Data was ONLY in the BODY of the request.
And here are some example requesst from some MobileIron documentation:
The first request was a default GET not a PUT.
curl -u admin_username:admin_password -kv "https://URL_to_your_mobileiron_cloud_environment/api/v1/account?emailAddress=johnnydoe#acme.com&uid=johnnydoe#acme.com&accountSource=Local" -d ''
curl GET -kv -u user:password "https://[mobileiron_cloud]/api/v1/device/57d9903c-aadf-4b40-aef3-e1f24302f180/customattributes”
curl -X POST -kv -u user:password -H 'Content-Type: application/json' -d '{ "attrs" : { "tlark" : [ "1" ] } } ' "https://[mobileiron_cloud]/api/v1/device/22000/customattributes"
curl -X POST -kv -u user:password -H 'Content-Type: application/json' -d '{ "attrs" : { "tlark" : [ "1" ] } } ' "https://[mobileiron_cloud]/api/v1/device/8bcc4cee-dca9-476d-8710-9bb1e738ade9/customattributes"
$param_pam_pam = #{
Method = 'PUT'
Uri = "$url"
ContentType = "application/json"
Headers = #{authorization = ("Basic {0}" -f $regase64AuthInfo) }
Body = #{
deviceUuids = #($guid)
note = "force check-in from $ma"
} | ConvertTo-Json
}
$reg = Invoke-RestMethod #param_pam_pam

Translate a curl request in rest::client Perl

This curl line works perfectly :
curl -v -H "Content-Type: application/json" -k -d "{\"UserName\":\"test\",\"Password\":\"test\"}" -X POST "https://xxx.xxx.xxx.xxx/redfish/v1/SessionService/Sessions"
but when trying to translate into Perl, I've a http 500 error code in response.
Here an excerpt of my code :
$CLIENT=REST::Client->new(
{
host => $HOSTURL,
timeout => 300,
}
);
# Formatage de la requete
$URL = "/redfish/v1/SessionService/Sessions";
$ACTION = "POST";
%CONTENT_JSON = (
'UserName' => 'test',
'Password' => 'test'
);
%SESS_HEADERS = (
'Content-Type' => 'application/json',
);
$CONTENT_JSON = encode_json(\%CONTENT_JSON);
# Lancement de la requete
print Dumper $ACTION,$URL,$CONTENT_JSON,\%SESS_HEADERS;
$CLIENT->request($ACTION,$URL,$CONTENT_JSON,\%SESS_HEADERS);
$REPCODE = $CLIENT->responseCode();
print Dumper $REPCODE;
print Dumper $CLIENT->responseContent();
exit;
and the results :
$VAR1 = 'POST';
$VAR2 = '/redfish/v1/SessionService/Sessions';
$VAR3 = '{"UserName":"test","Password":"test"}';
$VAR4 = {
'Content-Type' => 'application/json'
};
$VAR1 = 500;
$VAR1 = 'Can\'t connect to xxx.xxx.xxx.xxx:443
So, where am I wrong ?
This looks like a clue:
$VAR1 = 'Can\'t connect to xxx.xxx.xxx.xxx:443
Are you sure that you've got the correct domain name? And does the resource work over HTTPS?
Oh and I bet REST::Client uses LWP::UserAgent, so you'll need LWP::Protocol::https installed as well.

Unable to post messages using Mailbox API and Mojo::UserAgent

According to the API docs (https://documentation.mailgun.com/api-sending.html) all the relevant parameters are supplied, but it gives me
400 response: BAD REQUEST
Here's my piece of code:
#!/usr/bin/perl
use Mojo::UserAgent;
use MIME::Base64;
use JSON qw(to_json);
use strict;
use warnings;
use v5.10;
my $ua = Mojo::UserAgent->new;
my $endpoint = 'https://api.mailgun.net/v3/sandbox2ad5b70fd744416ea7ff3d5422YYYYYY.mailgun.org/messages';
my $key = 'key-d3d8d350d4ef9c92349df62208XXXXXX';
my $headers = { 'Authorization' => 'Basic ' . encode_base64('api:' . $key) };
my $params = {
'to' => 'abc#domain.ru',
'subject' => 'testing',
'text' => 'some text',
'from' => 'postmaster#sandbox2ad5b70fd744416ea7ff3d5422YYYYYY.mailgun.org'
};
my $tx = $ua->post($endpoint, $headers, json => $params);
my $res = $tx->success;
if ($res) {
say $res->body;
} else {
my $err = $tx->error;
die "$err->{code} response: $err->{message}" if $err->{code};
die "Connection error: $err->{message}";
}
I have Mojo version as follows:
CORE
Perl (v5.22.1, linux)
Mojolicious (7.26, Doughnut)
OPTIONAL
EV 4.0+ (4.22)
IO::Socket::Socks 0.64+ (0.67)
IO::Socket::SSL 1.94+ (2.024)
Net::DNS::Native 0.15+ (n/a)
I wrote another version of this script using LWP::UserAgent and it works fine.
Are there some Mojo::UserAgent experts who might have an idea of what is wrong with the script?
UPDATED
Here's my LWP::UserAgent version which works without problems:
my ($key, $domain, $from, $from_name, $to, $subject, $comments) = #_;
my $url = 'https://api.mailgun.net/v3';
$url = $url . '/' . $domain . '/messages';
my $ua = LWP::UserAgent->new;
$ua->default_header('Authorization' => 'Basic ' . encode_base64('api:' . $key));
my $data = {
to => $to,
subject => $subject,
text => $comments,
from => $from_name . '<' . $from . '>'
};
my $r = $ua->post($url, Content => $data);
my $rc = $r->code;
if ($rc == 200) {
my $hash = from_json($r->decoded_content);
say $hash->{id};
say $hash->{message};
} else {
return { error => $rc };
}
UPDATED ON 25.02.2017
I used fake requests to my localhost:9000. Here's what I've traced using nc -l 9000:
POST / HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Authorization: Basic YXBpOmtleS1kM2Q4ZDM1MGQ0ZWY5YzkyMzQ5ZGY2MjIwOGRXXXXXX==
Host: localhost:9000
User-Agent: libwww-perl/6.15
Content-Length: 144
Content-Type: application/x-www-form-urlencoded
text=%3Chtml%3E%3Cbody%3E%3Cp%3Etest%3C%2Fp%3E%3C%2Fbody%3E%3C%2Fhtml%3E&from=John%3Clala%40ya.ru%3E&to=zozoba29a%40yandex.ru&subject=My+Subject
And:
POST / HTTP/1.1
Host: localhost:9000
Accept-Encoding: gzip
Content-Type: application/x-www-form-urlencoded
Authorization: Basic YXBpOmtleS1kM2Q4ZDM1MGQ0ZWY5YzkyMzQ5ZGY2MjIwOGRjXXXXXX==
Content-Length: 144
User-Agent: Mojolicious (Perl)
from=John%3Clala%40ya.ru%3E&subject=My+Subject&text=%3Chtml%3E%3Cbody%3E%3Cp%3Etest%3C%2Fp%3E%3C%2Fbody%3E%3C%2Fhtml%3E&to=zozoba29a%40yandex.ru

LWP::UserAgent SendHub API Issue

SendHub's documentation state to send a post with data and json data.
This is the curl example they gave
Trying to do this with perl and LWP::User Agent but getting either bad request or unauthorized
Do I have the request coded properly?
curl -H "Content-Type: application/json" -X POST --data '{"contacts" : [1111],"text" : "Testing"}' https://api.sendhub.com/v1/messages/?username
require LWP::UserAgent;
my $uri = 'https://api.sendhub.com/v1/messages/?username=MY_USERNAME\&api_key=MY_KEY_NUMBER';
my $json = '{"contacts":[18005551212],"text":"testing"}';
my $req = HTTP::Request->new('POST',$uri);
$req->header('Content-Type' => 'application/json');
$req->content($json);
my $lwp = LWP::UserAgent->new;
my $response=$lwp->request($req);
if ($response->is_success) {
print $response->decoded_content;
}
else {
die $response->status_line;
}
It looks basically OK.
What is the backslash before the ampersand in the URL?
'https://api.sendhub.com/v1/messages/?username=MY_USERNAME\&api_key=MY_KEY_NUMBER'
I think it should be
'https://api.sendhub.com/v1/messages/?username=MY_USERNAME&api_key=MY_KEY_NUMBER'
but if you're getting 401 Unauthorized then it's most likely the request is correct but the user name and key are wrong.

Send a HTTP POST Request(xml data ) using WWW::Curl in perl

I want to use WWW::Curl instead of LWP::UserAgent to send a post request.
Below is the Code using LWP::UserAgent which works fine.
my $agent = LWP::UserAgent->new(agent => 'perl post');
push #{ $agent->requests_redirectable }, 'POST';
my $header = HTTP::Headers->new;
$header->header('Content-Type' => "text/xml; charset=UTF-8");
$header->content_encoding('gzip');
utf8::encode( my $utf8_content = $args{content} );
sinfo $utf8_content;
$error->description($utf8_content);
$error->log;
my $request = HTTP::Request->new(POST => $args{url}, $header, $utf8_content);
my $response = $agent->request($request);
I need to rewrite this code using WWW::Curl as Curl is faster than LWP.
I have tried the below code but it returns me code '35' as response, which
means the request is invalid.
my $curl = WWW::Curl::Easy->new();
$curl->setopt(WWW::Curl::Easy::CURLOPT_HEADER,1);
$curl->setopt(WWW::Curl::Easy::CURLOPT_URL,$self->uri());
$curl->setopt(WWW::Curl::Easy::CURLOPT_POST, 1);
$curl->setopt(WWW::Curl::Easy::CURLOPT_POSTFIELDS, $utf8_content);
my $response;
$curl->setopt(WWW::Curl::Easy::CURLOPT_WRITEDATA,\$response);
my $retcode = $curl->perform();
The data i pass in the post request ($utf8_content) is a xml string ,sample xml :
<Request>
<Source>
<RequestorID Password="PASS" Client="Client" EMailAddress="email#address.com"/>
<RequestorPreferences Language="en">
<RequestMode>SYNCHRONOUS</RequestMode>
</RequestorPreferences>
</Source>
<RequestDetails>
<SearchRequest>
<ItemDestination DestinationType="area" DestinationCode="XYZ"/>
</ItemDestination>
</SearchRequest>
</RequestDetails>
</Request>
Moreover the response too will be a xml string which can be retrieved from $response;
In theory, this should work, but doesn't. The problem is that $utf8_content_gzip contains a \0 in the middle and the C API truncates the request body. If this is a bug and not just a misunderstanding of mine how to talk to WWW::Curl, then either have the bug fixed or work around by simply not encoding the request.
use utf8;
use strictures;
use Devel::Peek qw(Dump);
use Encode qw(encode);
use HTTP::Response qw();
use IO::Compress::Gzip qw(gzip $GzipError);
use WWW::Curl::Easy qw();
my $utf8_content_gzip;
{
my $utf8_content = encode('UTF-8', '<root>Třistatřicettři stříbrných stříkaček stříkalo přes třistatřicettři stříbrných střech.</root>', Encode::LEAVE_SRC | Encode::FB_CROAK);
gzip(\$utf8_content, \$utf8_content_gzip)
or die sprintf 'gzip error: %s', $GzipError;
}
Dump $utf8_content_gzip;
my $xml;
{
my $curl = WWW::Curl::Easy->new;
$curl->setopt(WWW::Curl::Easy::CURLOPT_HEADER(), 1);
$curl->setopt(WWW::Curl::Easy::CURLOPT_URL(), 'http://localhost:5000');
$curl->setopt(WWW::Curl::Easy::CURLOPT_HTTPHEADER(), ['Content-Type: text/xml; charset=UTF-8', 'Content-Encoding: gzip']);
$curl->setopt(WWW::Curl::Easy::CURLOPT_POST(), 1);
$curl->setopt(WWW::Curl::Easy::CURLOPT_POSTFIELDS(), $utf8_content_gzip);
my $response;
$curl->setopt(WWW::Curl::Easy::CURLOPT_WRITEDATA(), \$response);
my $retcode = $curl->perform;
if (0 == $retcode) {
$response = HTTP::Response->parse($response);
$xml = $response->decoded_content;
} else {
die sprintf 'libcurl error %d (%s): %s', $retcode, $curl->strerror($retcode), $curl->errbuf;
}
}
Have you tried $curl->setopt(CURLOPT_SSLVERSION, CURL_SSLVERSION_SSLv3);?