Trouble POSTing using cURL, PHP, and Basic Authentication - php

I made a similar post last week, which can be found here. I was having problems with authentication, which I believe I've solved. The error message is different, at least.
I'm trying to recreate a successful POST I made to our vendor via POSTman by executing cURL commands in PHP.
Here is the example cURL command from their documentation:
curl -i -k -u '<api_key>': -XPOST --data-urlencode assessment_data#/path/to/test/file.json "https://<your_subdomain>.vendor.org/api/v1/import"; echo ""
This is my PHP code, which does not work:
<?php session_start();
include('../connect.php');
include('../functions.php');
function curlPost($url, $headers, $username, $password, $post) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CAINFO, 'certificate.pem');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, $username . ":" . $password);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
echo '<pre>';
echo curl_exec($ch) . '<br><br>';
echo print_r(curl_getinfo($ch)) . '<br><br>';
echo curl_error($ch) . '<br><br>';
echo '</pre>';
curl_close($ch);
}
$data = 'JSON_object={"JSON_key":"JSON_value"}';
curlPost('https://company.vendor.org/api/v1/import',
['Content-Type: multipart/form-data'],
'api-key',
'',
$data
);
and instead produces this output:
{"success":false,"errors":["500 Internal Server Error"],"warnings":[],"info":[],"meta":[],"results":[]}
Array
(
[url] => https://company.vendor.org/api/v1/import
[content_type] => application/json; charset=utf-8
[http_code] => 500
[header_size] => 547
[request_size] => 248
[filetime] => -1
[ssl_verify_result] => 0
[redirect_count] => 0
[total_time] => 1.586493
[namelookup_time] => 0.135777
[connect_time] => 0.177182
[pretransfer_time] => 0.286958
[size_upload] => 1999
[size_download] => 103
[speed_download] => 64
[speed_upload] => 1260
[download_content_length] => 103
[upload_content_length] => 1999
[starttransfer_time] => 0.345878
[redirect_time] => 0
[redirect_url] =>
[primary_ip] => xx.xxx.xx.xxx
[certinfo] => Array
(
'This array is actually empty, I didn't delete anything.'
)
[primary_port] => 443
[local_ip] => xxx.xxx.xx.xxx
[local_port] => 60532
[request_header] => POST /api/v1/import HTTP/1.1
Authorization: Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Host: company.vendor.org
Accept: */*
Content-Type: multipart/form-data
Content-Length: 1999
Expect: 100-continue
)
1
For good measure, here is a screenshot of a successful POST using POSTman (It's censored a little differently, but I'm passing in the exact same information):
Their documentation contains an example JSON object, which they save as a file and send as form-data. I've managed to recreate the object with live data, output it to a properly formatted string, and send that as the value instead. This works in POSTman, but not in my PHP, so I suspect the problem lies there somehow. CURLOPT_POSTFIELDS requires a string (tried an array - it got mad), and I've tried formatting it every way I can think of. Any help would be greatly appreciated.

Related

PHP - Using cURL to get a cookie from a redirecting URL but getting no response

I have a cURL command using which I get authenticated to a website and it gives a cookie in response, then subsequently using this cookie I can make REST API calls to this service
Here is the working cURL command:
curl -v -l -H "Content-Type: application/x-www-form-urlencoded" -H "Referrer:https://mywebsiteurl.com?ticket=unique_ticket_id" -d "_charset_=UTF-8&errorMessage=User+name+and+password+do+not+match&resource=%2F&username=username%40domain.com&password=XXXXXX&nextpage=welcomeCM.jsp&viewInfo=&ticket=unique_ticket_id" -X POST https://mywebsiteurl.com/index.jsp
In the above command ticket parameter contains a unique ticket id that is passed along with the website url
Now, I'm trying to accomplish the same using cURL PHP, here is the PHP code:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://mywebsiteurl.com/index.jsp");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "_charset_=UTF-8&errorMessage=User+name+and+password+do+not+match&resource=%2F&username=username%40domain.com&password=XXXXXX&nextpage=welcomeCM.jsp&viewInfo=&ticket=unique_ticket_id");
curl_setopt($ch, CURLOPT_POST, 1);
$headers = array(
'Content-Type: application/x-www-form-urlencoded',
'Referrer: https://mywebsiteurl.com?ticket=unique_ticket_id'
);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error:' . curl_error($ch);
}
echo $result;
curl_close ($ch);
Here echo $result shows nothing
I then tried var_dump($result); and it gives this output: string(0) "" which means nothing is getting returned in $response
After this I tried curl_getinfo and added the following code:
echo "<pre>";
$info = curl_getinfo($ch);
print_r($info);
echo "</pre>";
And this gave me the following array:
Array
(
[url] => https://mywebsiteurl.com/index.jsp
[content_type] => text/html;charset=UTF-8
[http_code] => 302
[header_size] => 1306
[request_size] => 619
[filetime] => -1
[ssl_verify_result] => 0
[redirect_count] => 0
[total_time] => 1.540687
[namelookup_time] => 0.028262
[connect_time] => 0.171774
[pretransfer_time] => 0.462507
[size_upload] => 280
[size_download] => 0
[speed_download] => 0
[speed_upload] => 181
[download_content_length] => 0
[upload_content_length] => 280
[starttransfer_time] => 1.54066
[redirect_time] => 0
[redirect_url] => https://mywebsiteurl.com/welcomeCM.jsp?username=username#domain.com&locale=en_US
[primary_ip] => YY.YYY.YYY.YY
[certinfo] => Array
(
)
[primary_port] => 443
[local_ip] => XX.XX.XXX.XX
[local_port] => 47692
)
Now my goal is to get the cookie in $result, but it is empty & nothing is getting returned into it
Is it that something is missing in the cURL command equivalent PHP code?
Can someone please help me out & point me in the direction to retrieve the cookie
Thanks a lot!
UPDATE
I added curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); to the request to have it follow the 302 redirect after successful login
But this time after the execution of cURL, echo $result is redirecting my current local webpage to /Dashboard?viewInfo= which obviously does not exist
Also this time var_dump($result); is resulting in: string(1462) " "
And curl_getinfo($ch) this time is giving the following array:
Array
(
[url] => https://mywebsiteurl.com/welcomeCM.jsp?username=username#domain.com&locale=en_US
[content_type] => text/html;charset=UTF-8
[http_code] => 200
[header_size] => 1821
[request_size] => 956
[filetime] => -1
[ssl_verify_result] => 0
[redirect_count] => 1
[total_time] => 1.746911
[namelookup_time] => 1.5E-5
[connect_time] => 1.5E-5
[pretransfer_time] => 6.2E-5
[size_upload] => 0
[size_download] => 1462
[speed_download] => 836
[speed_upload] => 0
[download_content_length] => 1462
[upload_content_length] => 0
[starttransfer_time] => 0.146587
[redirect_time] => 1.6003
[redirect_url] =>
[primary_ip] => YY.YYY.YYY.YY
[certinfo] => Array
(
)
[primary_port] => 443
[local_ip] => YY.YY.YYY.YY
[local_port] => 47705
)
Still can't get the required cookie here,
Please help!
If you want to use curls given functionality you can try using CURLOPT_COOKIEJAR / CURLOPT_COOKIEFILE, to store and get your cookie. This if file based.
In this case, curl will then write any Cookie related Information in a file.
You can define where this file will be located.
By using CURLOPT_COOKIEJAR , you will tell curl that it shall capture the cookie data.
// create cookie file
$cookie = __DIR__ . "/where/you/want/to/store/your/cookie/mycookie.txt";
fopen($cookie, "w");
// you may want to use some random identicator in your cookie file
// to make sure it does not get overwritten by some action
// prepare login
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://mywebsiteurl.com/index.jsp");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// tell curl to follow redirects
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURlOPT_POSTFIELDS, "username=usernam&password=XXXXXX");
curl_setopt($ch, CURLOPT_POST, 1);
// set a jar, to store your cookie
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie);
$headers = array(
'Content-Type: application/x-www-form-urlencoded',
'Referrer: https://mywebsiteurl.com?ticket=unique_ticket_id'
);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// do login
$loginResult = curl_exec($ch);
// check if your login has worked according to the given result by any method you want
if (preg_match("/Welcome/", $loginResult)) {
// simple regex for demonstration purpose
}
// now you could load your cookie out of the file, or just use the file for future requests
If your login has worked, you will have all information stored in your cookie file.
Now you can use that cookie again with the curlopt CURLOPT_COOKIEFILE for future requests.
// do other request, with your cookie
curl_setopt($ch, CURLOPT_URL, "https://mywebsiteurl.com/api/rest.php");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "your new post data");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
// set a jar to update your cookie if needed
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie);
// give curl the location of your cookie file, so it can send it
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie);

Issue using PHP cURL with the Streamable API

I am hoping to build a video upload using the Streamable API and PHP with cURL. https://streamable.com/documentation#upload-video-file
What I'm trying to accomplish is:
User fills out a form of info and selects a video file from their computer/device to upload
Submits the form, PHP handles it from there to talk to the Streamable API to upload the video via the form to my Streamable account, then return the shortcode from Streamable for me to store in a MySQL database with the rest of their info
I've tried, with success, using the curl command via terminal. But, I'm having issues with pulling it off via php form submission.
This is an example of the command I used in terminal to upload, which worked:
curl https://api.streamable.com/upload -u my_email:my_pass -F file=#path/to/file.mp4
With PHP, I have a pretty simple cURL script thanks to the tons of help online. I guess you could say I'm pretty new to using cURL.
$url = 'https://api.streamable.com/upload -u my_email.com:my_pass -F file=#path/to/file.mp4';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$server_output = curl_exec ($ch);
curl_close ($ch);
With that, I'm getting a HTTP 400 error.
https://streamable.com/documentation#errors
..codes in the 400 range indicate client errors...
I guess that's what's messing me up here?
I tried it this way, but I get the same error.
$pass = 'my_email:my_pass';
$postFields = array(
'file' => '/path/to/file.mp4',
'title' => 'Example Title'
);
$url = 'https://api.streamable.com/upload';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_USERPWD, $pass);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$server_output = curl_exec ($ch);
curl_close ($ch);
I used print_r(curl_getinfo($ch)); to see what's happening, and this is what it's spitting out - maybe this can be useful for some help:
Array ( [url] => https://api.streamable.com/upload
-u my_email:my_pass -F file=#/Path/to/file.mp4 [content_type] => [http_code] => 400 [header_size] => 66 [request_size] => 277 [filetime] => -1 [ssl_verify_result] => 0 [redirect_count] => 0 [total_time] => 0.36033 [namelookup_time] => 0.00138 [connect_time] => 0.082871 [pretransfer_time] => 0.283219 [size_upload] => 0 [size_download] => 0 [speed_download] => 0 [speed_upload] => 0 [download_content_length] => 0 [upload_content_length] => 275 [starttransfer_time] => 0.36031 [redirect_time] => 0 [redirect_url] => [primary_ip] => xx.xx.xxx.xxx [certinfo] => Array ( ) [primary_port] => 443 [local_ip] => 192.168.0.1 [local_port] => 57288 )
There are couple of things you need to change here:
Set CURLOPT_SSL_VERIFYPEER to false. It can be used to verify peer's certificate. If we specify it as false, it will accept any server(peer) certificate.
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
Here's a good read on the implication of turning CURLOPT_SSL_VERIFYPEER on and off, If CURLOPT_SSL_VERIFYPEER is false, is the data transfer no longer secure?
CURLOPT_POSTFIELDS is used to specify full data we want to submit with the POST request. The $postFields array should be converted to URL-encoded query string using http_build_query() function, so that it could be sent as application/x-www-form-urlencoded.
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postFields));
Try this:
$fields = array("file"=>curl_file_create("video.mp4"));
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://api.streamable.com/upload");
curl_setopt($ch, CURLOPT_USERPWD, "email:pass");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields );
$result = curl_exec($ch);
I think curl_file_create makes the trick, it seems using #fileName no more work for PHP 5.5+

Curl http_code 400

I am trying to send the push Notification but it is getting problem
$url = 'https://android.googleapis.com/gcm/send';
$fields = array(
'registration_ids' => $id,
'data' => $load,
);
$headers = array(
'Content-Type: application/json',
'Authorization: key=' . GOOGLE_API_KEY,
);
// Open connection
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
//curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11');
// Disabling SSL Certificate support temporarly
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields, true));
// Execute post
$result = curl_exec($ch);
$httpcode = curl_getinfo($ch);
And when I try to see the curl info I see there is http_code 400. I did everything but still I am getting problem and push notification is not working.
Can you guys please help me ? I am stuck here.
Array
(
[url] => https://android.googleapis.com/gcm/send
[content_type] => text/plain; charset=UTF-8
[http_code] => 400
[header_size] => 406
[request_size] => 698
[filetime] => -1
[ssl_verify_result] => 0
[redirect_count] => 0
[total_time] => 0.22549
[namelookup_time] => 0.028427
[connect_time] => 0.030052
[pretransfer_time] => 0.189248
[size_upload] => 382
[size_download] => 41
[speed_download] => 181
[speed_upload] => 1694
[download_content_length] => -1
[upload_content_length] => 382
[starttransfer_time] => 0.225382
[redirect_time] => 0
[certinfo] => Array
(
)
[primary_ip] => 172.217.6.234
[primary_port] => 443
[local_ip] => 162.243.229.189
[local_port] => 54327
[redirect_url] =>
)
Error 400 means Bad Request. I see in your code, in the $headers array that you have the GOOGLE_API_KEY which is not defined in your script. You also have not defined $id and $load from what I can see.
Firstly, you will need a Google Cloud Messaging API Key, which you can obtain from the Google Developer's Console.
Please note that the method which you are employing requires a client side app installed on the mobile device. An alternative would be to send a web-push notification, which pushes the notification to Chrome (or any other compatible web browser), so long as it is running and has any tab open. If this is an option you think is worth looking at, I suggest you look at the following web-push library on Git-Hub.

cURL takes too long to load

I am calling a REST endpoint in PHP using cURL to fetch some JSON data:
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
echo $result;
curl_close($ch);
It takes 2.5 seconds to fetch the data using the above code on my localhost. The same code takes around 7.5 seconds when run on the live server. When the URL is opened directly on a browser it takes only 1.5 seconds.
My question is: Why does it take so long for cURL to fetch data on the live server and how can I solve this problem?
Below is the output of curl_getinfo($ch) on the server:
Array
(
[content_type] => application/json
[http_code] => 200
[header_size] => 420
[request_size] => 113
[filetime] => -1
[ssl_verify_result] => 0
[redirect_count] => 0
[total_time] => 7.305496
[namelookup_time] => 0.150378
[connect_time] => 0.473187
[pretransfer_time] => 0.473237
[size_upload] => 0
[size_download] => 1291504
[speed_download] => 176785
[speed_upload] => 0
[download_content_length] => -1
[upload_content_length] => 0
[starttransfer_time] => 1.787901
[redirect_time] => 0
[redirect_url] =>
[certinfo] => Array
(
)
[primary_port] => 80
[local_port] => 53962
)
I found the solution to my problem. As I had mentioned in the question, the service was loading the fastest in browsers. So, I checked the 'Request Headers' of the request in the 'Network' tab of Google Chrome Inspector. I copied those headers and used them in my cURL request in PHP. After scraping those headers I found that all I needed to do was to add an Accept-Encoding header. I passed a value of gzip like so:
curl_setopt($ch, CURLOPT_ENCODING, 'gzip');
but setting it to an empty string also works.
curl_setopt($ch, CURLOPT_ENCODING, '');
According to the php.net manual for CURLOPT_ENCODING:
The contents of the "Accept-Encoding: " header. This enables decoding
of the response. Supported encodings are "identity", "deflate", and
"gzip". If an empty string, "", is set, a header containing all
supported encoding types is sent.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "set ur url");
curl_setopt($ch, CURLOPT_ENCODING , "gzip");
curl_setopt($ch, CURLOPT_ENCODING, '');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
Please check this example

Retrieve Twitter's X-RateLimit-Limit in PHP

With every Twitter request I make, the returned HTTP headers should include X-RateLimit-Limit.
However, I seem unable to retrieve these using PHP. Can someone tell me what bone-headed mistake I've made?
I've set my curl up in the normal way and am able to successfully GET and POST requests.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLINFO_HEADER_OUT, TRUE);
curl_setopt($ch, CURLOPT_VERBOSE, TRUE);
$response = curl_exec($ch);
$response_info=curl_getinfo($ch);
$erno = curl_errno($ch);
$er = curl_error($ch);
curl_close($ch);
I'm able to get some response information, like http_code
$response_info['http_code']
But this line just returns null
//Doesn't bloody work. No idea why!
$rate_limit = $response_info['X-RateLimit-Limit'];
I'm running PHP Version 5.3.10.
EDIT
This is the result of print_r($response_info);
Array
(
[url] => https://api.twitter.com/1/statuses/home_timeline.json...
[content_type] => application/json;charset=utf-8
[http_code] => 200
[header_size] => 695
[request_size] => 410
[filetime] => -1
[ssl_verify_result] => 0
[redirect_count] => 0
[total_time] => 1.239977
[namelookup_time] => 0.007361
[connect_time] => 0.155783
[pretransfer_time] => 0.465397
[size_upload] => 0
[size_download] => 99425
[speed_download] => 80182
[speed_upload] => 0
[download_content_length] => 99425
[upload_content_length] => 0
[starttransfer_time] => 0.794829
[redirect_time] => 0
[certinfo] => Array()
[redirect_url] =>
[request_header] => GET /1/statuses/home_timeline.json... HTTP/1.1
Host: api.twitter.com
Accept: */*
)
curl_getinfo does not return the response headers, only other meta info about the request. To retrieve headers, set CURLOPT_HEADER to true. That will include the headers in the output. To separate them from the response body do:
list($headers, $body) = explode("\n\n", $response, 2);
To parse the headers, explode again:
$headers = explode("\n", $headers);
foreach ($headers as $header) {
list($key, $value) = explode(':', $header, 2);
$headers[trim($key)] = trim($value);
}
echo $headers['X-RateLimit-Limit'];

Categories