ZF-3189: Zend_Http_Client_Adapter_Proxy::connectHandshake ignores useragent set in headers
Description
If the user-agent is specified in the headers, as opposed to via setConfig(), the default UA of Zend_Http_Client is used for CONNECT requests by the proxy adapter.
I'm not too familiar with proxy servers, but there could be issues if the CONNECT request uses one UA and the actual request uses another. It seems like setting the UA via setHeaders should overwrite the useragent config item.
Comments
Posted by Wil Sinclair (wil) on 2008-06-09T13:32:44.000+0000
Please evaluate and fix/categorize as necessary.
Posted by Ralph Schindler (ralph) on 2011-02-17T15:10:19.000+0000
Do you have any code to demonstrate this issue?
Posted by Adam Lundrigan (adamlundrigan) on 2011-06-07T02:34:34.000+0000
In tracing through the code, I noticed the following: Zend_Http_Client::request() calls Zend_Http_Client::_prepareHeaders(), which returns a numerically-indexed array of headers in 'name: value' format. That array is then passed to the adapter via an argument to it's connect() method. However, Zend_Http_Client_Adapter_Proxy::connect() treats $headers as an associative array of HeaderName=>HeaderValue pairs.
Did I miss something there, or is that actually the case? If it is, then Zend_Http_Client_Adapter_Proxy needs to be reworked to reflect that, as it uses $headers as an associative array in many places.
Posted by Adam Lundrigan (adamlundrigan) on 2011-06-07T03:06:07.000+0000
It looks to me that the culprit is here:
The config key 'useragent' always exists, as it has a default defined in Zend_Http_Client. In the connectHandshake() snippet above, the User-agent header will be set up with that default value (Zend_Http_Client) regardless of what might be set in $headers, as none of those headers are sent during the CONNECT handshake. As the original poster says, this may cause the CONNECT handshake and the subsequent request to have different UAs.
Posted by Adam Lundrigan (adamlundrigan) on 2011-10-04T15:31:23.000+0000
Test to reproduce the issue:
The first test ({{testConnectHandshakeSendsCustomUserAgentHeader}}) will pass, as setting the user agent in the client configuration works as expected. However, the second test ({{testConnectHandshakeSendsCustomUserAgentHeaderWhenSetInHeaders}}) currently fails for the reason the OP suggested: {{connectHandshake}} does not check to see if {{$headers}}} defines a user agent header.
My reproduction test required a slight modification to {{Zend_Http_Client_Adapter_Proxy}} so that it would record the request headers sent during the {{connectHandshake}} method call. Rather than change the public API of {{Zend_Http_Client_Adapter_Proxy}}, I added a protected variable to store the request, then created a test-specific adapter class ({{ZF3189_ProxyAdapter}}) to expose it.
Posted by Adam Lundrigan (adamlundrigan) on 2011-10-04T15:56:14.000+0000
Suggested fix:
Two things here: * Rejig the authorization header processing {{Zend_Http_Client_Adapter_Proxy::write}} to properly detect an existing Proxy-Authorization header (old method assumed that $headers was a header=>value associative array, which it isn't. * Update {{Zend_Http_Client_Adapter_Proxy::connectHandshake}} to pass User-Agent and Proxy-Authorization headers through to CONNECT request.
I've also added a third test to enforce that {{Zend_Http_Client_Adapter_Proxy::write}} does indeed properly detect a preexisting Proxy-Authorization header:
Thoughts?
Posted by Adam Lundrigan (adamlundrigan) on 2012-05-12T19:40:31.000+0000
I would like to have this fixed in ZF 1.12.0. Could someone with a proxy setup already in place test out this patch to ensure it works as expected?
Posted by Rob Allen (rob) on 2012-05-28T18:50:04.000+0000
Fixed in svn r24818.