user429620
user429620

Reputation:

Google Closure Compiler and multipart/form-data not working

I'm making a request to the google closure compiler API service:

   $content = file_get_contents('file.js');

   $url = 'http://closure-compiler.appspot.com/compile';
   $post = true;
   $postData = array('output_info' => 'compiled_code', 'output_format' => 'text', 'compilation_level' => 'SIMPLE_OPTIMIZATIONS', 'js_code' => urlencode($content)));

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);

    curl_setopt($ch, CURLOPT_HEADER, 1);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

    if ($post) {
        curl_setopt($ch, CURLOPT_POST, $post);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
    }

    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded; charset=UTF-8'));  

But the request is failing and I get this error message from google:

   Error(18): Unknown parameter in Http request: '------------------------------0f1f2f05fb97
   Content-Disposition: form-data; name'.
   Error(13): No output information to produce, yet compilation was requested.

I looked at the headers and this Content-Type header is being sent:

  application/x-www-form-urlencoded; charset=UTF-8; boundary=----------------------------0f1f2f05fb97

Not sure if that added boundary is normal? And how do I prevent this as google doesn't seem to like it?

Thank you, Wesley

Upvotes: 4

Views: 1686

Answers (3)

mgutt
mgutt

Reputation: 6177

1.) Don't use an array() to avoid switch to multipart/form-data:

Passing an array to CURLOPT_POSTFIELDS will encode the data as multipart/form-data, while passing a URL-encoded string will encode the data as application/x-www-form-urlencoded.

2.) Don't use http_build_query() to avoid double encoding problems (@Wesley). In addition you aren't able to use keys twice (I know this workaround, but its ugly).

Some of my error messages by using http_build_query():

JSC_PARSE_ERROR Input_0 Parse error. illegal octal literal digit 9; interpreting it as a decimal digit Parse error. syntax error ERROR - Parse error. missing ( before function parameters

3.) My proposal:

$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Expect:',
    'Content-type: application/x-www-form-urlencoded',
));
curl_setopt($ch, CURLOPT_TIMEOUT, 30); // don't set it to low! sending and response needs time
curl_setopt($ch, CURLOPT_ENCODING, ''); // automatically sets supported encodings
//curl_setopt($ch, CURLOPT_HEADER, true); // for debugging response header
//curl_setopt($ch, CURLINFO_HEADER_OUT, true); // for debugging request header
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // false would echo the answer
curl_setopt($ch, CURLOPT_POST, true);
// settings
curl_setopt($ch, CURLOPT_POSTFIELDS,
    'output_format=json'
    .'&output_info=compiled_code'
    .'&output_info=warnings'
    .'&output_info=errors'
    .'&output_info=statistics'
    .'&compilation_level=ADVANCED_OPTIMIZATIONS'
    .'&warning_level=verbose'
    //.'&output_file_name=default.js'
    //.'&code_url='
    .'&js_code=' . urlencode($js_code)
);
curl_setopt($ch, CURLOPT_URL, 'http://closure-compiler.appspot.com/compile');
$response = curl_exec($ch);
//$response = curl_getinfo($ch, CURLINFO_HEADER_OUT) . $response; // for debugging request header
print_r(json_decode($response, true));

Upvotes: 3

user562854
user562854

Reputation:

You have to use http_build_query() prior to sending POST data (array) to cURL.

string http_build_query ( mixed $query_data [, string $numeric_prefix [, string $arg_separator [, int $enc_type = PHP_QUERY_RFC1738 ]]] )

So your $postData should look like this:

$postData = http_build_query(
                                array(
                                'output_info' => 'compiled_code', 
                                'output_format' => 'text', 
                                'compilation_level' => 'SIMPLE_OPTIMIZATIONS', 
                                'js_code' => urlencode($content)
                                )
                            );

Upvotes: 5

Anodyne
Anodyne

Reputation: 1852

Looks like Google's API doesn't support multipart/form-data data. Which seems a bit lame to me...

According to the PHP documentation on curl_setopt():

Passing an array to CURLOPT_POSTFIELDS will encode the data as multipart/form-data, while passing a URL-encoded string will encode the data as application/x-www-form-urlencoded.

So it should work if you change the 4th line of your code to something like this:

$postData = 'output_info=compiled_code&output_format=text&compilation_level=SIMPLE_OPTIMIZATIONS&js_code=' . urlencode($content);

In other words, you have to do the URL encoding yourself - you apparently can't rely on cURL to take an array and encode it for you.

Upvotes: 4

Related Questions