70

i'm trying using cURL for a GET request like this:

function connect($id_user){
    $ch = curl_init();
    $headers = array(
    'Accept: application/json',
    'Content-Type: application/json',

    );
    curl_setopt($ch, CURLOPT_URL, $this->service_url.'user/'.$id_user);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    $body = '{}';

    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET"); 
    curl_setopt($ch, CURLOPT_POSTFIELDS,$body);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    // Timeout in seconds
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);

    $authToken = curl_exec($ch);

    return $authToken;
}

As you an see i want to pass $body as the request's body , but i don't know if its correct or not and i can't debug this actually, do you know if is the right to use curl_setopt($ch, CURLOPT_POSTFIELDS,$body); with a GET request?

Cause this enteire code works perfect with POST, now i'm trying change this to GET as you can see

Philip G
  • 4,098
  • 2
  • 22
  • 41
itsme
  • 48,972
  • 96
  • 224
  • 345
  • 1
    http://tools.ietf.org/html/rfc2616#section-9.3 - there is no such POSTFIELDS (request message body) for GET method in HTTP. – hakre Jul 07 '13 at 08:44

5 Answers5

65

The accepted answer is wrong. GET requests can indeed contain a body. This is the solution implemented by WordPress, as an example:

curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, 'GET' );
curl_setopt( $ch, CURLOPT_POSTFIELDS, $body );

EDIT: To clarify, the initial curl_setopt is necessary in this instance, because libcurl will default the HTTP method to POST when using CURLOPT_POSTFIELDS (see documentation).

Jonathan Holvey
  • 697
  • 9
  • 27
Dan
  • 3,246
  • 1
  • 32
  • 52
  • 8
    There is no need to use `GET` for `CURLOPT_CUSTOMREQUEST` because with the `libcurl` implementation in PHP it is implied that every request is of type `GET` or `HEAD`. So basically there is no official support for `GET` and Wordpress code is doing what it does best - creating redundancy. –  Jul 23 '15 at 23:34
  • 1
    What harm does explicitly indicating the type do though? By doing it that way they avoid needing extra case statements. It covers `GET`, `DELETE`, `PATCH`, etc. Much cleaner code IMHO. – Dan Jul 23 '15 at 23:36
  • Yet the `request` function still sets default values which include `GET` as the default request method. Wordpress is not a very good example of well written code. –  Jul 23 '15 at 23:46
  • 1
    Have you actually looked at the cited code..? `GET` in the example above is actually a variable. Sounds like you're a webdev who's annoyed that WP makes anyone able to write a website, putting you out of a job ;) – Dan Jul 23 '15 at 23:48
  • `$r['method']` (line 1424) is extracted from the `request` function arguments (line 1361) which is handled by the `wb_parse_args` function which on the other hand uses defaults (line 1354) in case no request option is overridden with the `request` function arguments. It's all in the code you just need to know how to read it. And I don't deal with software like Wordpress. –  Jul 24 '15 at 00:00
  • I have no issues understanding the code. I have issues seeing why you have an issue with calling `CURLOPT_CUSTOMREQUEST` in the context of that `switch`. – Dan Jul 24 '15 at 00:15
  • Because for both `GET` and `HEAD` it's completely redundant. –  Jul 24 '15 at 00:16
  • And as I have already stated, handling them as special cases results in two more case statements instead of lumping all of the remaining cases which can all safely take `CURLOPT_CUSTOMREQUEST` into a single final block. Code bloat is awful and I sincerely hope you are just not thinking -- anyone who consciously pursues more verbose code for no good reason is part of the problem. – Dan Jul 24 '15 at 00:18
  • amazing! Thanks! – Lucas Jan 26 '20 at 13:29
  • What a life saviour.., Thanks's a million. This must've been the accepted answer. – Anjana Silva May 29 '20 at 11:08
  • 1
    By inspecting the actual request data with Wireshark, I can see that the HTTP method being used when setting `CURLOPT_POSTFIELDS` is actually `POST`. This matches libcurl's [documented behaviour](https://curl.haxx.se/libcurl/c/CURLOPT_POSTFIELDS.html); "Using CURLOPT_POSTFIELDS implies setting CURLOPT_POST to 1". Therefore, setting `CURLOPT_CUSTOMREQUEST` *is* required for a `GET` request with a body. – Jonathan Holvey Sep 21 '20 at 00:57
39

CURLOPT_POSTFIELDS as the name suggests, is for the body (payload) of a POST request. For GET requests, the payload is part of the URL in the form of a query string.

In your case, you need to construct the URL with the arguments you need to send (if any), and remove the other options to cURL.

curl_setopt($ch, CURLOPT_URL, $this->service_url.'user/'.$id_user);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_HEADER, 0);

