Take the 2-minute tour ×

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 = "http://mydomain.com/myrestcall";

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

$headers = array(    "Accept-Encoding" =>    "gzip",
                    "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
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!

share|improve this question
You may try to add an Accept header with application/json –  Boris Guéry Jun 18 '12 at 17:27
Thanks, tried it, but no love :( Your comment reminded me that I should point out the some similar headers specifically in the example though, so thanks :) –  Ian Jun 18 '12 at 17:42
Is the webservice you're trying to request a public or private API? You may be missing some parameters however, the response error is very generic and we may not be able to help if it is a private API. –  Boris Guéry Jun 18 '12 at 17:43
Private, unfortunately. I know that this severely limits the degree to which others can help troubleshoot this issue, but them's the breaks I'm afraid. Mostly I'm hoping someone more experienced with php or curl will spot some common pitfall that I've walked into. –  Ian Jun 18 '12 at 17:53
Do you have any other way to test your webservice? Before to take much time debugging your code which looks fairly simple and correct, be sure that the remote service is not broken. –  Boris Guéry Jun 18 '12 at 18:03

2 Answers 2

up vote 4 down vote accepted

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,


                     "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.


share|improve this answer

I think the problem is that you are passing an array as the CURLOPT_POSTFIELDS option. By passing an array, this forces the POST request to use multipart/form-data when the server is probably expecting application/x-www-form-urlencoded.

Try changing



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

See http_build_query for more information and also this answer: My cURL request confuses some servers?

share|improve this answer
Thanks for the suggestion - same response though. I'll keep this in mind moving forward though. You make a good point. –  Ian Jun 18 '12 at 18:01
Sniffing the entire request in Wireshark may be helpful so you can see the HTTP request and response. Are they expecting you to post JSON data rather than urlencoded data? –  drew010 Jun 18 '12 at 18:03
It is expecting JSON, and per my response to Boris' comment, I'm going to follow your council, Wireshark my call along with the call sent from Poster, and compare the two. –  Ian Jun 18 '12 at 18:15
In that case you may need to set CURLOPT_POSTFIELDS to json_encode($this->body) and confirm that the content-type header going out is not being overridden by curl back to anything other than application/json –  drew010 Jun 18 '12 at 18:20
Checking out what wireshark has to say on the matter - thought I had it, and made this comment, then had to edit it to remove erroneous findings... –  Ian Jun 18 '12 at 20:31

Your Answer


