简体   繁体   中英

convert python request to PHP-cURL equivalent

I am sending a POST request to a URL. It works correctly in python but in php-curl, I always get a bad request error (ie my POST data is not as expected by the server)

Python code: (works correctly. 200 OK)

import httplib, urllib, json

def SendRequest(param1):
    url = "api.xyz.com"
    body = {"version": "1.0", "data":[{"param1":param1, "age":35}]}
    jsonBody = json.dumps(body)

    headers = {"Content-type": "application/json",
               "Accept": "application/json; charset=utf8"}
    conn = httplib.HTTPConnection(url)
    conn.request("POST", "/api/?client_id=xx-xx-xx", jsonBody, headers)
    response = conn.getresponse()

php-cURL code (does not work. 406 Bad request error)

function sendCurlRequest($param1)
{
    $payload = preparePayload($param1); 
    $url = "http://api.xyz.com/api/?client_id=xx-xx-xx"; 
    $jsonResponse = executePOSTRequest($url, $payload);
    $response = json_decode($jsonResponse);
}

function preparePayload($param1)
{
    $payload = array("version" = "1.0",
                     "data" => array(array("param1" => $param1,
                                           "age" => 35
                                          )
                                    ),
                    );

    $jsonPayload = json_encode($payload);
    return $jsonPayload;
}

function executePOSTRequest($url, $payload)
{
    $newlines = array("\r", "\n", " ");
    $url = str_replace($newlines, '', $url);
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt ($ch, CURLOPT_HTTPHEADERS,array('Content-Type:application/json; Accept: application/json; charset=utf8'));

    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $result = curl_exec($ch);
}

I know there is some mistake in my use of cURL. Please suggest.

Update: Use of double array in php is because server expects the JSON string (POST payload) in this format

{
"version": "1.0",
"data":
[{"param1":name, "age":35},{"param1":name,"age":60}]
}

In python, I am using list of dict; in php I think it is array of arrays only.

In a case like this, I find that it's always better to look at what goes over the wire instead of trying to puzzle out what might be wrong with the code.

My advice:

  • Create a little test server using the python BaseHTTPServer and derive a class from BaseHTTPRequestHandler that doesn't do anything but provide an override of the do_POST method

  • Your do_POST should just dump the headers and POST body it receives to file

  • Point your code samples at this little test server and then diff the files that it creates. I'm guessing that if the answer isn't immediately obvious, you'll at the very least get one or more useful clues to stomp this problem out.

I'm not sure if it causes your problem, but I do see a difference between the two: In the python code you send two header lines: Content-Type and Accept. While in the PHP code, they are a single line.

You are missing the parameter index - cURL POST fields need to be sent as a query string or as an array.

Either:

curl_setopt($ch, CURLOPT_POSTFIELDS, 'payload=' . urlencode($payload));

Or

curl_setopt($ch, CURLOPT_POSTFIELDS, array('payload' => $payload));

Replace payload with the name of the parameter expected by the API to hold the JSON string.

If the endpoint API is not expecting a parameter, then it should work - it just won't appear in the POST array in your test script. You can fetch the body of the POST contents using

$data = file_get_contents("php://input");
var_dump($data);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM