United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-4160499 : sun.net.www.protocol.http.HttpURLConnection error handling

Details
Type:
Bug
Submit Date:
1998-07-24
Status:
Resolved
Updated Date:
2001-10-19
Project Name:
JDK
Resolved Date:
2000-09-08
Component:
core-libs
OS:
solaris_8,solaris_2.6,windows_nt,solaris_2.5.1,generic,windows_2000
Sub-Component:
java.net
CPU:
x86,sparc,generic
Priority:
P5
Resolution:
Fixed
Affected Versions:
2.0,1.1.4,1.1.6,1.2.0,1.2.2,1.3.0,1.3.0_05,1.3.1
Fixed Versions:
1.3.0_05 (05)

Related Reports
Backport:
Backport:
Backport:
Duplicate:
Duplicate:
Duplicate:
Duplicate:
Duplicate:
Duplicate:
Duplicate:
Duplicate:
Relates:
Relates:

Sub Tasks

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



Hardware and Software, Engineered to Work Together