How to convert form fields into JSON data and submit data with HTTP POST using curl in PHP

Written by - 0 comments

Published on - Listed in PHP Coding


When data needs to be submitted to an external URL, an API for example, curl can be used. Curl exists on both the command line and as a library in many programming languages, such as PHP.

Using curl in PHP and submit (POST) data to external URL

POSTing data with curl, the command

Starting with the curl command is usually very helpful. It also helps to understand how the remote URL works, what fields are required and what input types (such as multiform or json) are accepted.

ck@mintp ~ $ curl -X POST https://my.example.com/post.php -d "firstname=Claudio" -d "lastname=Kuenzler" -d "company=Infiniroot GmbH"

In this case multiple fields/parameters (firstname, lastname and company) are submitted to an external URL. Using this "default" way of submitting data, uses the content-type application/x-www-form-urlencoded in the background. This can be verified using the --trace option (followed by another dash):

ck@mintp ~ $ curl --trace - -X POST https://my.example.com/post.php -d "firstname=Claudio" -d "lastname=Kuenzler" -d "company=Infiniroot GmbH"
[...]
=> Send header, 175 bytes (0xaf)
0000: 50 4f 53 54 20 2f 61 63 74 69 6f 6e 2f 6e 69 6e POST /post.php H
0010: 6a 61 2e 70 68 70 20 48 54 54 50 2f 31 2e 31 0d TTP/1.1..Host: m
0020: 0a 48 6f 73 74 3a 20 77 77 77 2e 61 6c 76 61 6e y.example.com..U
0040: 0a 55 73 65 72 2d 41 67 65 6e 74 3a 20 63 75 72 ser-Agent: curl/
0050: 6c 2f 37 2e 35 32 2e 31 0d 0a 41 63 63 65 70 74 /7.52.1..Accept:
0060: 3a 20 2a 2f 2a 0d 0a 43 6f 6e 74 65 6e 74 2d 4c  */*..Content-Le
0070: 65 6e 67 74 68 3a 20 31 33 31 0d 0a 43 6f 6e 74 ngth: 131..Conte
0080: 65 6e 74 2d 54 79 70 65 3a 20 61 70 70 6c 69 63 nt-Type: applica
0090: 61 74 69 6f 6e 2f 78 2d 77 77 77 2d 66 6f 72 6d tion/x-www-form-
00a0: 2d 75 72 6c 65 6e 63 6f 64 65 64 0d 0a 0d 0a    urlencoded......
=> Send data, 131 bytes (0x83)
0000: 63 6f 6d 70 61 6e 79 3d 74 65 73 74 26 66 69 72 firstname=Claudi
0010: 73 74 6e 61 6d 65 3d 43 6c 61 75 64 69 6f 26 6c o&lastname=Kuenzl
0020: 61 73 74 6e 61 6d 65 3d 4b 75 65 6e 7a 6c 65 72 er&company=Infini
0030: 26 63 6f 6d 70 61 6e 79 3d 54 65 74 20 43 6f 6d root
== Info: upload completely sent off: 131 out of 131 bytes
[...]

Note 1: -trace is available since curl ~7.51.
Note 2: The original POST data was obfuscated, hence the Content-Length does not match.

If the remote API requires the submitted data in JSON format, the HTTP POST request needs to be slightly adjusted:

ck@mintp:~$ curl -X POST -H "Content-Type: application/json" https://my.example.com/post.php -d '"firstname":"Claudio","lastname":"Kuenzler","company":"Infiniroot GmbH"'

Here the Content-Type header was set to application/json and the data was formatted into JSON format.

POSTing data with libcurl in PHP

As mentioned, curl can also be used in PHP. If you're coming from the curl command line, this might look strange at first. All curl command line options and parameters are defined by curl_setopt for a single option or curl_setopt_array for multiple options at the same time.

So a typical POST with libcurl in PHP, using the same data as in the command line example, looks like this:

// Putting all the POST data into an array
$data = array(
        "firstname" => "Claudio",
        "lastname" => "Kuenzler",
        "company" => "Infiniroot GmbH",
);

// Initialize a new curl call
$curl = curl_init();

// Put all the different curl options into an array
$opts = [
        CURLOPT_URL => 'https://my.example.com/post.php',
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CUSTOMREQUEST => 'POST',
        CURLOPT_POST => 1,
        CURLOPT_POSTFIELDS => $data,
];

// Use the options array and tell curl to use these options
curl_setopt_array($curl, $opts);

// Launch the curl request using curl_exec and save the output (from the remote URL) in $response
$response = curl_exec($curl);

// Close the curl call
curl_close($curl);

This again uses the default Content-Type application/x-www-form-urlencoded.

POSTing json data with libcurl in PHP

To submit the data in json format, the $data array first needs to be formatted into json. This can easily be done using the json_encode function. This function basically parses the array and creates a json string of it, saved as $payload. Besides this, the header Content-Type needs to be added in the $opts:

// Putting all the POST data into an array
$data = array(
        "firstname" => "Claudio",
        "lastname" => "Kuenzler",
        "company" => "Infiniroot GmbH",
);

// Re-format the data into JSON
$payload = json_encode($data);


// Initialize a new curl call
$curl = curl_init();

// Put all the different curl options into an array
$opts = [
        CURLOPT_URL => 'https://my.example.com/post.php',
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CUSTOMREQUEST => 'POST',
        CURLOPT_POST => 1,
        CURLOPT_HTTPHEADER => [ 'Content-Type: application/json' ],
        CURLOPT_POSTFIELDS => $payload,
];

// Use the options array and tell curl to use these options
curl_setopt_array($curl, $opts);

// Launch the curl request using curl_exec and save the output (from the remote URL) in $response
$response = curl_exec($curl);

// Close the curl call
curl_close($curl);

Debugging with curl_getinfo

Whether or not the code runs fine, you may want to get additional information about the executed curl request. This is where curl_getinfo comes into play. This function analyzes the curl call ($curl) and saves information about the request and server response in an array. Before closing the curl call, the information can be stored into a variable ($info):

// Putting all the POST data into an array
$data = array(
        "firstname" => "Claudio",
        "lastname" => "Kuenzler",
        "company" => "Infiniroot GmbH",
);

// Re-format the data into JSON
$payload = json_encode($data);

// Initialize a new curl call
$curl = curl_init();

// Put all the different curl options into an array
$opts = [
        CURLOPT_URL => 'https://my.example.com/post.php',
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CUSTOMREQUEST => 'POST',
        CURLOPT_POST => 1,
        CURLOPT_HTTPHEADER => [ 'Content-Type: application/json' ],
        CURLOPT_POSTFIELDS => $payload,
];

// Use the options array and tell curl to use these options
curl_setopt_array($curl, $opts);

// Launch the curl request using curl_exec and save the output (from the remote URL) in $response
$response = curl_exec($curl);

// Saving information about this executed curl call
$info = curl_getinfo($curl);


// Close the curl call
curl_close($curl);

As mentioned above, the information (return values) about this curl transmission is saved in an array. There are many return values, check out the curl_getinfo documentation for an up to date list. What definitely helps to use in every code, is to check the http_code (the http return code from the server response):

// Analyze http return code
if ( $info['http_code'] > 200 ) {
  echo "Remote API responded with a return code of $info['http_code']";
}


Add a comment

Show form to leave a comment

Comments (newest first)

No comments yet.

RSS feed

Blog Tags:

  AWS   Android   Ansible   Apache   Apple   Atlassian   BSD   Backup   Bash   Bluecoat   CMS   Chef   Cloud   Coding   Consul   Containers   CouchDB   DB   DNS   Database   Databases   Docker   ELK   Elasticsearch   Filebeat   FreeBSD   Galera   Git   GlusterFS   Grafana   Graphics   HAProxy   HTML   Hacks   Hardware   Icinga   Influx   Internet   Java   KVM   Kibana   Kodi   Kubernetes   LVM   LXC   Linux   Logstash   Mac   Macintosh   Mail   MariaDB   Minio   MongoDB   Monitoring   Multimedia   MySQL   NFS   Nagios   Network   Nginx   OSSEC   OTRS   Office   PGSQL   PHP   Perl   Personal   PostgreSQL   Postgres   PowerDNS   Proxmox   Proxy   Python   Rancher   Rant   Redis   Roundcube   SSL   Samba   Seafile   Security   Shell   SmartOS   Solaris   Surveillance   Systemd   TLS   Tomcat   Ubuntu   Unix   VMWare   VMware   Varnish   Virtualization   Windows   Wireless   Wordpress   Wyse   ZFS   Zoneminder