Asked  7 Months ago    Answers:  5   Viewed   203 times

I've got a simple PHP script that sends an HTTP POST request via cURL, and expects a json string in response (would have loved to use an existing library like pecl_http/HTTPRequest for this, but can't). The call consistently fails with a 415 error - Unsupported Media Type. I think I'm not configuring cURL correctly, but after much searching, I can't find out what I'm doing wrong. Here's some code:

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

        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 = "";

$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();

...and the response:

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>

Any insights or ideas?

Thanks in advance!



Problem solved! Here's the issue:

Sending an associative-array of headers DOES NOT WORK with cURL. There are several forums scattered around that show examples using an associative array for headers. DON'T DO IT!

The correct way (which is also scattered around the internets, but that I'm too dense to have noticed) is to construct your header key/value pairs as strings, and pass a standard array of these strings when setting the CURLOPT_HTTPHEADER option.

So in summary,


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


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

I hope this comes in handy to some other noble doofus down the road before they waste as much time debugging as I did.

If I had to guess, I would assume that the same rule applies to the POST body key/value pairs as well, which is why @drew010 's comment about using http_build_query() or json_encode() to stringify your message body is a great idea as well.

Thanks to everyone for your very useful comments, and for you time and consideration. In the end, a side by side comparison of the http traffic (captured via Wireshark) revealed the issue.


Wednesday, March 31, 2021
answered 7 Months ago


$data = array('username'=>'dog','password'=>'tall');
$data_json = json_encode($data);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json','Content-Length: ' . strlen($data_json)));
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_POSTFIELDS,$data_json);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response  = curl_exec($ch);


$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,$data_json);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response  = curl_exec($ch);

GET See @Dan H answer


$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POSTFIELDS,$data_json);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response  = curl_exec($ch);
Wednesday, March 31, 2021
answered 7 Months ago


curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");

And one more thhing, you need to add

curl_setopt($curl, CURLOPT_POSTREDIR, 3);

3 means follow redirect with the same type of request both for 301 and 302 redirects.

By doing this, second request will be as POST request as well. Note that, CURLOPT_POSTREDIR implemented in PHP 5.3.2 here

Wednesday, March 31, 2021
answered 7 Months ago

I managed out how to make it works. Tell me in case I am wrong. I used only one way to serialize/deserialize: I removed all annotations regarding this (@JSONSerialize and @JSONDeserialize) and registered Serializers and Deserializers in CustomObjectMapper class. I didn't find an article explaining this behaviour but I resolved in this way. Hope it's useful.

Tuesday, June 1, 2021
answered 5 Months ago

The Jersey distribution doesn't come with JSON/POJO support out the box. You need to add the dependencies/jars.

Add all these

  • jersey-media-json-jackson-2.17
  • jackson-jaxrs-json-provider-2.3.2
  • jackson-core-2.3.2
  • jackson-databind-2.3.2
  • jackson-annotations-2.3.2
  • jackson-jaxrs-base-2.3.2
  • jackson-module-jaxb-annotations-2.3.2
  • jersey-entity-filtering-2.17

With Maven, below will pull all the above in


For any future readers not using Jersey 2.17 (and using jars directly instead of Maven), you can go here to find the Jersey version you are using, and see what transitive dependency versions you need. The current version of this Jersey dependency uses Jackson 2.3.2. That's the main thing you need to look out for.

Friday, June 4, 2021
answered 5 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :