I am using the Jersey Client 2.0 library (with Apache HttpClient v4.2.5 transport connector) to consume a RESTful web service. My application must support connections via a proxy server with any of Basic, Digest or NTLM authentication. I have added support for all these types of proxy authentication and essentially everything is working correctly.
This is how I added support for Basic and Digest proxy authentication:
ClientConfig config = new ClientConfig();
config.property(ApacheClientProperties.PROXY_URI, "http://www.proxy.com:5678");
config.property(ApacheClientProperties.PROXY_USERNAME, "proxy_user");
config.property(ApacheClientProperties.PROXY_PASSWORD, "proxy_password");
ApacheConnector connector = new ApacheConnector(config);
config.connector(connector);
Client client = ClientBuilder.newClient(config);
In addition, the RESTful web service I am connecting to also requires Basic authentication itself, which I handle using the following:
client.register( new HttpBasicAuthFilter("user", "password") );
However, my application is not behaving exactly as I want: it seems that every individual HTTP request that I make is resulting in a 407 authentication challenge response from the proxy server. This is an issue for two reasons:
If I make a
POST
orPUT
request (having already successfully authenticated with the proxy server in the previous request) with the entity body supplied by anInputStream
, it is deemed to be a "non-repeatable" request so when the 407 challenge is received I get the following exception:org.apache.http.client.NonRepeatableRequestException: Cannot retry request with a non-repeatable request entity.
I could work around this issue by buffering the entity body data from the
InputStream
into a string or byte array so that the request is repeatable in case a 407 challenge is received, but this is inefficient and doesn't address issue 2.- Having to duplicate every request, first to trigger the 407 challenge and then to repeat with the necessary additional HTTP headers in place for proxy authentication, is very inefficient. Some of my client operations involve numerous HTTP requests to the RESTful web service, so this additional traffic and latency is unfortunate.
My expectation is that once the Jersey client has successfully authenticated with the proxy server the first time, all subsequent requests made using the same Client
instance would automatically include the necessary Proxy-Authorization
header to prevent any further 407 challenges. This seems to be the standard approach for HTTP 1.1 as per this link:
A proxy server sends the client a Proxy-Authenticate header, containing a challenge, in a 407 (Proxy Authentication Required) response. The client then repeats the initial request, but adds a Proxy-Authorization header that contains credentials appropriate to the challenge. After successful proxy authentication, a client typically sends the same Proxy-Authorization header to the proxy with each subsequent request, rather than wait to be challenged again.
So my question is what configuration settings do I need to apply to either the Jersey Client or the underlying Apache HttpClient transport layer to enable this behaviour? I have seen various other posts recommending the manual addition of the Proxy-Authorization
header, but I would rather avoid this workaround if possible. I am also ideally looking for a solution that will work with all three types of proxy authentication I'm using (Basic, Digest and NTLM).
If it is not possible to prevent all these extra 407 challenges, I would also like recommendations for the best approach when POSTing or PUTing data from local files in a "repeatable" way to prevent issues following a 407 proxy authentication challenge.