hc-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Adrian Sutton <adr...@intencha.com>
Subject SocketException with invalid server
Date Fri, 20 Jun 2003 00:50:06 GMT
Howdy all,
I'm having some trouble pinpointing the exact cause of an exception I'm  
getting from HttpClient, it seems to be related to connection  
management with MultiThreadedConnectionManager so I thought I'd draw on  
the expertise here. :)

Essentially, we have an invalid HTTP server (Stellent CMS actually and  
we will file a bug with them), which is returning headers like:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic "Secure Realm"
Connection: keep-alive

Which is clearly missing the Content-Length header.  Now, previously  
HttpClient handled this perfectly by reading until the end of the  
connection (ie: treating it like it was a Connection: close), however  
for some reason a socket exception is being thrown and the invalid  
connection is added back into the connection pool and then every  
connection to the server after that thows an exception.

I haven't been able to work out a good way to create a test case for  
this yet, but I can provide a simple set of steps to reproduce:

1. Get something like netcat which will let you "pretend" to be a HTTP  
server (ie: it will listen on a port and send back whatever you type)

2. Start it listening on port 8080 (for netcat use: nc -l -p 8080)

3.  Compile the program below and run it.

4. Enter the following into you netcat window (followed by a blank line  
to indicate the end of the headers):

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic "realm"
Connection: keep-alive

You'll see HttpClient throws an exception (listed below the code).   
Note that netcat did not close the connection, HttpClient did.  Also,  
note that it doesn't make any difference if you set netcat up to  
immediately start listening for another connection after the connection  
is closed (ie: netcat -l -p 8080 && netcat -l -p 8080).

It looks like HttpClient is closing the connection but not telling  
itself that the connection is closed so it then tries to reuse the  
connection and fails.  The same thing happens if you perform two GET  
requests and the server returns 200 OK with connection: keep-alive but  
no content length to the first request.

Any help tracking down this would be greatly appreciated, even if it's  
just a hint as to where to start making changes. :)

CODE: -------------------------
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.*;
import org.apache.commons.httpclient.contrib.ssl.*;
import org.apache.commons.httpclient.protocol.*;


public class Test {

     public static void main(String[] args) throws Exception {
         //String url =  
"https://basil/stellent/groups/secure/documents/adsales/testimage.jpg";
         String url = "http://localhost:8080/test.gif";
         HttpClient client = new HttpClient(new  
MultiThreadedHttpConnectionManager());
         client.getState().setCredentials(null, null, new  
UsernamePasswordCredentials("sysadmin", "idc"));
         GetMethod get = new GetMethod(url);
         int result = client.executeMethod(get);
         System.err.println("Result: " + result);
         System.err.println(get.getResponseBody());
     }
}
----------------------------------
Resulting exception:
Exception in thread "main" java.net.SocketException: Socket closed
         at  
java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:99)
         at  
java.net.SocketOutputStream.write(SocketOutputStream.java:136)
         at  
org.apache.commons.httpclient.HttpConnection$WrappedOutputStream.write(H 
ttpConnection.java:1347)
         at  
java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:69)
         at  
java.io.BufferedOutputStream.flush(BufferedOutputStream.java:127)
         at  
org.apache.commons.httpclient.HttpConnection.flushRequestOutputStream(Ht 
tpConnection.java:782)
         at  
org.apache.commons.httpclient.MultiThreadedHttpConnectionManager$HttpCon 
nectionAdapter.flushRequestOutputStream(MultiThreadedHttpConnectionManag 
er.java:1046)
         at  
org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase 
.java:2174)
         at  
org.apache.commons.httpclient.HttpMethodBase.processRequest(HttpMethodBa 
se.java:2529)
         at  
org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java 
:1066)
         at  
org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:6 
38)
         at  
org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:5 
00)
         at Test.main(Test.java:15)


The wire trace is:

