Solved

API call works in browser, fails with php curl

Posted on 2014-04-07
9
573 Views
Last Modified: 2016-05-21
I'm having trouble making an API call with php and curl. If I enter the post url with query string data directly into a browser, I receive a response with the results I'm looking for, but I cannot get the correct response using curl.

Here is an example of the url that gives me the results I'm looking for:
'http://mydomain.com/api.svc/addJsonOrder?Customer={"FirstName":"Test","LastName":"Customer"}&CustomerShipAddress={"Address1":"123 Some St","City":"New City","State":"NY","Zipcode":"10012"}&Order={"PaymentTypeName":"Visa"}&OrderLineItem=[{"SKU":"R1827-1286-8","Quantity":"1","Price":"459.00"}]&UserCredentials={"UserName":"username","Password":"password"}'

Open in new window


And here's the request via curl that fails:
    
    $url = "http://mydomain.com/api.svc/addJsonOrder";
    $data_string = 'Customer={"FirstName":"Test","LastName":"Customer"}&CustomerShipAddress={"Address1":"123 Some St","City":"New City","State":"NY","Zipcode":"10012"}&Order={"PaymentTypeName":"Visa"}&OrderLineItem=[{"SKU":"R1827-1286-8","Quantity":"1","Price":"459.00"}]&UserCredentials={"UserName":"username","Password":"password"}';
    
    $headers = array(
      "Accept: application/json",
      "Content-type: application/json",
      "Content-length: " . strlen($data_string),
      "Connection: close"
    );
    
    $ch = curl_init();
    $f = fopen('request.log', 'w');

    curl_setopt_array($ch, array(
      CURLOPT_URL             => $url,
      CURLOPT_HTTPHEADER      => $headers,
      CURLOPT_POST            => 1,
      CURLOPT_CUSTOMREQUEST   => 'POST',
      CURLOPT_POSTFIELDS      => $data_string,

      CURLOPT_RETURNTRANSFER  => 1,
      CURLOPT_FOLLOWLOCATION  => 1,
      CURLOPT_VERBOSE         => 1,
      CURLOPT_STDERR          => $f
    ));

    $return = curl_exec($ch);
    fclose($f);
    curl_close($ch);

Open in new window


