dev@jersey.java.net

Patch: HttpClient backend to Jersey Client

From: Jorge L Williams <Jorge.Williams_at_inl.gov>
Date: Mon, 17 Nov 2008 18:27:28 -0700

Okay I'm a little lazy so some of this e-mail is a cut and paste from one
I posted to the user mailing list last week...

I've added support for Basic, Digest, and NTLM authentication and
preemptive authentication by adding an Apache HTTPClient backend to Jersey
client. Cookie handling is also supported -- though off by default. This
also fixes other errors associated with URLConnections like not being able
to retrieve 401 error codes. Also, HTTPClient seems perform better than
URLConnection -- though I haven't done any real benchmarking -- it does
feel snappier! As as side note, I've also modified the WADL2Java
implementation so that it uses Jersey client as a backend -- as a way of
providing support for these features from a generated WADL client.

I took the approach of simply creating a root ClientHandler and
ClientConfig class (under impl). I didn't touch any of the Jersey Client
API code.

Basically the usage looks something like this:


DefaultHttpClientConfig clientConfig = new DefaultHttpClientConfig();

//
// Set the credentials (realm, host, port, username, password)
//
clientConfig.setCredentials (null, "host.inl.gov", 443, username,
password);
clientConfig.getProperties().put
(HttpClientConfig.PROPERTY_PREEMPTIVE_AUTHENTICATION, Boolean.TRUE);

Client c = new Client (new HttpClientHandler(), clientConfig);


I've been testing my implementation for a week or so and things seems
stable.

You might want to look at the documentation for the HttpClientConfig class
for an idea of what features are supported. I've tried my best to shield
developers from the details of Apache HTTPClient as much as possible. You
only need to instantiate a class from the HttpClient package if you want
to use a custom credential provider.

Some other things to keep in mind:

    * There is a single HTTPClient per HttpClientHandler. It may be worth
while to use it as a root for multiple Clients to save on resources. There
should typically be a single HttpClientHandler per application.
    * Client operations are thread safe, the HTTP connection may be
shared between different threads. If you retrieve a response entity input
stream you must call close() on the stream when you're done with it in
order to release the connection to other threads.
    * In this initial implementation, only standard methods (GET, POST,
DELETE, OPTIONS, HEAD, and PUT) are supported.
    * Chunk encoding is a true/false operation in HTTPClient there's no
way of specifying a chunk size. If you set PROPERTY_CHUNKED_ENCODING_SIZE
to anything other than null it will be set to true.
    * In this initial implementation, chunk encoding probably doesn't
matter since we write entities to a byte array before we transmit them

Possible Security Flaw:

Credentials get passed from an HttpClientConfig to an HttpClientHandler
via ClientConfig properties. I'm not sure if this poses a security
threat, but I'd figure I'd mention it. Is there a better way of doing
this? I couldn't find a good connection between a ClientHandler and a
ClientConfig...

Anyway, let me know if you have any issues,

jOrGe W.