On Tue, 2012-09-04 at 15:20 -0400, Daniel Kulp wrote: > On Aug 6, 2012, at 10:43 AM, Oleg Kalnichevski <[email protected]> wrote: > >>>> CXF allows these to be configured on a per-client (and sometimes even > >>>> per- request) basis. It looks like HC seems to have these on the > >>>> connection factory. > >>> > >>> It does not have to be this way. Connections can start off as plain and > >>> later get upgraded to TLS/SSL by the protocol handling code. One would > >>> have to tweak the default protocol handler a bit, though, probably by > >>> overriding the HttpAsyncRequestExecutor#requestReady method [2]. > >> > >> Ah. OK. I'll take a look there. I was looking in the various > >> connection > >> factories and pools. Haven't looked there yet. Lots of stuff going on. > >> > >> :-) > >> > > > > I also added a CXF specific connection manager implementation in order > > to enable SSL customization based on request configuration. However, > > before I proceed I would like to understand the requirements a little > > better. Can I assume that once an SSL connection has been fully set up > > using request level config parameters and can be pooled and safely > > reused for subsequent requests to the same service (even by different > > users) or requests may contain different / incompatible SSL > > configuration for the same service? > > They may contain different configurations. Particular different client certs > if using client certs as the authentication mechanism. > > I found the "state" object to pass into the connection factory and plan on > implementing a new state object that will attempt to handle that by comparing > the various values on the HTTPConduit settings. However, I *DID* run into > a couple problems that, while I was able to work around them with some hacks, > they likely should be fixed in the HTTP stuff. In particular: > > 1) The "state" object that is passed into the factory is never saved > anywhere. IMO, if a new connection is created based on the state, it might > be good to record that state (or at least make that an option) so the state > stuff actually works. I got around this by subclassing the BasicNIOConnPool > to override the BasicNIOConnPool.createEntry method to add a state object to > the entry. A bit involved. >
Let me try to explain the rationale behind the design. HC connection pools distinguish between route info and connection state. Routes are immutable and are well known in advance. A route in its basic form is a scheme/host/port combo. At connection creation time only the route matters as all HTTP connections start out their life cycle as state-less per HTTP specification. In real life settings, however, HTTP connections may acquire certain state during their life-cycle, for instance, by serving a resource protected with a connection based auth scheme such as NTLM. So, the object that represents a state of a connection may need to be associated with the connection after it has already been created. SSL is similar. An HTTP connection can be created as plain and later get upgraded to TLS/SSL. If the target server requires the client to authenticate itself with a certificate, the connection becomes state-full after successful authentication only. Once a connection becomes state-full it can only be leased if requested with the same combination of route info and state. I believe this is the reason why you are getting a new SSL connection for each new HTTPS request. I guess the state object used in the lease request is not equal to that associated with the pool entry. If in your case SSL context details are effectively a given, you should make then a part of the route info instead of the state. HC connection pools are designed to be able to use any arbitrary immutable class as a route info. > 2) Lots of issues trying to associate the request with the connection at > connection creation time. I needed information from the request in order to > setup the SSL stuff. However, I had a LOT of issues trying to accomplish > that. The only thing the ConnectionFactory gets it the IOSession. All that > has in it is the HttpHost. The HttpHost is final. The connect occurs on a > different thread so thread locals won't work. Also note that all the fields > in SSLIOSession are final and private. Thus, I also couldn't find a way to > delay the SSL setup stuff till later. Thus, I had to get the > request/connection stuff associated up front. I ended up using a > IdentityHashMap to associate the HttpHost with the request stuff, but it > seemed very hacky. > > Not really sure what the right solution would be. My initial thought was to > make HttpHost non-final so that I could subclass it with an CXFHttpHost or > SSLHttpHost or something that would contain extra methods that I could call. > Alternatively, add a "properties" map to HttpHost or similar that I could > store additional stuff. Another option would be to have the IOSession > passed to the factory also contain the "state" (if specified) as a property > that could be queried. > Just ditch HttpHost. You obviously need a richer class to represent connection routes. HttpClient has HttpRoute class for that matter. You probably should be using a custom class that also includes HTTP proxy and SSL context bits specific to CXF. Does this help you in any way? Oleg
