2010-10-30 6 views
0

Я отправляю запрос POST по URL-адресу. Он корректно работает в Python, но в PHP-завиток, я всегда получаю плохую ошибку запроса (то есть мои данные POST не как ожидалось сервером)конвертировать запрос python в эквивалент PHP-cURL

Python код: (. Работает правильно 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 код (не работает. 406 Bad ошибки запроса)

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); 
} 

Я знаю, что есть какая-то ошибка в моем использовании завитка. Пожалуйста, предложите.

Update: Использование двойного массива в PHP потому, что сервер ожидает строку JSON (POST полезной нагрузки) в этом формате

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

В Python, я использую список Словаре; В php я думаю, что это только массив массивов.

+0

Я уверен, что ваша проблема в том, что исходный код Python посылает чистый JSON тело, и PHP версии размещая различные значения как поля POST. Я не знаю, как отправить чистое тело JSON, но я уверен, что ответ находится здесь, на SO –

+0

Pekka, thx для вашего комментария, но я думаю, что в обоих случаях я отправляю строку JSON как данные POST. Вы имеете в виду, что в php моя строка JSON разбивается на части и каждое поле отправляется как поля формы? это не может быть так. –

ответ

1

В таком случае я считаю, что всегда лучше смотреть на то, что происходит над проводом, вместо того, чтобы пытаться выяснить, что может быть неправильным с кодом.

Мой совет:

  • Создать маленький сервер тест с помощью питона BaseHTTPServer и выводим класс от BaseHTTPRequestHandler, что ничего не сделать, но обеспечить переопределение метода do_POST

  • Ваш do_POST должен просто сбрасывать заголовки и тело POST получает файл

  • Направьте свои образцы кода на этот небольшой тестовый сервер, а затем удалите файлы , которые он создает. Я предполагаю, что , что если ответ не сразу очевидно, вы, по крайней мере, получите один или несколько полезных подсказок для топания этой проблемы.

+0

Спасибо за звуковой совет. Это также будет иметь большую помощь в будущих проблемах. Наконец, я сделал POST на локальный сервер через php и python и сравнил различия в заголовках и данных. Я делал некоторые ошибки при использовании завитка. Благодарю. –

+0

Отлично! Рад быть в состоянии помочь. – bgporter

1

Я не уверен, если это вызывает проблему, но я вижу разницу между ними: В коде питона вы отправляете две строки заголовка: Content-Type и Accept. Хотя в PHP-коде они представляют собой одну строку.

+0

Нет, это не вызывает проблемы. Я довольно долго боролся с завитом. Я попытался отправить Content-Type и Accept как две отдельные строки. Нет разницы. –

+1

Хорошо, вы также знаете, что параметр должен быть назван: CURLOPT_HTTPHEADER без S в конце? Итак: curl_setopt ($ ch, CURLOPT_HTTPHEADER, array ('Content-Type: application/json;', 'Accept: application/json; charset = utf8')); – Michielvv

+0

Эй, Михельвв, приятно поймать. Я не заметил дополнительных «S». Когда я сделал POST на локальный сервер, только тогда я увидел его в журнале ошибок apache. Благодарю. :-) Кроме того, как вы сказали, Content-Type и Accept должны быть разными элементами в массиве. Слияние их как одной строки НЕПРАВИЛЬНО. Благодарю. –

1

Вам не хватает указателя параметров - поля cURL POST должны быть отправлены как строка запроса или как массив.

Либо:

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

Или

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

Заменить payload с именем параметра, ожидаемого API для хранения строки JSON.

Если API конечной точки не ожидает параметра, тогда он должен работать - он просто не появится в массиве POST в тестовом скрипте.Вы можете получить тело содержимого POST с помощью

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

да, у меня есть ваше мнение. Но в python я не использую какой-либо параметр для хранения строки JSON. Кроме того, в документах API не упоминается такой параметр. Все, что он упоминает, это «форматировать запрос как строку JSON и передавать его как данные POST в заданный URL». Это ограничение cURL? –

+0

В этом случае он должен был работать так, как вы его уже писали. Вы пробовали его с помощью API или просто с вашим тестовым сценарием? Я добавил вам способ протестировать прямой контент POST с массивом $ _POST –

+0

да, Эран. Благодарю. Я следил за советом bgporter, чтобы опубликовать его на локальном сервере через php и python и проверить разницу между ними. Вот как я попал в пустую проблему _POST. http://stackoverflow.com/questions/4060345/post-is-empty-in-php –

Смежные вопросы