According to the description of the Google Custom Search API you can invoke it using the GET verb of the REST interface, like with the example:
GET https://www.googleapis.com/customsearch/v1?key=INSERT-YOUR-KEY&cx=017576662512468239146:omuauf_lfve&q=lectures
I setup my API key and custom search engine, and when pasted my test query directly on my browser it worked fine, and I got the JSON file displayed to me.
Then I tried to invoke the API from my PHP code by using:
$json = file_get_contents("$url") or die("failed");
Where $url was the same one that worked on the browser, but my PHP code was dying when trying to open it.
After that I tried with curl, and it worked. The code was this:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$body = curl_exec($ch);
Questions:
How come file_get_contents() didn't work and curl did?
Could I use fsocket for this as well?
Question 1:
At first you should check ini setting allow_url_fopen, AFAIK this is the only reason why file_get_contents() shouldn't work. Also deprecated safe_mode may cause this.
Oh, based on your comment, you have to add http:// to URL when using with file system functions, it's a wrapper that tells php that you need to use http request, without it function thinks you require to open ./google.com (the same as google.txt).
Question 2:
Yes, you can build almost any cURL request with sockets.
My personal opinion is that you should stick with cURL because:
timeout settings
handles all possible HTTP states
easy and detailed configuration (there is no need for detailed knowledge of HTTP headers)
file_get_contents probably will rewrite your request after getting the IP, obtaining the same thing as:
file_get_contents("xxx.yyy.www.zzz/app1",...)
Many servers will deny you access if you go through IP addressing in the request.
With cURL this problem doesn't exists. It resolves the hostname leaving the request as you set it, so the server is not rude in response.
This could be the "cause", too..
1) Why are you using the quotes when calling file_get_contents?
2) As it was mentioned in the comment, file_get_contents requires allow_url_fopen to be enabled on your php.ini.
3) You could use fsockopen, but you would have to handle HTTP requests/responses manually, which would be to reinvent the wheel when you have cURL. The same goes for socket_create.
4) Regarding the title of this question: cURL can be more customizable and useful to work with complex HTTP transactions than file_get_contents. Though, it should be mentioned, that working with stream contexts allows you to make a lot of settings for your file_get_contents calls. However, I think cURL is still more complete since it gives you, for instance, the possibility of working with multiple parallel handlers.
Related
I am using file_get_contents in PHP to get information from a client's collections on contentDM. CDM has an API so you can get that info by making php queries, like, say:
http://servername:port/webutilities/index.php?q=function/arguments
It has worked pretty well thus far, across computers and operating systems. However, this time things work a little differently.
http://servername/utils/collection/mycollectionname/id/myid/filename/myname
For this query I fill in mycollection, myid, and myname with relevant values. myid and mycollection have to exist in the system, obviously. However, myname can be anything you want. When you run the query, it doesn't return a web page or anything to your browser. It just automatically downloads a file with myname as the name of the file, and puts it in your local /Downloads folder.
I DON'T WISH TO DOWNLOAD THIS FILE. I just want to read the contents of the file it returns directly into PHP as a string. The file I am trying to get just contains xml data.
file_get_contents works to get the data in that file, if I use it with PHP7 and Apache on my laptop running Ubuntu. But, on my desktop which runs Windows 10, and XAMPP (Apache and PHP5), I get this error (I've replaced sensitive data with ###):
Warning:
file_get_contents(###/utils/collection/###/id/1110/filename/1111.cpd):
failed to open stream: No such file or directory in
D:\Titus\Documents\GitHub\NativeAmericanSCArchive\NASCA-site\api\update.php
on line 18
My coworkers have been unable to help me so I am curious if anyone here can confirm or deny whether this is an operating system issue, or a PHP version issue, and whether there's a solid alternative method that is likely to work in PHP5 and on both Windows and Ubuntu.
file_get_contents() is a simple screwdriver. It's very good for getting data by simply GET requests where the header, HTTP request method, timeout, cookiejar, redirects, and other important things do not matter.
fopen() with a stream context or cURL with setopt are powerdrills with every bit and option you can think of.
In addition to this, due to some recent website hacks, we had to secure our sites more. In doing so, we discovered that file_get_contents failed to work, where curl still would work.
Not 100%, but I believe that this php.ini setting may have been blocking the file_get_contents request.
; Disable allow_url_fopen for security reasons
allow_url_fopen = 0
Either way, our code now works with curl.
reference :
http://25labs.com/alternative-for-file_get_contents-using-curl/
http://phpsec.org/projects/phpsecinfo/tests/allow_url_fopen.html
So, You can solve this problem by using PHP cURL extension. Here is an example that does the same thing you were trying:
function curl($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
$url = 'your_api_url';
$data = curl($url);
And finally you can check your data by print_r($data). Hope it you it will works and you will understand.
Reference : http://php.net/manual/en/book.curl.php
I'm writing ActionScript3 flash game, which needs to access REST services specified by sponsor (buyer of game) - things like highscores etc. I know how to use URLLoader, URLRequest, set URLRequestHeader.
Unfortunately sponsor is on shared hosting and can't put crossdomain.xml in the server root, so I can't connect to it from my localhost flash game (Same Origin Policy). I learned that there is a way to connect to rest API by proxying calls through a php file on a different server.
So I have a proxy.php file on my private server, and am calling it like:
www.myserver.pl/scripts/proxy.php?url=http%3A%2F%2sponsorserver.hosting.com/api/init.json
(url=URLEncoded address)
It connects (returns HTTP 200), however I don't know yet how to pass custom headers to the init.json script; I tried all combinations sending them through GET and POST, as well as calling script through GET and POST (using RESTClient FF extension).
This is the proxy.php:
$getvars = 'myparam1=3;&myparam2=data;'; // for test purposes
$url = $_GET['url'] . '?' . $getvars;
$session = curl_init($url);
curl_setopt($session, CURLOPT_HEADER, true);
curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec_follow($session);
echo $response;
curl_close($session);
Unfortunately my server has base_dir != '' so I can't set CURLOPT_FOLLOWLOCATION and use curl_exec, hence the curl_exec_follow (taken from this SO answer: https://stackoverflow.com/a/10835824/2492808). Could it be why the GET variables are not picked up by the init.json? It says it doesn't see the myparam1 and myparam2. Unfortunately I can't change php.ini on my server, and need a way to make it working, so that I can integrate and test sponsor's rest API from my IDE. Thanks!
EDIT: that was stupid, it's not the GET variables that I want to send to sponsor script, but http headers. So I've removed $getvars and added:
curl_setopt ($session, CURLOPT_HTTPHEADER, Array('myparam1=3','myparam2=data'));
before curl_exec_follow and inside, before every new curl_exec call, which theoretically should set the headers and make them through. Unfortunately, script still doesn't see the headers :(
Also, according to php manual, I tried removing base_opendir restriction by putting .htaccess in www.myserver.pl/scripts/:
<IfModule mod_php5.c>
php_value open_basedir ""
</IfModule>
But it's not changing anything, probably I don't have
"AllowOverride Options" or "AllowOverride All" privileges to do so
so CURLOPT_FOLLOWLOCATION is still illegal.
Unfortunately I can't change php.ini on my server, and need a way to make it working, so that I can integrate and test sponsor's rest API from my IDE. Thanks!
Useless excuse these days. Buy a $15 per month server hosted on the amazon cloud. It's easier to spend $15 than to spend an hour writing code for an easily solvable problem. You were probably spending $10 anyway on a shared hosting plan.
I'm using Eclipse and XDebug to develop a PHP application that relies on web services.
I have test pages that consume my services in 2 ways: AJAX (using jQuery) and cURL.
I add breakpoints to my service page and launch the debugger. When I call the the service from AJAX, execution stops nicely at the breakpoint, and I get my variables, step-by-step control etc.
But when I call the service using cURL (i.e. from within a PHP page), the breakpoints fail to function. Even if I turn on the "Break at first line" debugger option, I cannot get the execution to stop when using cURL.
Is it a debugger behavior? Do I need to add a hearder to my cURL calls? Alter the URL? Or is it an XDebug limitation?
Thanks for your time and effort,
Guy
I can't comment yet, so I post this as an answer.
Can you debug more than one AJAX request in one session?
Was your debug session still running in Eclipse when you tried to debug using cURL?
Description on how it works for me:
Start debug session with a simple debug.php file that contains only a <?php and nothing else. It stops on the first line, you "continue" it and it finishes execution.
Now request the script using cURL (or another browser) adding ?XDEBUG_SESSION_START=ECLIPSE_DBGP to its path (I even think this addition is optional)
Your script should show up in the debug view stopped at the first line
Hope ths helps.
Here is tip on how to trigger Xdebugger client from Curl without browser:
1- From command line:
curl -H "Cookie: XDEBUG_SESSION=1" http://YOUR-SITE.com/your-script.php
2- From PHP
<?php
$ch = curl_init ();
curl_setopt ($ch, CURLOPT_URL, 'http://YOUR-SITE.com/your-script.php');
curl_setopt ($ch, CURLOPT_COOKIE, 'XDEBUG_SESSION=1');
curl_exec ($ch);
?>
So it doesn't matter if you attach "XDEBUG_SESSION=1" to CURL URL, but what is necessary is to send a proper cookie together with request.
I know this is a pretty old thread, but I thought I'd post my experience for others that may come across it, like I did, with the same problem. What I discovered is that, if you are debugging remotely (which I always do), there are a couple settings you have to change in php.ini to make this work. Here are the ones that worked for me:
xdebug.remote_connect_back = false
xdebug.remote_host = {client host name or IP}
The first setting is normally "true," and tells xdebug to look for the client at the same IP address where the HTTP request originated. In this case however, the request is coming from the server, so that won't work. Instead you must use the second setting to tell xdebug where to find the client. Hope this helps save somebody a little time!
To trigger the debugger the simplest solution is to use the cookie approach -b XDEBUG_SESSION=ECLIPSE_DBGP worked for me on eclipse, see below:
curl -H 'Content-type: application/json' \
-b XDEBUG_SESSION="ECLIPSE_DBGP" \
-X POST \
-d '{"uid":200, "message":"asdsad","message_type":1}'
http://daxuebao.local:8083/api/message/send
When you are debugging the Ajax request, that one is sent by the browser, in the same navigation context as the other (non-Ajax) requests -- which is why it works fine.
The request sent by curl is in another, different, context -- and I'm not sure you can hook the debugger into that... But, maybe...
First of all, here's an information that might prove helpful, quoting the Xdebug's documentation :
Xdebug contains functionality to keep
track of a debug session when started
through a browser: cookies. This works
like this:
When the URL variable XDEBUG_SESSION_START=name is
appended to an URL Xdebug emits a
cookie with the name
"XDEBUG_SESSION" and as value the
value of the XDEBUG_SESSION_START
URL parameter.
When there is a GET (or POST) variable XDEBUG_SESSION_START or the
XDEBUG_SESSION cookie is set, Xdebug
will try to connect to a debugclient.
To stop a debug session (and to destroy the cookie) simply add the URL
parameter XDEBUG_SESSION_STOP.
Xdebug will then no longer try to make
a connection to the debugclient.
Maybe it might work if you set that cookie "by hand", sending it allong the curl request...
I suppose you'd first have to get its value, as set by Xdebug at the beginning of the debugging session -- re-using the cookie you have in your browser should be possible, though.
Note : I've never tried this -- if you try, and it works, could you please confirm it worked ?
I ran into this same exact issue. I solved it by turning the auto-start feature off in php.ini:
xdebug.remote_autostart = 0
and then adding the API key to the webservice URL that my webservice client calls:
?XDEBUG_SESSION_START=<your API key here>
and I'm not sure if this matters, but I entered the API key into my debugger (MacGDBp). Now the debugger fires up only when the webervice server-side script is called, not when the client is started.
Hope this helps.
I'm using curl in PHP to check the HTTP code when requesting some files, I'm trying to make my speed run faster so I'm wondering is there a way to make it get the HTTP code without actually getting the web page from the remote host
Set CURLOPT_NOBODY to true. This means that rather than preforming a GET or POST request, a HEAD request will be preformed so the remote server will only return the HTTP header.
curl_setopt($ch, CURLOPT_NOBODY, true);
There is also some example code in this answer
I'm using Eclipse and XDebug to develop a PHP application that relies on web services.
I have test pages that consume my services in 2 ways: AJAX (using jQuery) and cURL.
I add breakpoints to my service page and launch the debugger. When I call the the service from AJAX, execution stops nicely at the breakpoint, and I get my variables, step-by-step control etc.
But when I call the service using cURL (i.e. from within a PHP page), the breakpoints fail to function. Even if I turn on the "Break at first line" debugger option, I cannot get the execution to stop when using cURL.
Is it a debugger behavior? Do I need to add a hearder to my cURL calls? Alter the URL? Or is it an XDebug limitation?
Thanks for your time and effort,
Guy
I can't comment yet, so I post this as an answer.
Can you debug more than one AJAX request in one session?
Was your debug session still running in Eclipse when you tried to debug using cURL?
Description on how it works for me:
Start debug session with a simple debug.php file that contains only a <?php and nothing else. It stops on the first line, you "continue" it and it finishes execution.
Now request the script using cURL (or another browser) adding ?XDEBUG_SESSION_START=ECLIPSE_DBGP to its path (I even think this addition is optional)
Your script should show up in the debug view stopped at the first line
Hope ths helps.
Here is tip on how to trigger Xdebugger client from Curl without browser:
1- From command line:
curl -H "Cookie: XDEBUG_SESSION=1" http://YOUR-SITE.com/your-script.php
2- From PHP
<?php
$ch = curl_init ();
curl_setopt ($ch, CURLOPT_URL, 'http://YOUR-SITE.com/your-script.php');
curl_setopt ($ch, CURLOPT_COOKIE, 'XDEBUG_SESSION=1');
curl_exec ($ch);
?>
So it doesn't matter if you attach "XDEBUG_SESSION=1" to CURL URL, but what is necessary is to send a proper cookie together with request.
I know this is a pretty old thread, but I thought I'd post my experience for others that may come across it, like I did, with the same problem. What I discovered is that, if you are debugging remotely (which I always do), there are a couple settings you have to change in php.ini to make this work. Here are the ones that worked for me:
xdebug.remote_connect_back = false
xdebug.remote_host = {client host name or IP}
The first setting is normally "true," and tells xdebug to look for the client at the same IP address where the HTTP request originated. In this case however, the request is coming from the server, so that won't work. Instead you must use the second setting to tell xdebug where to find the client. Hope this helps save somebody a little time!
To trigger the debugger the simplest solution is to use the cookie approach -b XDEBUG_SESSION=ECLIPSE_DBGP worked for me on eclipse, see below:
curl -H 'Content-type: application/json' \
-b XDEBUG_SESSION="ECLIPSE_DBGP" \
-X POST \
-d '{"uid":200, "message":"asdsad","message_type":1}'
http://daxuebao.local:8083/api/message/send
When you are debugging the Ajax request, that one is sent by the browser, in the same navigation context as the other (non-Ajax) requests -- which is why it works fine.
The request sent by curl is in another, different, context -- and I'm not sure you can hook the debugger into that... But, maybe...
First of all, here's an information that might prove helpful, quoting the Xdebug's documentation :
Xdebug contains functionality to keep
track of a debug session when started
through a browser: cookies. This works
like this:
When the URL variable XDEBUG_SESSION_START=name is
appended to an URL Xdebug emits a
cookie with the name
"XDEBUG_SESSION" and as value the
value of the XDEBUG_SESSION_START
URL parameter.
When there is a GET (or POST) variable XDEBUG_SESSION_START or the
XDEBUG_SESSION cookie is set, Xdebug
will try to connect to a debugclient.
To stop a debug session (and to destroy the cookie) simply add the URL
parameter XDEBUG_SESSION_STOP.
Xdebug will then no longer try to make
a connection to the debugclient.
Maybe it might work if you set that cookie "by hand", sending it allong the curl request...
I suppose you'd first have to get its value, as set by Xdebug at the beginning of the debugging session -- re-using the cookie you have in your browser should be possible, though.
Note : I've never tried this -- if you try, and it works, could you please confirm it worked ?
I ran into this same exact issue. I solved it by turning the auto-start feature off in php.ini:
xdebug.remote_autostart = 0
and then adding the API key to the webservice URL that my webservice client calls:
?XDEBUG_SESSION_START=<your API key here>
and I'm not sure if this matters, but I entered the API key into my debugger (MacGDBp). Now the debugger fires up only when the webervice server-side script is called, not when the client is started.
Hope this helps.