It seems PHP's built-in cURL module changes the header fields before sending them.
I developed a small class to communicate with an encoder device trough HTTP requests, using cURL to do the task. The code works fine under Windows, however, when I run it under Debian, the device responds with an HTTP 406 error.
The error code indicates that the server cannot respond in the requested format. (More info)
This is strange, since the response type is determined by the extension of the URL (and the possible modes are xml and json), and I didn't set explicitly the Accept
parameter in the header.
Using the CURLOPT_VERBOSE
parameter, it dumps the following data:
* Hostname was NOT found in DNS cache
* Trying 172.19.0.9...
* Connected to 172.19.0.9 (172.19.0.9) port 1080 (#0)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* Server certificate:
* subject: C=US; ST=Illinois; L=Lake Forest; O=Haivision Network Video, Inc.; OU=PRODUCT DEVELOPMENT; CN=localhost.localdomai n; emailAddress=support@haivision.com
* start date: 2016-01-22 14:40:48 GMT
* expire date: 2026-01-19 14:40:48 GMT
* issuer: C=US; ST=Illinois; L=Lake Forest; O=Haivision Network Video, Inc.; OU=PRODUCT DEVELOPMENT; CN=localhost.localdomain ; emailAddress=support@haivision.com
* SSL certificate verify result: self signed certificate (18), continuing anyway.
> POST /ecs/auth.xml HTTP/1.1
Host: 172.19.0.9:1080
Accept: */*
Content-Length: 86
Content-Type: application/x-www-form-urlencoded
* upload completely sent off: 86 out of 86 bytes
< HTTP/1.1 406 Not Acceptable
* Server nginx is not blacklisted
< Server: nginx
< Date: Fri, 01 Apr 2016 08:45:30 GMT
< Content-Type: application/xml
< Content-Length: 135
< Connection: keep-alive
<
* Connection #0 to host 172.19.0.9 left intact
It looks like the Content-Type: application/xml
changed to application/x-www-form-urlencoded
, and I think this is the main reason why the request fails so miserably.
The array being passed to the curl_setopts()
function looks like this:
array(11) {
[19913]=>
bool(true)
[64]=>
bool(false)
[52]=>
bool(false)
[68]=>
int(10)
[10023]=>
array(5) {
["Authorization"]=>
string(10) "Basic ==Og"
["Cache-Control"]=>
string(8) "no-cache"
["Content-Type"]=>
string(15) "application/xml"
["Connection"]=>
string(10) "keep-alive"
["Content-Length"]=>
int(86)
}
[20079]=>
array(2) {
[0]=>
object(Pest)#43 (6) {
["curl_opts"]=>
array(9) {
[19913]=>
bool(true)
[64]=>
bool(false)
[52]=>
bool(false)
[68]=>
int(10)
[10023]=>
array(0) {
}
[20079]=>
*RECURSION*
[81]=>
int(0)
[84]=>
int(2)
[41]=>
bool(true)
}
["base_url"]=>
string(23) "https://172.19.0.9:1080"
["last_response"]=>
NULL
["last_request"]=>
NULL
["last_headers"]=>
NULL
["throw_exceptions"]=>
bool(true)
}
[1]=>
string(13) "handle_header"
}
[81]=>
int(0)
[84]=>
int(2)
[41]=>
bool(true)
[10036]=>
string(4) "POST"
[10015]=>
string(86) "<?xml version="1.0" encoding="UTF-8"?>
<user username="#########" password="########"/>
"
As you can see, there's no Accept
tag, and the content type is set to application/xml
.
So here's my question: why does curl changing the request's header? If the roots of the problem are something else, then what's the reason it works on Win10 and not on Debian Jessie?
Update (16. 04. 04.):
Fun thing, that the same version of cURL library doesn't work in PHP, but it does in cli:
curl -X POST -H "Authorization: Basic aGFpYWRtaW46bWFuYWdlcg==" -H "Content-Type: application/xml" -H "Cache-Control: no-cache" -H "Postman-Token: 760f1aac-619f-4b64-ec06-0146554fcecf" -d '<?xml version="1.0"?><user username="########" password="#######" />' "https://172.19.0.9:1080/ecs/auth.xml"
<?xml version="1.0"?>
<sessionid value="fd7b8fd0-ac5e-4f72-a01c-142082de24f1"/>
CURL version on the linux box is 7.26.0 (x86_64-pc-linux-gnu) libcurl/7.26.0.
Thanks in advance, and sorry for the wall of text.