2

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?

michnovka
  • 2,880
  • 3
  • 26
  • 58
  • If it's JSON to be sent, better use POST. GET has a limit on params size and length. – nice_dev Jun 24 '19 at 15:42
  • are u using `Content-Type: application/json` in curl header? – devpro Jun 24 '19 at 15:44
  • I will likely not breach this limit. The question is not what I should use, but how to pass raw data with GET. This is perfectly possible with e.g. Postman app – michnovka Jun 24 '19 at 15:44
  • @devpro yes, I am, but that does not help me ATTACH the data to the request. As soon as I set CURLOPT_POSTFIELDS request type is set to POST and not GET – michnovka Jun 24 '19 at 15:44
  • @michnovka Ok, I wasn't aware that your params wouldn't breach the limit. However, it's unclear about what kind of `raw` data you are trying to send in `GET` request and how did `CURLOPT_POSTFIELDS` come into the picture? – nice_dev Jun 24 '19 at 15:47
  • send complete example your curl code... with request url... or try with **Query String**... if you want this with GET – devpro Jun 24 '19 at 15:49
  • Abstract out "params" idea from your code and wrap it so if its a post() method it posts, if its a get() you use http_build_query to build out the url. Or use a lib, which has thousands of man-hours and unit tests :/ – Lawrence Cherone Jun 24 '19 at 15:50
  • 1
    Why do weird, non-standard things with requests that every user of the API will potentially need to deal with, figure out, and work around standards in their request libraries? Just do POST if there will be a request body. – drew010 Jun 24 '19 at 22:59

1 Answers1

5

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.

Community
  • 1
  • 1
miken32
  • 42,008
  • 16
  • 111
  • 154