Вопрос по jboss, curl, php, post – PHP cURL POST возвращает 415 - неподдерживаемый тип медиа

4

У меня есть простой PHP-скрипт, который отправляет HTTP-запрос POST через cURL и ожидает в ответ строку json (я бы хотел использовать для этого существующую библиотеку, например pecl_http / HTTPRequest, но не могу). Вызов постоянно завершается с ошибкой 415 - Unsupported Media Type. Я думаю, что я не настраиваю cURL правильно, но после долгих поисков я не могу выяснить, что я делаю неправильно. Вот некоторый код:

class URLRequest
{
    public $url;
    public $headers;
    public $params;
    public $body;
    public $expectedFormat;
    public $method;

    public function URLRequest($aUrl, array $aHeaders, array $aParams, $aFormat = "json", $isPost = false, $aBody = "+")
    {
        $this->url = $aUrl;
        $this->headers = $aHeaders;
        $this->params = $aParams;
        $this->expectedFormat = $aFormat;
        $this->method = ($isPost ? "POST" : "GET");
        $this->body = $aBody;

    }

    public function exec()
    {

        $queryStr = "?";
        foreach($this->params as $key=>$val)
            $queryStr .= $key . "=" . $val . "&";

        //trim the last '&'
        $queryStr = rtrim($queryStr, "&");

        $url = $this->url . $queryStr;

        $request = curl_init();
        curl_setopt($request, CURLOPT_URL, $url);
        curl_setopt($request, CURLOPT_HEADER, 1);
        curl_setopt($request, CURLOPT_HTTPHEADER, $this->headers);
        curl_setopt($request, CURLOPT_RETURNTRANSFER, 1);
        //curl_setopt($request, CURLOPT_SSL_VERIFYPEER, false);

        if($this->method == "POST")
        {
            curl_setopt($request, CURLOPT_POST, 1);
            curl_setopt($request, CURLOPT_POSTFIELDS, $this->body);

            //this prevents an additions code 100 from getting returned
            //found it in some forum - seems kind of hacky
            curl_setopt($request, CURLOPT_HTTPHEADER, array("Expect:"));
        }

        $response = curl_exec($request);
        curl_close($request);

        preg_match("%(?<=HTTP/[0-9]\.[0-9] )[0-9]+%", $response, $code);

        $resp = "";
        if($this->expectedFormat == "json")
        {
            //parse response
        }
        elseif($this->expectedFormat == "xml")
        {
            //parse response
        }

        return $resp;

    }
}


$url = "http://mydomain.com/myrestcall";

$query = array( "arg_1" =>      "test001",
                "arg_2" =>      "test002",
                "arg_3" =>      "test003");

$headers = array(    "Accept-Encoding" =>    "gzip",
                    "Content-Type" =>       "application/json",
                    "Accept" =>             "application/json",
                    "custom_header_1" =>    "test011",
                    "custom_header_2" =>    "test012",
                    "custom_header_3" =>    "test013");

$body = array(  "body_arg_1" =>      "test021",
                "body_arg_2" =>     array("test022", "test023"), 
                "body_arg_3" =>     "test024"); 


$request = new URLRequest($url, $headers, $query, "json", true, $body);

$response = $request->exec();

... и ответ:

HTTP/1.1 415 Unsupported Media Type
Server: Apache-Coyote/1.1
X-Powered-By: Servlet 2.5; JBoss-5.0/JBossWeb-2.1
Content-Type: text/html;charset=utf-8
Content-Length: 1047
Date: Mon, 18 Jun 2012 16:30:44 GMT

<html><head><title>JBoss Web/2.1.3.GA - Error report</title></head><body><h1>HTTP Status 415 - </h1><p><b>type</b> Status report</p><p><b>message</b> <u></u></p><p><b>description</b> <u>The server refused this request because the request entity is in a format not supported by the requested resource for the requested method ().</u></p><h3>JBoss Web/2.1.3.GA</h3></body></html>

Есть идеи или идеи?

Заранее спасибо!

