Reputation:
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
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
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
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