I am trying to retrieve data from a server which usually returns it in XML, however I trying to request it in a JSON format (if requested correctly it will return the data in JSON).
$header = array(
'http' => array(
'header'=>"Content-type: application/json"
),
);
$response = file_get_contents($query, false, $header);
print_r($response);
This approach was taken from here. Currently the program does not return anything.
Does anyone spot any potential problems with this?
You need to set the HTTP Accept header to tell the server that you want it to give you JSON:
Accept: application/json
(assuming that the remote server is correctly implemented to read the header)
The Content-Type request header indicates the type of the payload that you are POSTing.
In your case, it does not apply, since you're sending a GET request.
Related
I am developing REST API and while it is easy to set raw JSON data for request in cURL for POST
$payload = json_encode(array("user" => $data));
//attach encoded JSON string to the POST fields
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
I cannot figure out how to send such data with GET requests.
Is there something like CURLOPT_GETFIELDS or CURLOPT_RAWDATA? The purpose of sending JSON with GET request is to pass in some params.
I do not wish to add formdata to the request, I wish to post JSON so that it can be parsed on the receiver.
Thanks!
EDIT:
based on comments I want to avoid confusion, so the resulting request should look like:
GET / HTTP/1.1
Host: 127.0.0.1:3000
Content-Type: application/json
Accept: application/json
Host: 127.0.0.1:3000
content-length: 13
Connection: keep-alive
cache-control: no-cache
{
"a": "b"
}
as you can see, GET request here has data and it is parsed and works perfectly by web server. How do I achieve this with cURL?
GET requests do not have a body, that's the whole idea: you're just getting something from the server, as opposed to posting something to it. From RFC 7231:
A payload within a GET request message has no defined semantics;
sending a payload body on a GET request might cause some existing
implementations to reject the request.
In other words, a GET request can have data, but it should not. From earlier in the spec, where GET is defined as a safe method:
Request methods are considered "safe" if their defined semantics are
essentially read-only; i.e., the client does not request, and does
not expect, any state change on the origin server as a result of
applying a safe method to a target resource.
...
Of the request methods defined by this specification, the GET, HEAD,
OPTIONS, and TRACE methods are defined to be safe.
If you really want to have JSON in your GET request (and send it to a reasonably implemented server resource) the only place it can go is in the URI as part of the query string. For GET requests I find using file_get_contents to be much easier than dealing with cURL.
<?php
$payload = json_encode(["user" => $data]);
$url_data = http_build_query([
"json" => $payload
]);
$url = "https://some.example/endpoint.php?" . $url_data;
$result = file_get_contents($url);
If you want to send it to an unreasonably implemented server resource, and violate the spirit of the HTTP RFCs, you could do this:
<?php
$url = "https://some.example/endpoint.php";
$payload = json_encode(["user" => $data]);
$ctx = stream_context_create(["http" => [
"header"=>"Content-Type: application/json",
"content"=>$payload
]]);
$result = file_get_contents($url, false, $ctx);
If you're determined to do this specifically with cURL, you might have luck with the CURLOPT_CUSTOMREQUEST option set to "GET" and CURLOPT_POSTDATA with your data.
I am working on proxy with PHP. In my php code I am sending proper required headers and expected to get response body and headers. However I am getting response body correctly as I want but not getting headers properly (supposed to get Status 200 but getting 401). When i traced with firefox I found that SAP URL itsself making 2 request internally by using data which I send. so with my first request it is not authenticated so SAP url itslef managining to send same request again and 2nd time it gives both proper response body with headers. Howevber I php code when I get it i get response body from 2nd response and headers from 1st response.
here is code.
$opts = array(
'http'=>array(
'method'=>"POST",
'content' => $xml_request,
'header'=>array("Host:" . $sap_url,
"Content-Type: text/xml; charset=UTF-8",
$authstring,$xml_request)
)
);
$context = stream_context_create($opts);
$result = file_get_contents($sap_url, false, $context);
$http_res_array = get_headers($sap_url);
You should probably use curl functions instead and do BOTH requests yourself. file_get_contents, does the second request for you, but takes away the possibility to fetch the second headers.
Maybe a little old but anyways:
You're using the get_headers()-function to get the headers. It's documentation states that:
Fetches all the headers sent by the server in response to a [new] HTTP request
It doesn't empathize that this function will actually send a new request to the server and return the response-header for that request. Therefor, the headers can be slightly different.
Since you're using file_get_contents() to load the content, you can use the global $http_response_header-variable right after your request, which will contain the response-header from the last executed request.
I have a basic API endpoint set up on my site, which a 3rd party site will use to verify certain info that is entered into a form by the user.
Here's the flow:
1. User is on 3rd party site.
2. User enters info into a form
3. Info is sent to my site's endpoint.
4. My site checks the information and returns a JSON object.
As you can see from #4, my API is currently set up to return a JSON object. After the info is checked, something like this happens:
header('content-type: application/json; charset=utf-8');
echo json_encode($response);
exit;
However, the 3rd party site is only set up to receive URL variables. Is there a way to pass back url variables programmatically? I realize I could theoretically send a new request, but it's not clear to me where that request should go (the internal workings of the 3rd party site aren't well documented), so I'd much prefer to send it as a response.
I hope this makes sense. Please comment if it doesn't. Thanks in advance!
You don't get to send GET/POST parameters in the response, but in the response body you can send whatever you want in whatever format you want - and they can use curl or file_get_content and parse it on their side (3rd party's website).
For example (on the 3rd party's website):
//setting a call to your server
$opts = array('http' =>
array(
'method' => 'POST',
'header' => "Content-Type: text/xml\r\n".
"Authorization: Basic ".base64_encode("$https_user:$https_password")."\r\n",
'content' => $body,
'timeout' => 60
)
);
$context = stream_context_create($opts);
$url = 'https://'.$https_server;
// Here they call your server
$result = file_get_contents($url, false, $context, -1, 40000);
// Here you'll parse the $result
I'm working on a XML reader and am running into a odd issue with a few feeds. Using CURL or even file_get_contents the feeds load as binary data more often than real data. Whenever I load the feed in a browser it looks fine.
The specific feed is http://www.winnipegsun.com/home/rss.xml
The code I am using is
$string = file_get_contents("http://www.winnipegsun.com/home/rss.xml");
var_dump( $string );
The response is gzipped:
If you look at the HTTP headers:
Content-Encoding: gzip
Unzip it with PHP:
gzinflate(substr($string, 10));
http://php.net/manual/en/function.gzinflate.php
Hope that helps... cheers
You should be able to send an empty Accept-Encoding header to the server and then it should not send the content gzipped or return a Not Acceptable response:
$string = file_get_contents(
"http://www.winnipegsun.com/home/rss.xml",
FALSE,
stream_context_create(
array(
'http' => array(
'method' => "GET",
'headers' => 'Accept-Encoding:\r\n'
)
)
)
);
var_dump($string);
I am not sure the webserver is configured correctly though, because it wouldnt respond to that with the uncompressed feed, even when adding Cache Control headers telling to it not send a cached response. Oddly enough, just doing
$string = file_get_contents("http://www.winnipegsun.com/home/rss.xml?".time());
worked out of the box. And you can also send a POST request.
I've set up a REST service and client in PHP and I'm having a bit of trouble with PUT.
Here's my situation:
I'm coding a REST resource that should accept an array of data and an image. The REST resource should update an existing record, so I'm using PUT. I'm sending the data with a PHP curl client I wrote. So - pretty much the same situation as if you were sending a HTML multipart form to a PHP script that does a file upload and accepts some additional POST fields - except with PUT and PHP curl..
Up 'till now I've been sending the PUT request something like this (pseudo code):
$a_some_data = array('name' => 'test', 'user_id' => 4);
$body = http_build_query($a_data);
$fh = fopen('php://memory', 'rw');
fwrite($body);
rewind($fh);
$ch = curl_init();
curl_setopt_array($ch, array(
CURLOPT_URL => 'http://myapi/resource/someid',
CURLOPT_PUT => TRUE,
CURLOPT_INFILE => $fh,
CURLOPT_INFILESIZE => strlen($body)
));
curl_exec($ch);
and reading the data on the server like so:
parse_str(file_get_contents('php://input'), $put_data);
..which works just fine.
So now I would like to add a (binary) file into the mix.
- How would I implement this on the client side?
- How would I deal with the file on the server?
For a test I set up a HTML form with a file input, copied the raw multipart/form-data request it sends, and tried sending that data as a file with curl in a PUT request. That kind of works, but I would have to parse the raw data on the server manually, which I'm not sure is the best idea. Alternatively, I guess I could send the file as the body of the PUT request, and add the other parameters in the URL as a query string - but I guess that kind of defies the point of a PUT REST resource..
Please share your thoughts on this.
Thanks!
There are at least two other ways unless your original version isn't enough (since libcurl should deal just fine with binary files too with that script). Note that how you decide receive the PUT in the receiving end is not a curl issue so I'll leave it out of this response.
1 - Like you started out, but provide a CURLOPT_READFUNCTION with which you feed the data to libcurl that it will send.
2 - Use CURLOPT_POSTFIELDS (with a string) and make it look like a POST, and then you change the HTTP method with CURLOPT_CUSTOMREQUEST to "PUT"