Chapter 6 advanced topics 6.1 custom client connection
Under specific conditions, you may need to customize the way HTTP packets are transmitted over the line, and the possible HTTP parameters are used to handle non-standard incompatible behaviors. For example, for a web crawler, it may need to force the httpclient to accept the response header information in an incorrect format to rescue the content of the message.
Generally, the process of inserting a custom message parser or custom connection implementation requires several steps:
Provides a custom lineparser/lineformatter interface. If necessary, implement the message parsing/formatting logic.
Class mylineparser extends basiclineparser {@ overridepublic header parseheader (final chararraybuffer buffer) throws parseexception {try {return Super. parseheader (buffer);} catch (parseexception ex) {// suppress parseexception exception return New basicheader ("invalid", buffer. tostring ());}}}
I mentioned a custom operatedclientconnection implementation. Replace the default request/response parser and request/response formatter to be customized. Write/read different packets as neededCode.
Class myclientconnection extends defaultclientconnection {@ describedomainbuffer (final sessioninputbuffer buffer, final httpresponsefactory responsefactory, final httpparams Params) {return new values (buffer, new mylineparser (), responsefactory, params );}}
To create new class connections, a custom clientconnectionoperator interface is provided. Implement different Socket initialization codes if needed.
Class myclientconnectionoperator extends {public myclientconnectionoperator (final schemeregistry SR) {super (SR) ;}@ overridepublic operatedclientconnection createconnection () {return New myclientconnection ();}}
To create connection operations for new classes, the clientconnectionmanager interface is provided.
Class myclientconnmanager extends {public myclientconnmanager (final httpparams Params, final callback SR) {super (Params, Sr) ;}@ overrideprotected clientconnectionoperator createconnectionoperator (final callback SR) {return New myclientconnectionoperator (SR );}}
6.2 stateful HTTP connections the HTTP specification assumes that session status information is usually embedded in HTTP packets in the HTTP cookie format. Therefore, HTTP connections are usually stateless, this assumption is usually incorrect in real life. In some cases, when an HTTP connection is created using a specific user ID or security context, it cannot be shared with other users and can only be reused by this user. An example of such a stateful HTTP connection is the NTLM authentication connection and the SSL connection that uses the client certificate authentication. 6.2.1 The User Token processor httpclient depends on the usertokenhandler interface to determine whether the given execution context is specified by the user. If the context is user-specified or if the context does not contain any resources or the details specified by the current user are null, the token object is returned by this processor and is expected to uniquely identify the current user. The User Token is used to ensure that the specified resource is not shared or reused with other users.
If it can be obtained from the given execution context, the default implementation of the usertokenhandler interface is to use an instance of the main class to represent the status object of the HTTP connection. Usertokenhandler uses a user's primary connection based on an SSL session Authentication mode such as NTLM or an enabled client. If neither of them is available, no token is returned.
If they cannot meet their needs by default, you can provide a custom implementation:
Defaulthttpclient httpclient = new defaulthttpclient (); httpclient. setusertokenhandler (New usertokenhandler () {public object getusertoken (httpcontext context) {return context. getattribute ("My-token ");}});
6.2.2 during HTTP request execution, httpclient adds the following objects related to the user identity to the execution context:
'Http. User-token': the object instance represents the real User ID, which is generally expected to be an instance of the principle interface.
After the request is executed, we can check the content of the local HTTP context to find whether the connection used to execute the request is stateful.
Defaulthttpclient httpclient = new defaulthttpclient (); httpcontext localcontext = new basichttpcontext (); httpget = new httpget ("http: // localhost: 8080 /"); httpresponse response = httpclient.exe cute (httpget, localcontext); httpentity entity = response. getentity (); If (entity! = NULL) {entity. consumecontent ();} object usertoken = localcontext. getattribute (clientcontext. user_token); system. Out. println (usertoken );
6.2.2.1 persistent and stateful connections note that persistent connections with State objects can be reused only when requests are executed and objects in the same state are bound to the execution context. Therefore, it is important to ensure that the same context is re-used to execute subsequent HTTP requests of the same user or to bind the User Token to the previous request execution context.
Defaulthttpclient httpclient = new defaulthttpclient (); httpcontext localcontext1 = new basichttpcontext (); httpget httpget1 = new httpget ("http: // localhost: 8080 /"); httpresponse response1 = httpclient.exe cute (httpget1, localcontext1); httpentity entity1 = response1.getentity (); If (entity1! = NULL) {entity1.consumecontent ();} principal = (principal) localcontext1.getattribute (clientcontext. user_token); httpcontext localcontext2 = new basichttpcontext (); localcontext2.setattribute (clientcontext. user_token, principal); httpget httpget2 = new httpget ("http: // localhost: 8080/"); httpresponse response2 = httpclient.exe cute (httpget2, localcontext2); httpentity entity2 = Response Ty (); If (entity2! = NULL) {entity2.consumecontent ();}