Monday, 18 August 2014

Making a PUT request using PHP and cURL

I recently had to write some PHP to PUT some JSON data to a RESTful web API. My final solution involved reading numerous blog posts to piece together exactly what I needed. Bearing that in mind I decided to document my solution in case it’s useful to others, and for my own future use.

The conventional technique for invoking a PUT operation is to set CURLOPT_PUT to true. However, this option is used to PUT a file, with the file to PUT being set with CURLOPT_INFILE and CURLOPT_INFILESIZE. Using this approach involves writing your JSON data to a file first, and removing the file after the operation. Aside from the inefficiency of this approach, functions such as tmpfile(), fwrite() and fseek() are not always supported in some environments.

The standard solution is to set CURLOPT_CUSTOMREQUEST to “PUT” in order to specify the request type, and then set the CURLOPT_POSTFIELDS to the JSON data you want to PUT. In addition, you must set CURLOPT_RETURNTRANSFER to true in order to return the transfer value as a string, rather than it being output directly by curl_exec(). This is a well documented solution, most notably by LornaJane.

However, this solution needed extending in order to enable communication over SSL. In addition, I needed to append some custom header information to the request in order to support the authentication required by the web service. My solution is shown below.

1 function callRestAPI($uri, $signature, $json) {
2 $headers = array (
3 "Content-Type: application/json; charset=utf-8",
4 "Content-Length: " .strlen($json),
5 "X-Signature: " . $signature
6 );
7
8 $channel = curl_init($uri);
9 curl_setopt($channel, CURLOPT_RETURNTRANSFER, true);
10 curl_setopt($channel, CURLOPT_CUSTOMREQUEST, "PUT");
11 curl_setopt($channel, CURLOPT_HTTPHEADER, $headers);
12 curl_setopt($channel, CURLOPT_POSTFIELDS, $json);
13 curl_setopt($channel, CURLOPT_SSL_VERIFYPEER, false);
14 curl_setopt($channel, CURLOPT_CONNECTTIMEOUT, 10);
15
16 curl_exec($channel);
17 $statusCode = curl_getInfo($channel, CURLINFO_HTTP_CODE);
18 curl_close($channel);
19 return $statusCode;
20 }

The important additions are that I set:

  1. CURLOPT_SSL_VERIFYPEER to false to stop cURL from verifying the peer’s certificate, thus enabling communication over SSL. By default this value is true, and you are meant to set CURLOPT_CAINFO to specify the file holding the certificate to verify the peer with. I opted for stopping cURL from verifying the peer’s certificate in the interests of simplicity.
  2. CURLOPT_HTTPHEADER to an array of HTTP header fields, containing the data required by the web service, including an authentication parameter.

In addition, after executing the PUT request I called curl_getInfo to get information about the PUT request. Specifically I requested the status code of the operation using the CURLINFO_HTTP_CODE constant. This provides the HTTP status code contained within the response message, which is then returned to the calling function, so that an appropriate message can be output.

1 comment:

  1. i need to create a a form in my wesitethat use api to give the possibility who buy an our sub account to create it self.. i have seen the script api jason:
    {
    "authentication": {
    "apiKey": "apiKeyAsSetInAccountSettings"
    },
    "createAccount": [
    {
    "username": "username",
    "password": "password",
    "apiKey": "YourKeyToUseForTheNewAccount",
    "email": "mail@email.com",
    "role": "0"
    }
    ]
    }

    can you say me if is possible and how i combine this script to put in a form in my website?

    ReplyDelete