65

I have been working on building an Rest API for the hell of it and I have been testing it out as I go along by using curl from the command line which is very easy for CRUD

I can successfully make these call from the command line

curl -u username:pass -X GET http://api.mysite.com/pet/1
curl -d '{"dog":"tall"}' -u username:pass -X GET http://api.mysite.com/pet
curl -d '{"dog":"short"}' -u username:pass -X POST http://api.mysite.com/pet
curl -d '{"dog":"tall"}' -u username:pass -X PUT http://api.mysite.com/pet/1

The above calls are easy to make from the command line and work fine with my api, but now I want to use PHP to create the curl. As you can see, I pass data as a json string. I have read around and I think I can probably do the POST and include the POST fields, but I have not been able to find out how to pass http body data with GET. Everything I see says you must attached it to the url, but it doesn't look that way on the command line form. Any way, I would love it if someone could write the correct way to do these four operations in PHP here on one page. I would like to see the simplest way to do it with curl and php. I think I need to pass everything through the http body because my php api catching everything with php://input

Gilberg
  • 2,514
  • 4
  • 31
  • 41

5 Answers5

179

PUT

$data = array('username'=>'dog','password'=>'tall');
$data_json = json_encode($data);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json','Content-Length: ' . strlen($data_json)));
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_POSTFIELDS,$data_json);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response  = curl_exec($ch);
curl_close($ch);

POST

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,$data_json);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response  = curl_exec($ch);
curl_close($ch);

GET See @Dan H answer

DELETE

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
curl_setopt($ch, CURLOPT_POSTFIELDS,$data_json);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response  = curl_exec($ch);
curl_close($ch);
voodoo417
  • 11,861
  • 3
  • 36
  • 40
  • Thanks for the PUT, if you can add the GET (with json in the body) and POST i'll accept – Gilberg Jan 21 '14 at 23:50
  • 1
    @Gilberg added for POST. In GET-request data is passing through url :) – voodoo417 Jan 21 '14 at 23:55
  • Thanks, I can't use Dan's because my api is waiting for php://input and if I include it in the url it won't go to the php://input stream. In short I can't grab it from $_GET, I could but it would be a small headache. I can do it easliy from the command line with `curl -d '{json-string}' -X GET http://api.mysite.com/user` so there has got to be a way to mimic that in php – Gilberg Jan 22 '14 at 00:03
  • Thanks @voodoo4q7 I'll accept, but I would still like to see how to pass data in the body of a GET. I know my server accepts it so it is not a problem for me. – Gilberg Jan 22 '14 at 00:08
  • @Gilberg curl add params to url - you just doesnt see – voodoo417 Jan 22 '14 at 00:19
  • Are you sure about that? From the command line I tried `curl -u username:pass -X GET http://api.mysite.com/user?test=data` and got no data in php://input stream, but `curl -d '{"test":"data"}' -u username:pass -X GET http://api.mysite.com/user` came through in php://input – Gilberg Jan 22 '14 at 00:34
  • @voodoo417 : I like you answer, it's really straightforward. Can you show us how are receiving our post after we receive it ? – iori Feb 02 '15 at 13:29
  • @voodoo417: And what if I need to update the "updated_at" timestamp along with it... – Vagabond May 28 '15 at 17:07
  • 1
    Could you use CURLOPT_PUT as well? – robsch Aug 11 '16 at 14:53
  • How to get JSON url in Destination page, I tried, but no luck. `file_get_contents("php://input")` – Lim Socheat Mar 02 '17 at 10:24
  • Don't you need to set the `"Content-Length: $len"` for `POST` and `DELETE` too? – Nigel Alderton Jun 08 '18 at 10:15
  • @voodoo417 The only part missing in your solution was `curl_setopt($ch, CURLOPT_USERPWD, "user:pass")` to cover the autentication part – Luiz Vaz Jun 28 '18 at 04:57
  • Kudos to this mother f***er for writing down CURLOPT_CUSTOMREQUEST in this answer. Using this instead of CURLOPT_PUT solved my issue. – Millar248 Aug 13 '18 at 13:48
  • If it helps anyone, for the server I was working with I had to add an "Accept: application/json" header for all PUT requests. Apparently this is due to how some servers are configured. – dougd_in_nc Dec 17 '19 at 23:28
  • Note the addition of 'Content-Length' with the PUT call. This is required otherwise the receiver will report an empty $this->request["data"] (Cake/Php). – Jan Jul 06 '22 at 10:19
