JDK-4160499 : sun.net.www.protocol.http.HttpURLConnection error handling
  • Type: Bug
  • Status: Resolved
  • Resolution: Fixed
  • Component: core-libs
  • Sub-Component: java.net
  • Priority: P5
  • Affected Version:
    2.0,1.1.4,1.1.6,1.2.0,1.2.2,1.3.0,1.3.0_05,1.3.1 2.0,1.1.4,1.1.6,1.2.0,1.2.2,1.3.0,1.3.0_05,1.3.1
  • OS:
    generic,solaris_2.5.1,solaris_2.6,solaris_8,windows_nt,windows_2000 generic,solaris_2.5.1,solaris_2.6,solaris_8,windows_nt,windows_2000
  • CPU: generic,x86,sparc
  • Submit Date: 1998-07-24
  • Updated Date: 2001-10-19
  • Resolved Date: 2000-09-08
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availabitlity Release.

To download the current JDK release, click here.
Other
1.3.0_05 05Resolved
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Description
There are certain file types (.html, .htm, .txt) that will not generate a FileNotFoundException if the server returns a >400 response code. This sometimes leads to an error stream being read as if it were the requested document. If another type of file is requested a FileNotFoundException is thrown and the error stream is not accessible without requesting the document again.

The RFE 4087140 which was approved by the CCC describes the method getErrorStream() which would provide an error stream in the case of a FileNotFoundException. Probably the best course would be to always throw the FileNotFoundException on >400 responses for any type of document. Applications could then catch this exception and call getErrorStream() if they wanted access to the error stream (as in the case of HotJava, where it displays the server error message)

Name: krT82822			Date: 09/29/99


The implementation of java.net.HttpURLConnection.getErrorStream() is "return null".  Furthermore, the implementation of sun.net.www.protocol.http.HttpURLConnection.getErrorStream() is also "return null".

The fact that these methods are unimplemented indicates that they will never work as defined.

This is a major problem, becuase of the behaivor of the getInputStream() methods on the same classes.  These methods throw a FileNotFoundException if the HTTP response code is >= 400.  Nearly every web server in existence returns a document along with an error code -- for example, if the error code is 404, the document usually says "Document not found", and generally includes the e-mail address of the webmaster, and possibly other useful information.  Sometimes this document even indicates that a search returned no matches.  In any case, it is often important that this "error" document is made available to the user -- but there is NO WAY to get this document using the URLConnection classes.

I'm trying to write an HTTP proxy in Java.  I CANNOT do so, however, becuase I can't handle error conditions -- which, of course, happen all the time on the Internet.  The end user's browser gets a "document contained no data" or similar error instead of the real error document that the remote web server created.

import java.io.*;
import java.net.*;

public class Connect {
        static  byte[]                  buf;
        static  InputStream             is, es;
        static  URLConnection   conn;
    
    public static void main(String[] args) {
                buf = new byte[80];

        try{
            URL url = new URL("http://java.sun.com/products/jdk/1.3/docs/badLastSeg");
                        conn = url.openConnection();
                        is = conn.getInputStream();
                        es = ((HttpURLConnection)conn).getErrorStream();
                        System.out.println("input stream IS:"  +  is);
                        System.out.println("error stream IS:"  +  es);
                        is.read(buf);
                        System.out.println("buf is:" + buf);
                        for(int i=0; i < buf.length; i++) {
                                System.out.print(buf[i]);
                        }
                        System.out.println("-----");
                }
                catch(Exception e){
                        System.err.println("YIKES!");
                        System.out.println(e);
                        try {
                                System.out.println("err stream is:" + es);
                                // commence workaround... (which doesn't work yet)
                                es = ((HttpURLConnection)conn).getErrorStream();
                                System.out.println(
                                        "err stream (after 2nd getErrorStream()) is (still) :  " + es);
                                if(es != null) {
                                        es.read(buf);
                                        for(int i=0; i < buf.length; i++) {
                                                System.out.print(buf[i]);
                                        }
                                }
                        }
                        catch(Exception e2) {
                                System.exit(1);
                        }
                        System.exit(1);
                }
                
        }
}

(Review ID: 95930)
======================================================================

Name: krT82822			Date: 12/03/99


C:\Ian\demo>c:\jdk1.2.2\bin\java -version
java version "1.2.2"
Classic VM (build JDK-1.2.2-001, native threads, symcjit)

C:\Ian\demo>

Two attachments, as it were, here.  First the stack trace and second the test
program.  Use this test program to surf to a cite that gives an unauthorized
response (401).  I'm sure you can find a site like that (ours is from an
internal servlet, you don't really want that too).  Try the test program with a
site that returns 200, 301... anything
less that 400 and everything is okay.  Try anything 400 and over and you get
a file not found exception and 404 is NOT the only over 400 code. 401 should
be returned!

LoginTest.java is a complete program just run it from the command line.

**********************Stack Trace
C:\Ian\demo>rl

C:\Ian\demo>c:\jdk1.2.2\bin\java LoginTest
java.io.FileNotFoundException: http://192.168.0.129/servlet/Demo1.LoginHandler.L
oginHandler
        at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLCon
nection.java:530)
        at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:145
)
        at LoginTest.main(LoginTest.java:14)

C:\Ian\demo>rl

C:\Ian\demo>c:\jdk1.2.2\bin\java LoginTest
204
No Content
************* end stack trace

*******************************file LoginTest.java
class LoginTest
{
    public static final void main(String args[])
    {
	try
	{
	    java.net.URL url = new
java.net.URL("http://192.168.0.129/servlet/Demo1.LoginHandler.LoginHandler");
	    java.net.HttpURLConnection hurlc =
(java.net.HttpURLConnection)url.openConnection();
	    hurlc.setDoOutput(true);
	    hurlc.setDoInput(true);
	    java.io.OutputStream out = hurlc.getOutputStream();
	    out.write("name=micky&passwd=mouse".getBytes());
	    System.out.println(hurlc.getResponseCode());
	    System.out.println(hurlc.getResponseMessage());
	    java.io.InputStream in = hurlc.getInputStream();
	    byte[] b = new byte[2000];
	    in.read(b);
	    System.out.println(new String(b));
	}
	catch(Exception e)
	{
	    e.printStackTrace();
	}
      
    }
}
*********** end file LoginTest.java
(Review ID: 98576)
======================================================================

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: merlin FIXED IN: merlin INTEGRATED IN: 1.3.0_05 1.3.1_01 merlin VERIFIED IN: 1.3.1_01a
2004-06-14

WORK AROUND If the requested file does not exist, and ends in .html, .htm, .txt or /, you will get the error stream with no exception thrown. If the file does not end like any of these you can catch the exception and immediately request it again to get the error stream. The response code can be obtained with getResponseCode(). Name: krT82822 Date: 09/29/99 There is NO WORKAROUND for this bug! Short of using raw sockets to retrieve the error document. But this may be difficult or impossible, depending on what information must be passed to the server in order to generate the error document. (Review ID: 95930) ====================================================================== Name: skT45625 Date: 04/10/2000 You can't use a buffered-anything, because that would possibly trigger the Exception without returning data. Include a check for a SocketException around your read() loop, and handle it like an EOF. (Review ID: 103500) ======================================================================
2004-06-11

EVALUATION Related to bug 4222009. We should get rid of the error handling inside HttpURLConnection.getInputStream, and let applications rely on response code and message for further action. As it should have been done in the first place. Will fix in Merlin. yingxian.wang@eng 1999-10-11
1999-10-11