What is wrong with this PHP cURL request to a Google API? - php

EDIT/UPDATE:
1) I tried the URL with just http (not https), and it worked in my browser. But, it did not work with PHP and cURL!
2) I read the curl error message, and it said Couldn't resolve host 'ajax.googleapis.com'. But, again, it could resolve the host from my web browser on the same machine!
3) Google explicitly stated that I needed the CURLOPT_REFERER to be set, so I'm keeping it.
Any other ideas? Thanks!
ORIGINAL POST:
When I enter this URL into my web browser, I get the JSON response I want. But, when I run the following cURL code in PHP5 (via Apache 2), the request fails. Can anyone point to some possible problems?
$url = "https://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=hola&langpair=es%7Cen&key=I-REMOVED-MY-API-KEY-FOR-STACKOVERFLOW-POST";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_REFERER, "http://my.ip.addr.ess/");
$response = curl_exec($ch);
var_dump($response);
The output is bool(false);
I have no idea what's wrong... do you? Thanks!

When the response if false, there was an error. Check for errors doing something like this:
if (($response = curl_exec($ch)) === FALSE) {
echo curl_error($ch);
exit();
}
In production code you definitely want to do something else on an error condition (instead of outputting the error message and exiting), but this will help you for debugging.

Probably because you're accessing a HTTPS resource.
Quick fix:
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

Use http:// instead of https://. Code works fine without the key in the query string. CURLOPT_REFERER is also not necessary.

Related

cURL request getting wrong request version in Google App Engine

I have a cURL request in my code which works fine when running locally:
$url = "http://ipinfo.io/{$_SERVER['REMOTE_ADDR']}";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$response = curl_exec($ch);
$locale = json_decode($response);
and returns a JSON as expected. Our production system is on Google App Engine, however, where I get the website version for a browser rather than the JSON.
I can get this cURL request to work if I change
google_app_engine.enable_curl_lite = "1"
in the php.ini in the root directory of my project to
extension = "curl.so"
but Google's documentation insists the former is to be used on production. Additionally, using the latter breaks things like Monolog's SlackHandler.
Is there a way to get the JSON from this cURL request while still using Google's "cURL Lite"?
From the ipinfo.io documentation:
"We do a little bit of magic on the server to determine if we should send the JSON response or the webpage. We usually get it right, but if you're seeing the webpage instead of the JSON (or want to check the JSON output in a browser) you can force the JSON response by adding /json to the end of the URL"
Adding /json to the end of the URL worked for me in this case, but I wanted a more general solution. Since Google's cURL Lite uses their URL Fetch in the background, ipinfo.io's "magic" is somehow getting confused. I found that by specifying the Accept header then the /json addition wasn't required. In PHP:
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: application/json'));
Thanks to the folks on the #php channel of NashDev Slack for helping me on this one!

PHP cURL - not detecting errors?

I'm having some weirdness with returning cURL response code errors. The following code, despite the remote host throwing a 404, does not cURL error. Why?
$ch = curl_init('http://www.google.com/13ewsdasd'); //<-- definitely a 404
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
echo curl_exec($ch) ? 'All OK' : 'Error: '.curl_error($ch); //'All OK'
I found this answer that suggested using curl_get_Info with the CURL_INFO_HTTP_CODE flag, but no joy there, either - that just gives me "0".
$ch = curl_init('http://www.google.com/13ewsdasd'); //<-- still a 404
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
echo curl_getinfo($ch, CURLINFO_HTTP_CODE); //<-- 0
I seem to recall issues detecting errors with cURL before. Am I missing something obvious? I just want to detect when the remote server throws a 404 or 500.
Another answer suggested doing this via get_headers(), but it seems silly to have to fire a second, separate request just to find out the response code of the first one.

Check if an image exist using HTTPS

I am just wondering if there is a way to check if an encrypted image exist over https.
I am using this code below to check whether an image exist. It will return 200 if it does, and 404 if it doesn't. But this only work on image URL that does not contain https.
function exists_url($uri){
$ch = curl_init($uri);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_exec($ch);
return $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
}
If I try to verify this url ( https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcTup5KSMveqkgrDKZR6p-0ANhPkJ7srbJOlKR78DUqqh85I_3MUrw ) it gives me a result of 0 instead of 200 or 404.
I have thought to use getimagesize() function to accomplish this task. But even this function only works for image that is not send over HTTPS.
Since you're using SSL/TLS you must point cURL to a valid CA Certificate bundle. The bundle must be in .pem format. You can obtain such a bundle from http://curl.haxx.se/ca/.
Next you need to tell cURL to use your CA bundle. You can do this with the CURLOPT_CAINFO option.
curl_setopt($ch, CURLOPT_CAINFO, '/path_to_file/cacert.pem');
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
You could simply deactivate the verify of peer with
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
So you have not to worry about nothing.
Watch out: #user555 answer is better for security purposes
A response code of 0 from Curl typically means there was an error connecting to the server or something along those lines (See PHP cURL HTTP CODE return 0 and countless other questions).
I did however run this code myself using PHP 5.5.x and it returned a 200 as expected. getimagesize() not working also leads me to think it's most likely a problem with curl or php on your system, what versions of them do you have?

How can I output the body of a webpage if the response code is 500 using curl?

I've been through hell and high water with this problem. I get a 500 error on a page a tiny, tiny fraction of the time. I have been completely unable to reproduce it, but Google insists that they see a 500 code. Fetch as Googlebot says it's successful, however something is wrong. I've been down many avenues and the only recourse I have left is to brute-force the local copy of the website.
I want to use curl to hammer the dev site until I get a 500 error, and when I do, to output the body of the page to the terminal so I can actually get some useful information.
for(;;){
$url = "http://www.blahblah.dev/";
$ch = curl_init();
//Set the URL
curl_setopt($ch, CURLOPT_URL, $url);
//Enable curl response
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
//Enable POST data
curl_setopt($ch, CURLOPT_POST, true);
//Use the $pData array as the POST data
curl_setopt($ch, CURLOPT_POSTFIELDS, $jData);
$result = curl_exec($ch);
if(strstr($result, "error")){
echo $result;
exit();
}
curl_close($ch);
usleep(500000);
}
As you can see, I'm simply checking to see if "error" appears in the body, as I can't figure out how to check for a 500 error properly. I realize that this is a terrible and contrived way of debugging, but it's all I've got at this point. Thanks!

How do I find out what was sent with cURL?

I'm trying to figure out why a cURL process (written in PHP) that used to be working is no longer working. I'm receiving the same data back as what an actual browser is receiving, but I'm not sure if I'm sending the same information as the browser.
Is there a way I can find out what the cURL library in PHP is sending?
Note: I don't have access to the server I'm accessing and I'm actually thinking they're blocking me, so I'm trying to determine what I need to change to copy the browser.
Since PHP 5.1.3, you can use CURLOPT_HEADER_OUT to get the request headers you sent. I think this might be what you're looking for.
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://www.example.com/");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_exec($ch);
var_dump(curl_getinfo($ch,CURLINFO_HEADER_OUT));
After you run the curl, try this:
$info = curl_getinfo($curlHandle);
echo '<pre>';
print_r($info);
echo '</pre>';
There's a complete list of what curl_getinfo returns here: http://au2.php.net/manual/en/function.curl-getinfo.php
One of which is: CURLINFO_HEADER_OUT - The request string sent
Hope that does it for ya :D

Categories