Here's the error that gets spit out to my log file…
* About to connect() to mydomain.com port 80 (#0)
* connected
* Connected to mydomain.com (xx.xxx.xx.xx) port 80 (#0)
> POST /api.svc/addJsonOrder HTTP/1.1
Host: mydomain.com
Accept: application/json
Content-type: application/json
Content-length: 905
Connection: close

* upload completely sent off: 905 out of 905 bytes
< HTTP/1.1 405 Method Not Allowed
< Cache-Control: no-cache
< Pragma: no-cache
< Allow: GET
< Content-Length: 1565
< Content-Type: text/html; charset=UTF-8
< Expires: -1
< Server: Microsoft-IIS/7.5
< X-AspNet-Version: 4.0.30319
< Set-Cookie: lang=1; path=/
< X-Powered-By: ASP.NET
< Date: Tue, 08 Apr 2014 02:37:55 GMT
< Connection: close
< 
* Closing connection #0

Open in new window


I'm probably way off here, but in the 405 response, it states "Allow: GET" which I'm assuming means that it will only accept a GET request. I've tried this also with no success.

Any code examples would be great, curl is making my brain bleed.
0
Comment
Question by:matthewamundson
  • 3
  • 2
  • 2
  • +1
9 Comments
 
LVL 34

Expert Comment

by:Dan Craciun
ID: 39985173
What is the error when you use GET?
0
 
LVL 82

Accepted Solution

by:
Dave Baldwin earned 334 total points
ID: 39985364
You need to get rid of these fields, they are for POST, not GET.
     CURLOPT_POST            => 1,
      CURLOPT_CUSTOMREQUEST   => 'POST',
      CURLOPT_POSTFIELDS      => $data_string,

Open in new window

From http://us3.php.net/manual/en/function.curl-setopt.php
CURLOPT_HTTPGET       TRUE to reset the HTTP request method to GET. Since GET is the default, this is only necessary if the request method has been changed.
And finally, just use the same URL with the query string that you used in your browser.  If you are passing variable data then you might want to urlencode the data (not the names) and concatenate it to the URL querystring.
0
 
LVL 82

Assisted Solution

by:Dave Baldwin
Dave Baldwin earned 334 total points
ID: 39985390
Here are two simple files that demonstrate the simplicity of a basic GET with curl.

The curl file from Example #1 on http://us3.php.net/manual/en/function.curl-exec.php    You need to put in your own server address to test this.  You could probably use the URL from your browser in this code and see the response on your screen.
<?php
// create a new cURL resource
$ch = curl_init();

// set URL and other appropriate options
curl_setopt($ch, CURLOPT_URL, "http://10.202.46.40/dibtest/PHPechonames.php?fname=Fred&lname=Flintstone");
curl_setopt($ch, CURLOPT_HEADER, 0);

// grab URL and pass it to the browser
curl_exec($ch);

// close cURL resource, and free up system resources
curl_close($ch);
?>

Open in new window

The response file.
<?php
if (!isset($_GET['fname'])){$fname = "";} else {$fname = $_GET['fname'];}
if (!isset($_GET['lname'])){$lname = "";} else {$lname = $_GET['lname'];}
echo "Your first name is $fname and your last name is $lname.";
?>

Open in new window

0
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 39985597
I'm with DaveBaldwin here.  This is an important message (emphasis added):

HTTP/1.1 405 Method Not Allowed

Method is a term of art in HTTP client/server programming.  In almost all cases, the method is either GET or POST.  Other methods are defined but are rarely used.  GET requests are information-only and idempotent.  POST requests must be used if the request can change the state of the data model.  A GET request is anything you can type into the address bar of a browser, including request arguments to the right of the ? at the end of the URL.

In PHP, you can find the request arguments in $_GET and $_POST.  There must be a similar distinction in ASP.NET.

Here is my teaching example showing how to make a GET request.  Note that the term POST is nowhere in sight!

<?php // /demo/curl_get_example.php
error_reporting(E_ALL);


// DEMONSTRATE THE BASICS OF CURL
// SOMETHING LIKE demo/curl_get_example.php?url=http://twitter.com


// YOU COULD HAVE SOMETHING LIKE THIS
$url = isset($_GET["url"]) ? $_GET["url"] : 'http://twitter.com';

// BUT SINCE IT IS ON MY SERVER, I HAVE HARD-CODED THIS
$url = 'https://twitter.com/RayPaseur';

// TRY THE REMOTE WEB SERVICE
$htm = my_curl($url);

// SHOW THE WORK PRODUCT OR BARK OUT ERROR MESSAGES
echo "<pre>";
echo PHP_EOL . '<strong>' . $url . '</strong>' . PHP_EOL;
echo PHP_EOL . htmlentities($htm);
echo PHP_EOL;


// A FUNCTION TO RUN A CURL-GET CLIENT CALL TO A FOREIGN SERVER
function my_curl
( $url
, $timeout=5
, $error_report=TRUE
)
{
    $curl = curl_init();

    // HEADERS AND OPTIONS APPEAR TO BE A FIREFOX BROWSER REFERRED BY GOOGLE
    $header[] = "Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5";
    $header[] = "Cache-Control: max-age=0";
    $header[] = "Connection: keep-alive";
    $header[] = "Keep-Alive: 300";
    $header[] = "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7";
    $header[] = "Accept-Language: en-us,en;q=0.5";
    $header[] = "Pragma: "; // BROWSERS USUALLY LEAVE THIS BLANK

    // SET THE CURL OPTIONS - SEE http://php.net/manual/en/function.curl-setopt.php
    curl_setopt( $curl, CURLOPT_URL,            $url  );
    curl_setopt( $curl, CURLOPT_USERAGENT,      'Mozilla/5.0 (Windows NT 6.1; rv:22.0) Gecko/20100101 Firefox/22.0'  );
    curl_setopt( $curl, CURLOPT_HTTPHEADER,     $header  );
    curl_setopt( $curl, CURLOPT_REFERER,        'http://www.google.com'  );
    curl_setopt( $curl, CURLOPT_ENCODING,       'gzip,deflate'  );
    curl_setopt( $curl, CURLOPT_AUTOREFERER,    TRUE  );
    curl_setopt( $curl, CURLOPT_RETURNTRANSFER, TRUE  );
    curl_setopt( $curl, CURLOPT_FOLLOWLOCATION, TRUE  );
    curl_setopt( $curl, CURLOPT_TIMEOUT,        $timeout  );
    curl_setopt( $curl, CURLOPT_VERBOSE,        TRUE   );

    // IF USING SSL, THESE MAY BE IMPORTANT
    curl_setopt( $curl, CURLOPT_SSL_VERIFYHOST, FALSE  );
    curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER, FALSE  );
    curl_setopt( $curl, CURLOPT_SSLVERSION,     3      );

    // RUN THE CURL REQUEST AND GET THE RESULTS
    $htm = curl_exec($curl);

    // ON FAILURE HANDLE ERROR MESSAGE
    if ($htm === FALSE)
    {
        if ($error_report)
        {
            $err = curl_errno($curl);
            $inf = curl_getinfo($curl);
            echo "CURL FAIL: $url TIMEOUT=$timeout, CURL_ERRNO=$err";
            var_dump($inf);
        }
        curl_close($curl);
        return FALSE;
    }

    // ON SUCCESS RETURN XML / HTML STRING
    curl_close($curl);
    return $htm;
}

Open in new window

0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 

Author Comment

by:matthewamundson
ID: 39986093
Thanks all!

While it seems that GET is the correct method here, using the most basic curl command from Dave Baldwin is returning "HTTP Error 400. The request is badly formed."

I assume this means there's an error in my request url, but I'm confused because it works just fine in a browser. Here's the actual url, and notice the json array. I've tried urlencoding it as well, with no luck.

http://mydomain.com/api.svc/addJsonOrder?Customer={"FirstName":"Matthew","LastName":"Amundson","Email":"matthew@test.com"}&CustomerShipAddress={"Email":"matthew@test.com","Address1":"123 Some St","City":"New York","State":"NY","Zipcode":"10012"}&Order={"PaymentTypeName":"Visa","ShippingTypeName":"flatrate_flatrate","TotalShipping":"5.00","TotalHandling":"0.00","ProductTotalPrice":"459.00","ThirdPartyOrderNumber":"100000024","TotalCreditCardCharge":"459.00"}&OrderLineItem=[{"SKU":"R1827-1286-8","Quantity":"1","Price":"459.00"}]&UserCredentials={"UserName":"username","Password":"password"}

Open in new window


Is there another type of encoding that needs to be done before sending with GET?
0
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 39986194
What is the actual URL?  It's not mydomain.com, right?
0
 
LVL 108

Assisted Solution

by:Ray Paseur
Ray Paseur earned 166 total points
ID: 39986229
Here is what I can discern about the request variables.  They look OK, but we would need to see the API documentation to learn more.  You may need to urlencode() the values if you're sending with cURL.

http://iconoun.com/demo/temp_matthew.php?Customer={"FirstName":"Matthew","LastName":"Amundson","Email":"matthew@test.com"}&CustomerShipAddress={"Email":"matthew@test.com","Address1":"123 Some St","City":"New York","State":"NY","Zipcode":"10012"}&Order={"PaymentTypeName":"Visa","ShippingTypeName":"flatrate_flatrate","TotalShipping":"5.00","TotalHandling":"0.00","ProductTotalPrice":"459.00","ThirdPartyOrderNumber":"100000024","TotalCreditCardCharge":"459.00"}&OrderLineItem=[{"SKU":"R1827-1286-8","Quantity":"1","Price":"459.00"}]&UserCredentials={"UserName":"username","Password":"password"}

<?php // demo/temp_matthew.php
error_reporting(E_ALL);
echo '<pre>';

// VISUALIZE THE REQUEST VARIABLES
echo '<pre>';
print_r($_GET);

foreach ($_GET as $key => $jso)
{
    echo PHP_EOL . $key;
    $obj = json_decode($jso);
    var_dump($obj);
}

Open in new window

0
 

Author Comment

by:matthewamundson
ID: 39994836
Thanks for the suggestions! Tried all solutions but starting to think there's an issue with the API.

Contacted the developer and will comment again if there's any light shed.
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Importing and exporting data Magento 1.x ? 4 37
Wordpress type image upload 10 29
html input clean up 3 32
Creating a slider 12 34
Generating table dynamically is the most common issue faced by php developers.... So it seems there is a need of an article that explains the basic concept of generating tables dynamically. It just requires a basic knowledge of html and little maths…
Deprecated and Headed for the Dustbin By now, you have probably heard that some PHP features, while convenient, can also cause PHP security problems.  This article discusses one of those, called register_globals.  It is a thing you do not want.  …
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now