4

I have some problem(s) with PHP cURL. I tried to get data from the API using PHP cURL. This is my cURL code in PHP :

<?php

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => "https://www.example.com/dos/AW/API",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => "{\"Filter\" : {\"IsActive\" : \"True\",\"OutputSelector\" : \"Name\"}}",
  CURLOPT_HTTPHEADER => array(
    "API_ACTION: GetItem",
    "API_KEY: MHlIARzQqxVpOg2dUxH4q9w7bx3pOL6K",
    "Accept: application/json"
  ),
));

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}

?>

With that code I can get a response but the response contains some errors. I also tried using POSTMAN to check, and the API works fine as I got a successful response with the same data. My question is: "Is there anything wrong with my cURL code that would explain why I got an error when I used cURL and I got successful response in POSTMAN "?

I would appreciate if someone could help me with this. Thank you very much.

mrj
  • 849
  • 2
  • 8
  • 18
Antonio
  • 755
  • 4
  • 14
  • 35

2 Answers2

4

given that you aren't showing us the successful postman request, we can't know for sure what errors you make, that said, you are making a couple of obvious mistakes here.

first off, when debugging curl code, use CURLOPT_VERBOSE , it gies you a lot of useful information when debugging your curl requests (and if you did this, you would probably notice how the Postman requests's content-type is completely different from curl's content-type http headers - more on this soon)

second, when you want a POST request, don't use CURLOPT_CUSTOMREQUEST, use CURLOPT_POST.

third, when passing a string to CURLOPT_POSTFIELDS, the content-type implicitly becomes Content-Type: application/x-www-urlencoded, unless you override it. and you are obviously NOT sending x-www-urlencoded data, but JSON-encoded data, so your content-type is all wrong, its supposed to be Content-type: application/json

fourth, you can hardcode the json if you want, but the code looks much prettier if you json_encode it

fifth, don't use setopt / setopt_array without checking the return type.

fixing all that, you'll end up with something like:

function ecurl_setopt_array($ch, array $options) {
    if (! curl_setopt_array ( $ch, $options )) {
        throw new \RuntimeException ( 'curl_setopt_array failed. ' . curl_errno ( $ch ) . ': ' . curl_error ( $ch ) );
    }
}

$curl = curl_init ();

ecurl_setopt_array ( $curl, array (
        CURLOPT_URL => "https://www.example.com/dos/AW/API",
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_ENCODING => "",
        CURLOPT_MAXREDIRS => 10,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
        CURLOPT_VERBOSE => true,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => json_encode ( array (
                'Filter' => array (
                        'IsActive' => 'True',
                        'OutputSelector' => 'Name' 
                ) 
        ) ),
        CURLOPT_HTTPHEADER => array (
                "API_ACTION: GetItem",
                "API_KEY: MHlIARzQqxVpOg2dUxH4q9w7bx3pOL6K",
                "Accept: application/json",
                'Content-Type: application/json' 
        ) 
) );

$response = curl_exec ( $curl );
$err = curl_error ( $curl );

curl_close ( $curl );

if ($err) {
    echo "cURL Error #:" . $err;
} else {
    echo $response;
}

Edit: fixed the json data, when i wrote it, i didn't see that isActive is not an actual boolean, but the string literal True - i mistakenly encoded it as a json boolean true instead, sorry, fixed. (although i suspect it's supposed to be a boolean anyway, and that your original code just encodes it wrong, perhaps you should double check isActive's type in the api docs, assuming there is one)

hanshenrik
  • 19,904
  • 4
  • 43
  • 89
  • I got what is wrong. Replace `ecurl_setopt_array` with `curl_setopt_array` and it will works. – Antonio Jul 22 '17 at 02:19
  • Is there a practical reason to use `CURLOPT_POST` instead of `CURLOPT_CUSTOMREQUEST` for POST or is it purely semantic? I've used the latter quite a bit without issue. – Magnus Bull Nov 16 '20 at 10:13
  • @MagnusBull yes there is. quoting [the official libcurl documentation](https://curl.se/libcurl/c/CURLOPT_CUSTOMREQUEST.html): ```Many people have wrongly used this option to replace the entire request with their own, including multiple headers and POST contents. While that might work in many cases, it will cause libcurl to send invalid requests and it could possibly confuse the remote server badly. Use CURLOPT_POST and CURLOPT_POSTFIELDS to set POST data. Use CURLOPT_HTTPHEADER to replace or extend the set of headers sent by libcurl. Use CURLOPT_HTTP_VERSION to change HTTP version.```, hmmm – hanshenrik Nov 16 '20 at 10:27
  • 1
    @MagnusBull what i have noticed personally is that CURLOPT_CUSTOMREQUEST overrides everything else, and it's sticky; when you use CUSTOMREQUEST, `CURLOPT_HTTPGET` and `CURLOPT_PUT` and `CURLOPT_POST` no longer work properly, as CUSTOMREQUEST overrides all of them.. anyway the official libcurl documentation say "dont use CUSTOMREQUEST for POST requests, it could cause curl to send a malformed request", that should be reason enough. – hanshenrik Nov 16 '20 at 10:30
1

@Antonio, Response you are getting is from the other end, might be you are missing something which restrict the processing of query at other end. try to print http_code, or use curl_getinfo to get complete information.

in case of response code is 200, then you may ask from another end to validate the request.

PS: not able to comment because of repo restrictions.

ggupta
  • 675
  • 1
  • 10
  • 27
  • use the following line in your code below the line of response $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE); – ggupta Jul 21 '17 at 10:38
  • use `CURLOPT_VERBOSE` - it gives more information than all of curl_getinfo 's options combined. – hanshenrik Jul 21 '17 at 10:59