[DEBUG] HttpClient - -Java version: 1.4.1_01
[DEBUG] HttpClient - -Java vendor: Apple Computer, Inc.
[DEBUG] HttpClient - -Java class path:  
commons-httpclient-2.0-beta1.jar:commons-logging-1.0.2.jar:.
[DEBUG] HttpClient - -Operating system name: Mac OS X
[DEBUG] HttpClient - -Operating system architecture: ppc
[DEBUG] HttpClient - -Operating system version: 10.2.6
[DEBUG] HttpClient - -SUN 1.2: SUN (DSA key/parameter generation; DSA  
signing; SHA-1, MD5 digests; SecureRandom; X.509 certificates; JKS  
keystore; PKIX CertPathValidator; PKIX CertPathBuilder; LDAP,  
Collection CertStores)
[DEBUG] HttpClient - -SunJSSE 1.41: Sun JSSE provider(implements RSA  
Signatures, PKCS12, SunX509 key/trust factories, SSLv3, TLSv1)
[DEBUG] HttpClient - -SunRsaSign 1.0: SUN's provider for RSA signatures
[DEBUG] HttpClient - -SunJCE 1.4: SunJCE Provider (implements DES,  
Triple DES, Blowfish, PBE, Diffie-Hellman, HMAC-MD5, HMAC-SHA1)
[DEBUG] HttpClient - -SunJGSS 1.0: Sun (Kerberos v5)
[DEBUG] MultiThreadedHttpConnectionManager -  
-HttpConnectionManager.getConnection:  config =  
org.apache.commons.httpclient.HostConfiguration@b8332793, timeout = 0
[DEBUG] HttpConnection - -Creating connection for localhost using  
protocol http:80
[DEBUG] HttpConnection - -Creating connection for localhost using  
protocol http:80
[DEBUG] HttpConnection - -HttpConnection.setSoTimeout(0)
[DEBUG] HttpMethod - -Execute loop try 1
[DEBUG] wire - ->> "GET /test.gif HTTP/1.1[\r][\n]"
[DEBUG] HttpMethod - -Adding Host request header
[DEBUG] wire - ->> "User-Agent: Jakarta  
Commons-HttpClient/2.0beta1[\r][\n]"
[DEBUG] wire - ->> "Host: localhost:8080[\r][\n]"
[DEBUG] wire - ->> "[\r][\n]"
[DEBUG] wire - -<< "HTTP/1.1 401 Unauthorized[\r][\n]"
[DEBUG] wire - -<< "WWW-Authenticate: Basic "realm"[\r][\n]"
[DEBUG] wire - -<< "Connection: keep-alive[\r][\n]"
[DEBUG] HttpMethod - -Authorization required
[DEBUG] HttpAuthenticator - -Using 'localhost:8080' authentication realm
[DEBUG] HttpMethod - -HttpMethodBase.execute(): Server demanded  
authentication credentials, will try again.
[DEBUG] HttpMethod - -Should NOT close connection in response to  
Connection: keep-alive

[DEBUG] HttpMethod - -Execute loop try 2
[DEBUG] wire - ->> "GET /test.gif HTTP/1.1[\r][\n]"
[DEBUG] HttpMethod - -Request to add Host header ignored: header  
already added
[DEBUG] wire - ->> "User-Agent: Jakarta  
Commons-HttpClient/2.0beta1[\r][\n]"
[DEBUG] wire - ->> "Host: localhost:8080[\r][\n]"
[DEBUG] wire - ->> "Authorization: Basic c3lzYWRtaW46aWRj[\r][\n]"
[DEBUG] MultiThreadedHttpConnectionManager - -Freeing connection:  
org.apache.commons.httpclient.HttpConnection@5718f2
[DEBUG] MultiThreadedHttpConnectionManager - -Notifying no-one, there  
are no waiting threads
Exception in thread "main" java.net.SocketException: Socket closed
         at  
java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:99)
         at  
java.net.SocketOutputStream.write(SocketOutputStream.java:136)
         at  
org.apache.commons.httpclient.HttpConnection$WrappedOutputStream.write(H 
ttpConnection.java:1347)
         at  
java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:69)
         at  
java.io.BufferedOutputStream.flush(BufferedOutputStream.java:127)
         at  
org.apache.commons.httpclient.HttpConnection.flushRequestOutputStream(Ht 
tpConnection.java:782)
         at  
org.apache.commons.httpclient.MultiThreadedHttpConnectionManager$HttpCon 
nectionAdapter.flushRequestOutputStream(MultiThreadedHttpConnectionManag 
er.java:1046)
         at  
org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase 
.java:2174)
         at  
org.apache.commons.httpclient.HttpMethodBase.processRequest(HttpMethodBa 
se.java:2529)
         at  
org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java 
:1066)
         at  
org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:6 
38)
         at  
org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:5 
00)
         at Test.main(Test.java:15)


Mime
View raw message