//$body = '{}';
//curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET"); 
//curl_setopt($ch, CURLOPT_POSTFIELDS,$body);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
Burhan Khalid
  • 169,990
  • 18
  • 245
  • 284
  • why does i can't use the request's body in get instead of query string ? :/ – itsme Jun 21 '13 at 08:04
  • That's just how `GET` works. You can send a `POST` request to a URL with a query string, with the `POST` payload in the body of the request and some extra data in the querystring. – Burhan Khalid Jun 21 '13 at 08:09
  • 4
    @BurhanKhalid what you said isn't entirely true. [The GET method](http://tools.ietf.org/html/rfc2616#page-53) doesn't disallow body for GET requests, anyway I don't know anything about the cURL bindings for php. Badbetonbreakbutbedbackbone: searching for your problem I found this project try [it](https://github.com/guzzle/guzzle). – Dario Jun 21 '13 at 08:31
  • 1
    I did not say it is not allowed, I said it is how `GET` works. You can pass any number of things in the body of the request, however the other server will disregard them. The _payload_ of a request (the data that you intend to send across) is what matters; and for `GET`, it is in the query string. – Burhan Khalid Jun 21 '13 at 11:05
  • 1
    How can you know how the server manages the request by the actual call from the client? Since the question implies that badbetonbreakbutbedbackbone needs to inquiry a server that manage the body of a GET request I think that what you wrote isn't correct at all, it's not true that a priori inquired server discard the information. Just my 2 cents. – Dario Jun 21 '13 at 11:43
  • What he asked was, can you use `CURL_POSTFIELDS` to pass a body with a `GET` request; which is not what that option is for. Its not the call that makes the difference, its the method that is used that makes the difference in what and how the server will respond. However, instead of explaining it back and forth - just try it yourself. Open telnet to any server and initiate a GET request, and then try to send something in the body :) – Burhan Khalid Jun 21 '13 at 22:02
  • 1
    So, what I understand by the question is how a php client can send a body in a GET request (he only knows about that option that it does a similar thing in PUT and POST). Before I wrote my first comment I checked if, via cURL (bash command) and via httpie (http://httpie.org/), there's the possibility of sending a body in GET requests. So when I realized that body in GET request are sent I checked the RFC to be sure about it. To enusure myself again I wrote a simple express.js server with a GET route containing request logs:again when I inquired it via httpie I saw what I passed in the body. :) – Dario Jun 22 '13 at 11:55
  • Anyway, even if I really don't know about php internals, reading the documentation about that cURL bindings, I think that you're right saying that it isn't possible sending a body with that thing. – Dario Jun 22 '13 at 11:58
  • As already has been pointed out, the GET method has no request message body. http://tools.ietf.org/html/rfc2616#section-9.3 – hakre Jul 07 '13 at 08:44
  • 2
    This is not the correct answer. It doesn't even answer the original question. It is possible to send a Request Payload with a GET Method outside the URI, in the Request body. @Dario, unfortunately, Guzzle doesn't support it, as it is not in the specification. – Pedro Cordeiro May 12 '14 at 13:32
8
  <?php
  $post = ['batch_id'=> "2"];
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL,'https://example.com/student_list.php');
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));
  $response = curl_exec($ch);
  $result = json_decode($response);
  curl_close($ch); // Close the connection
  $new=   $result->status;
  if( $new =="1")
  {
    echo "<script>alert('Student list')</script>";
  }
  else 
  {
    echo "<script>alert('Not Removed')</script>";
  }

  ?>
Leo
  • 7,274
  • 5
  • 26
  • 48
Siddharth Shukla
  • 1,063
  • 15
  • 14
0

For those coming to this with similar problems, this request library allows you to make external http requests seemlessly within your php application. Simplified GET, POST, PATCH, DELETE and PUT requests.

A sample request would be as below

use Libraries\Request;

$data = [
  'samplekey' => 'value',
  'otherkey' => 'othervalue'
];

$headers = [
  'Content-Type' => 'application/json',
  'Content-Length' => sizeof($data)
];

$response = Request::post('https://example.com', $data, $headers);
// the $response variable contains response from the request

Documentation for the same can be found in the project's README.md

Danny Sofftie
  • 1,031
  • 1
  • 8
  • 16
-2

you have done it the correct way using

curl_setopt($ch, CURLOPT_POSTFIELDS,$body);

but i notice your missing

curl_setopt($ch, CURLOPT_POST,1);
DevZer0
  • 13,433
  • 7
  • 27
  • 51
  • so why should i use that sorry? – itsme Jun 21 '13 at 07:57
  • because your using a POST fields so you must make a post request – DevZer0 Jun 21 '13 at 07:58
  • Do what @Khalid said below – DevZer0 Jun 21 '13 at 08:03
  • 2
    This is also not the answer to this question. REST specifies you have to use a GET request to retrieve information, and you might want to send a few filters in the Request Payload. Switching the method to POST breaks the original specification of the question. Sending a payload within a GET method IS possible, I'm just not sure with libcurl. – Pedro Cordeiro May 12 '14 at 13:34