11

You can use this small library: https://github.com/ledfusion/php-rest-curl

Making a call is as simple as:

// GET
$result = RestCurl::get($URL, array('id' => 12345678));

// POST
$result = RestCurl::post($URL, array('name' => 'John'));

// PUT
$result = RestCurl::put($URL, array('$set' => array('lastName' => "Smith")));

// DELETE
$result = RestCurl::delete($URL); 

And for the $result variable:

  • $result['status'] is the HTTP response code
  • $result['data'] an array with the JSON response parsed
  • $result['header'] a string with the response headers

Hope it helps

brickpop
  • 2,754
  • 1
  • 13
  • 12
5

For myself, I just encode it in the url and use $_GET on the destination page. Here's a line as an example.

$ch = curl_init();
$this->json->p->method = "whatever";
curl_setopt($ch, CURLOPT_URL, "http://" . $_SERVER['SERVER_NAME'] . $this->json->path . '?json=' . urlencode(json_encode($this->json->p)));
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec($ch);
curl_close($ch);

EDIT: Adding the destination snippet... (EDIT 2 added more above at OPs request)

<?php
if(!isset($_GET['json']))
    die("FAILURE");
$json = json_decode($_GET['json']);
$method = $json->method;
...
?>
Dan H
  • 606
  • 4
  • 6
  • 1
    Thanks, could you write out your complete curl code in php to make it clear how you define POST,GET,PUT,DELETE. My API looks for those methods. – Gilberg Jan 21 '14 at 23:31
  • Added. It's just a simple HTTP request, but as you can see on the destination I use GET. It's literally just to move a json string around (for example, from my application front end, to script1, to script2, which then gets replied back to the app front end -- not included in source). – Dan H Jan 21 '14 at 23:37
  • +1, but I am going to wait for the POST, PUT and DELETE because the rest api I wrote needs those – Gilberg Jan 21 '14 at 23:52
0

I was Working with Elastic SQL plugin. Query is done with GET method using cURL as below:

curl -XGET http://localhost:9200/_sql/_explain -H 'Content-Type: application/json' \
-d 'SELECT city.keyword as city FROM routes group by city.keyword order by city'

I exposed a custom port at public server, doing a reverse proxy with Basic Auth set.

This code, works fine plus Basic Auth Header:

$host = 'http://myhost.com:9200';
$uri = "/_sql/_explain";
$auth = "john:doe";
$data = "SELECT city.keyword as city FROM routes group by city.keyword order by city";

function restCurl($host, $uri, $data = null, $auth = null, $method = 'DELETE'){
    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $host.$uri);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    if ($method == 'POST')
        curl_setopt($ch, CURLOPT_POST, 1);
    if ($auth)
        curl_setopt($ch, CURLOPT_USERPWD, $auth);
    if (strlen($data) > 0)
        curl_setopt($ch, CURLOPT_POSTFIELDS,$data);

    $resp  = curl_exec($ch);
    if(!$resp){
        $resp = (json_encode(array(array("error" => curl_error($ch), "code" => curl_errno($ch)))));
    }   
    curl_close($ch);
    return $resp;
}

$resp = restCurl($host, $uri); //DELETE
$resp = restCurl($host, $uri, $data, $auth, 'GET'); //GET
$resp = restCurl($host, $uri, $data, $auth, 'POST'); //POST
$resp = restCurl($host, $uri, $data, $auth, 'PUT'); //PUT
Luiz Vaz
  • 1,669
  • 1
  • 19
  • 32
-3

set one more property curl_setopt($ch, CURLOPT_SSL_VERIFYPEER , false);

  • This is bad advice. Setting that flag means you're not validating the SSL certificate. It opens you up to DNS hijacking. – Machavity Jul 07 '17 at 16:28