An API request needs to be sent. For some reason, the server is blocking CURL request, but it approves an XHR ajax request. I could send an ajax request, but another problem arises - Mixed content my website is served over HTTPS but the request that needs to be sent is over HTTP so I cannot use ajax.
I am looking for a way to simulate ajax request through CURL, in some way, trick the server to believe that the CURL request is indeed an ajax request.
Here's what I have tried.
This is my CURL request.
$ch = curl_init();
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; Linux x86_64)');
curl_setopt($ch, CURLOPT_REFERER, 'server's url');
curl_setopt($ch, CURLOPT_AUTOREFERER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Accept:application/json, text/javascript, */*; q=0.01',
'Accept-Encoding:gzip, deflate',
'Accept-Language:en-US,en;q=0.9',
'Connection:keep-alive',
'Content-Type: application/json; charset=utf-8',
'X-Requested-With: XMLHttpRequest',
'__RequestVerificationToken: $token'
));
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 10);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_COOKIEJAR, base_path().'/cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, base_path().'/cookies.txt');
$buffer = curl_exec($ch);
if(curl_error($ch))
{
$buffer = curl_error($ch);
}
curl_close($ch);
return $buffer;
This curl request is blocked
But, this ajax request goes through my localhost, but since my live website uses HTTPS I cannot really use it.
$.ajax({
type: "get",
xhrFields: { withCredentials:true },
url: http://apiendpoint.com,
success: function(data)
{
// console.log(data);
}
})
in chrome, you can copy a working curl expression from developer toolbar. Try with that one from cli. If that works, you can figure out which parts are required and which parts are not. Then you can transcript it to php.
If you have doubts if the same thing happens from php than from curl, just try it with requestbin.
I think it is possible the header for token may not be what you think it is, since given $a==1, '$a' converts to $a, but "$a" converts to "1" (notice single quotes vs double quotes).
in your example, try replacing:
'__RequestVerificationToken: $token'
with:
"__RequestVerificationToken: $token"
and let us know if that solves the problem.
Consider using passthru("curl command here..."); using the suggestion from lintabá
You can use 2-stage request
1 curl .... -c ${cookie_file}
2 curl .... -b ${cookie_file} -c ${cookie_file}
This should work.
first is basicly gets the cookie with session id
2nd do the real request
Related
I'm working with a third party API, and it returns 400 HTTP STATUS when you make a mistake.
When using POSTMAN, the 400 HTTP error page shows as expected, but when using PHP's cURL, the page just loads for about a minute, then it gives me a "504 - Gateway timeout", and I need to close the browser to be able to access the page again.
When the cURL request is valid (the API returns a 200 OK) it works normally.
My question is, why is cURL giving the 504 error instead of 400?
And why is it ignoring CURLOPT_CONNECTTIMEOUT and CURLOPT_TIMEOUT?
Below is my cURL code (both $token, $payload and $config variables are declared and valid):
$ch = curl_init("https://api.mercadolibre.com/items?access_token=$token");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"User-Agent: Alcavie/" . $config['version'],
"Accept: application/json",
"Content-Type: application/json",
//"Accept-Encoding: gzip, deflate, br",
//"Connection: keep-alive"
));
$error = false;
try{
$result = curl_exec($ch);
$resultJson = json_decode($result);
}catch(\Exception $e){
var_dump($e);
$error = true;
exit;
}
curl_close($ch);
The API probably sends HTTP302 in between and if so, you'd either need two requests ortell cURL to follow the redirect with curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);HTTP504 means that the client didn't react in a timely manner upon the previous HTTP header;there may be other causes for HTTP504, but it is one of the most common. Postman is insufficient to test this properly (I don't use it at all); better use a web-browser, hit F12 and tick the "preserve logs" checkbox... then you can clearly see which HTTP headers are being sent in succession.
Also useful to debug this would be: curl_setopt($ch, CURLOPT_HEADER, true);
I'm trying to use Application Only Authentication, as described here:
https://developer.twitter.com/en/docs/basics/authentication/overview/application-only
I'm using the following PHP code to do so.
if(empty($_COOKIE['twitter_auth'])) {
require '../../social_audit_config/twitter_config.php';
$encoded_key = urlencode($api_key);
$encoded_secret = urlencode($api_secret);
$credentials = $encoded_key.":".$encoded_secret;
$encoded_credentials = base64_encode($credentials);
$request_headers = array(
'Host: api.twitter.com',
'User-Agent: BF Sharing Report',
'Authorization: Basic '.$encoded_credentials,
'Content-Type: application/x-www-form-urlencoded;charset=UTF-8',
'Content-Length: 29',
'Accept-Encoding: gzip'
);
print_r($request_headers);
$ch = curl_init();
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_HTTPHEADER, $request_headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_URL, 'https://api.twitter.com/oauth2/token');
curl_setopt($ch, CURLOPT_POSTFIELDS, 'grant_type=client_credentials');
$attempt_auth = curl_exec($ch);
print_r($attempt_auth);
}
It should return JSON with the token in it, but instead it returns gobbledygook, as seen in the image below:
I'm sure I'm missing some very simple step, where am I going wrong?
If I send the curl request without the headers, it returns an error in JSON format as expected, so is there something wrong with my headers?
You have few options here. Instead of setting header directly, use below
curl_setopt($ch, CURLOPT_ENCODING, 'gzip');
If you set header directly then you should use
print_r(gzdecode($attempt_auth));
See below thread as well
Decode gzipped web page retrieved via cURL in PHP
php - Get compressed contents using cURL
I'm working on a web_app using teamviewer API. According to the documentation, it works using HTTP requests (GET, POST, etc..).
I don't get how to make a request on PHP using CURL. The documentation said to do this:
POST /api/v1/oauth2/token HTTP/1.1
Host: webapi.teamviewer.com
Content-Type: application/x-www-form-urlencoded
so I wrote this
$url = 'webapi.teamviewer.com';
$headers = array(
'GET /api/v1/oauth2/authorize HTTP/1.1',
'Content-type: application/x-www-form-urlencoded'
);
//data
$data = [
'response_type' => 'authorization_code',
'redirect_uri' => 'https%3A%2F%2FTesting%2Ecom%2F',
'client_id' => '65671-XDdsxUNyxGmskcJHQgLC'
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POST, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
I just can't figure out how to indicate the request the HTTP/1.1 and the path /api/v1/oauth2/authorize. I'm putting it in the header but I'm sure it doesn't go there.
I use to work on embedded C and I remember that first you connect to the host and then write GET path HTTP/1.1 as a command.
Your $url should be the full path, just like a normal URL. So it would be
$url = 'webapi.teamviewer.com/api/v1/oauth2/authorize';
And you can remove the GET ... part from $headers, because the URL (path) doesn't go in there.
That should work after that. If you want to see more info about the curl connection and what's going on, add this option:
curl_setopt($ch, CURLOPT_VERBOSE, true);
The full list of curl options is at the PHP manual page on curl_setopt.
I need PHP to submit paramaters from one domain to another. JavaScript is not an option for my situation. I'm now trying to use CURL with PHP, but have not been successful in bypassing the cross domain.
From domain_A, I have a page with the following PHP with CURL script:
if (_iscurl()){
echo "<p>CURL is enabled</p>";
$url = "http://domain_B/process.php?id=123&amt=100&jsonp=?";
$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT,10);
curl_setopt($ch, CURLOPT_USERAGENT , "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1)");
curl_setopt($ch, CURLOPT_URL, $url );
$return = curl_exec($ch);
curl_close($ch);
echo "<p>Finished operations</p>";
}
else{
echo "CURL is disabled";
}
?>
I am not getting any results, so I am assuming that the PHP CURL script is not successful. Any ideas to fix this?
Thanks
Well, its bit late. But adding this answer for further readers who might face similar issue. This issue arises some times when we are sending php curl request from a domain hosted over http to a domain hosted over https (http over ssl).
Just add below code snippet before curl execution.
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec($ch);
Using false in CURLOPT_RETURNTRANSFER doesn't return anything by curl. make it true(or 1)
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
I have a simple PHP Script, that uses CURL to send a HTTP Post Request to a remote server.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://91.250.77.10/test.php');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, array('a' => 'b'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$contents = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
if ($error)
echo $error;
else
echo $contents;
This results in an error: "no response from server". The request can't be found in the access log of the remote server, too!
What's more, if I send the postfields as a querystring, i.e.:
curl_setopt($ch, CURLOPT_POSTFIELDS, '&a=b');
then everything is just fine.
It seems like something is wrong with the Apache or PHP configuration on the remote server. Any hints?
Edit:
As for now, it looks like the Server doesn't accept (or correctly handle) requests with Content-Type: multipart/form-data
(CURL uses that type when setting an array as the postfields, but not when setting a string.)
Since I need to send a file with the request, i have to use the multipart/form-data. So how do I get the server to correctly handle this?
If you pass an array to CURLOPT_POSTFIELDS then the form is submitted as multipart/form-data There could be a possibility your remote end is not accepting this encoding type.
Best way to do POST request is to format postFields like this.
VARIABLE = VALUE separated by &.
TIP:
$postFields = 'var1=cons1&var2=cons2&var3=cons3&var4=cons4&var5=cons5';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://91.250.77.10/test.php');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields;
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$contents = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
if ($error)
echo $error;
else
echo $contents;
Would be Pleased to do any more help.
Check if the HTTP header contains "Expect:100-continue" field. Some Servers do not deal with this field and just wait.
You can try:
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect: '));
For more information, pls see:
curl http 100 continue and multipartform-data post