Спасибо, попробовал, но без любви :( Ваш комментарий напомнил мне, что я должен указать на некоторые похожие заголовки, в частности, в примере, так что спасибо :) Ian
Веб-сервис, который вы пытаетесь запросить публичный или частный API? Возможно, вам не хватает некоторых параметров, ошибка ответа очень общая, и мы не сможем помочь, если это частный API. Boris Guéry
Частный, к сожалению. Я знаю, что это сильно ограничивает степень, в которой другие могут помочь в устранении этой проблемы, но я боюсь перерывов. В основном я надеюсь, что кто-то более опытный с php или curl обнаружит некоторую распространенную ловушку, с которой я столкнулся. Ian
У вас есть какой-нибудь другой способ протестировать ваш веб-сервис? Прежде чем уделять много времени отладке вашего кода, который выглядит довольно простым и корректным, убедитесь, что удаленный сервис не сломан. Boris Guéry
Вы можете попробовать добавитьAccept заголовок сapplication/json Boris Guéry

Ваш Ответ

2   ответа
12

Отправка ассоциативного массива заголовков НЕ РАБОТАЕТ с cURL. Есть несколько форумов, которые показывают примеры использования ассоциативного массива для заголовков. Не делай этого!

correct способ (который также разбросан по сетям, но который я слишком плотный, чтобы заметить) состоит в том, чтобы создать пары ключ / значение заголовка в виде строк и передать стандартный массив этих строк при установке параметра CURLOPT_HTTPHEADER.

Итак, в итоге,

WRONG:

$headers = array(    "Accept-Encoding" =>    "gzip",
                     "Content-Type" =>       "application/json",
                     "custom_header_1" =>    "test011",
                     "custom_header_2" =>    "test012",
                     "custom_header_3" =>    "test013");

RIGHT:

$headers = array(    "Accept-Encoding: gzip",
                     "Content-Type: application/json",
                     "custom_header_1: test011",
                     "custom_header_2: test012",
                     "custom_header_3: test013");

Я надеюсь, что это пригодится некоторым другим благородным глупцам в будущем, прежде чем они потратят столько же времени на отладку, как и я.

Если бы мне пришлось угадывать, я бы предположил, что это же правило применимо и к парам ключ / значение тела POST, поэтому комментарий @ drew010 об использованииhttp_build_query() или жеjson_encode() Стригизация вашего сообщения также является отличной идеей.

Спасибо всем за ваши очень полезные комментарии, а также за ваше время и внимание. В конце концов, параллельное сравнение http-трафика (перехваченного через Wireshark) выявило проблему.

Спасибо!

Черт! Я пробовал ВСЕ и буквально нашел десятки различных страниц и учебных пособий, показывающих, как устанавливать заголовки со значением key = & gt ;, и это просто не работало! СПАСИБО, ЯН!
7

CURLOPT_POSTFIELDS вариант. Передав массив, это заставляетPOST запрос на использованиеmultipart/form-data когда сервер, вероятно, ожидаетapplication/x-www-form-urlencoded.

Попробуйте изменить

curl_setopt($request, CURLOPT_POSTFIELDS, $this->body);

в

curl_setopt($request, CURLOPT_POSTFIELDS, http_build_query($this->body));

Увидетьhttp_build_query для получения дополнительной информации, а также этот ответ:Мой запрос cURL смущает некоторые серверы?

В этом случае вам может понадобиться установитьCURLOPT_POSTFIELDS вjson_encode($this->body) и подтвердите, что выходящий заголовок типа контента не переопределяется с помощью curl обратно на что-либо кромеapplication/json
Спасибо за предложение - тот же ответ, хотя. Я буду иметь в виду, что буду двигаться вперед. Ты делаешь доброе дело. Ian
Проверяя, что Wireshark должен сказать по этому вопросу - подумал, что у меня есть, и сделал этот комментарий, а затем пришлось отредактировать его, чтобы удалить ошибочные результаты ... Ian
Может быть полезен анализ всего запроса в Wireshark, чтобы вы могли видеть HTTP-запрос и ответ. Они ожидают, что вы опубликуете данные в формате JSON, а не данные в формате Urlencoded?
Он ожидает JSON и, согласно моему ответу Борису, прокомментируйте, я собираюсь последовать вашему совету, Wireshark мой звонок вместе с вызовом, отправленным с постера, и сравнить их. Ian

Похожие вопросы