This is the mail archive of the
java-patches@sources.redhat.com
mailing list for the Java project.
Patch: Http protocol
- To: java-patches at sourceware dot cygnus dot com
- Subject: Patch: Http protocol
- From: Bryce McKinlay <bryce at albatross dot co dot nz>
- Date: Thu, 10 Aug 2000 21:10:11 +1200
This patch, based on an old submission from John Stracke, fixes some
problems with our HttpConnection stuff. There are still some issues
remaining, such as not following redirects, not supporting proxys, and
an inefficient header parsing loop. We may also eventually want to
properly support some HTTP/1.1 features like chunking/persistent
connections/pipelining, but this patch works fairly well for now. I'm
checking it in.
regards
[ bryce ]
2000-08-10 Bryce McKinlay <bryce@albatross.co.nz>
John Stracke <francis@ecal.com>
* gnu/gcj/protocol/http/Connection.java (gotHeaders): Removed.
(connect): Don't falsely claim HTTP/1.1 compliance. Call
getHttpHeaders().
(disconnect): Don't unset connected flag.
(getHeaderField (String)): Call connect() if not connected.
(getHeaderField (int)): Ditto.
(getHeaderFieldKey): Ditto.
(getHttpHeaders): Don't call connect().
* java/net/HttpURLConnection.java (instanceFollowRedirects,
gotResponseVals): New fields.
(getResponseCode): Call getResponseVals() conditionally.
(getResponseMessage): Ditto.
(getResponseVals): Call connect(). Don't throw FileNotFoundException.
Index: gnu/gcj/protocol/http/Connection.java
===================================================================
RCS file: /cvs/java/libgcj/libjava/gnu/gcj/protocol/http/Connection.java,v
retrieving revision 1.4
diff -u -r1.4 Connection.java
--- Connection.java 2000/03/07 19:55:25 1.4
+++ Connection.java 2000/08/10 08:50:15
@@ -1,6 +1,6 @@
// Connection.java - Implementation of HttpURLConnection for http protocol.
-/* Copyright (C) 1999 Free Software Foundation
+/* Copyright (C) 1999, 2000 Free Software Foundation
This file is part of libgcj.
@@ -37,7 +37,6 @@
private Hashtable requestProperties;
private Hashtable hdrHash = new Hashtable();
private Vector hdrVec = new Vector();
- private boolean gotHeaders = false;
private BufferedInputStream bufferedIn;
public Connection(URL url)
@@ -94,14 +93,15 @@
PrintWriter out = new PrintWriter(sock.getOutputStream());
// Send request including any request properties that were set.
- out.print(getRequestMethod() + " " + url.getFile() + " HTTP/1.1\n");
+ out.print(getRequestMethod() + " " + url.getFile() + " HTTP/1.0\n");
out.print("Host: " + url.getHost() + ":" + port + "\n");
Enumeration reqKeys = requestProperties.keys();
Enumeration reqVals = requestProperties.elements();
while (reqKeys.hasMoreElements())
out.print(reqKeys.nextElement() + ": " + reqVals.nextElement() + "\n");
out.print("\n");
- out.flush();
+ out.flush();
+ getHttpHeaders();
connected = true;
}
@@ -120,7 +120,6 @@
}
sock = null;
}
- connected = false;
}
// TODO: public boolean usingProxy()
@@ -135,10 +134,8 @@
if (!connected)
connect();
- if (! doInput)
+ if (!doInput)
throw new ProtocolException("Can't open InputStream if doInput is false");
- if (bufferedIn == null)
- bufferedIn = new BufferedInputStream(sock.getInputStream());
return bufferedIn;
}
@@ -157,48 +154,52 @@
// Override default method in URLConnection.
public String getHeaderField(String name)
{
- try
- {
- getHttpHeaders();
- }
- catch (IOException x)
- {
- return null;
- }
+ if (!connected)
+ try
+ {
+ connect();
+ }
+ catch (IOException x)
+ {
+ return null;
+ }
+
return (String) hdrHash.get(name.toLowerCase());
}
// Override default method in URLConnection.
public String getHeaderField(int n)
{
- try
- {
- getHttpHeaders();
- }
- catch (IOException x)
- {
- return null;
- }
+ if (!connected)
+ try
+ {
+ connect();
+ }
+ catch (IOException x)
+ {
+ return null;
+ }
+
if (n < hdrVec.size())
return getField((String) hdrVec.elementAt(n));
-
return null;
}
// Override default method in URLConnection.
public String getHeaderFieldKey(int n)
{
- try
- {
- getHttpHeaders();
- }
- catch (IOException x)
- {
- return null;
- }
+ if (!connected)
+ try
+ {
+ connect();
+ }
+ catch (IOException x)
+ {
+ return null;
+ }
+
if (n < hdrVec.size())
return getKey((String) hdrVec.elementAt(n));
-
return null;
}
@@ -226,20 +227,13 @@
private void getHttpHeaders() throws IOException
{
- if (gotHeaders)
- return;
- gotHeaders = true;
-
- connect();
-
// Originally tried using a BufferedReader here to take advantage of
// the readLine method and avoid the following, but the buffer read
// past the end of the headers so the first part of the content was lost.
// It is probably more robust than it needs to be, e.g. the byte[]
// is unlikely to overflow and a '\r' should always be followed by a '\n',
// but it is better to be safe just in case.
- if (bufferedIn == null)
- bufferedIn = new BufferedInputStream(sock.getInputStream());
+ bufferedIn = new BufferedInputStream(sock.getInputStream());
int buflen = 100;
byte[] buf = new byte[buflen];
@@ -247,6 +241,7 @@
boolean gotnl = false;
byte[] ch = new byte[1];
ch[0] = (byte) '\n';
+
while (true)
{
// Check for leftover byte from non-'\n' after a '\r'.
@@ -254,9 +249,12 @@
line = line + '\r' + new String(ch, 0, 1);
int i;
+ // FIXME: This is rather inefficient.
for (i = 0; i < buflen; i++)
{
- bufferedIn.read(buf, i, 1);
+ buf[i] = (byte) bufferedIn.read();
+ if (buf[i] == -1)
+ throw new IOException("Malformed HTTP header");
if (buf[i] == '\r')
{
bufferedIn.read(ch, 0, 1);
Index: java/net/HttpURLConnection.java
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/net/HttpURLConnection.java,v
retrieving revision 1.3
diff -u -r1.3 HttpURLConnection.java
--- HttpURLConnection.java 2000/03/07 19:55:27 1.3
+++ HttpURLConnection.java 2000/08/10 08:50:16
@@ -1,7 +1,7 @@
// HttpURLConnection.java - Subclass of communications links using
// Hypertext Transfer Protocol.
-/* Copyright (C) 1999 Free Software Foundation
+/* Copyright (C) 1999, 2000 Free Software Foundation
This file is part of libgcj.
@@ -69,11 +69,14 @@
public static final int HTTP_GATEWAY_TIMEOUT = 504;
public static final int HTTP_VERSION = 505;
+ static boolean followRedirects = true;
+
protected String method = "GET";
protected int responseCode = -1;
protected String responseMessage;
+ protected boolean instanceFollowRedirects = followRedirects;
- static boolean followRedirects = true;
+ private boolean gotResponseVals = false;
protected HttpURLConnection(URL url)
{
@@ -121,21 +124,30 @@
public int getResponseCode() throws IOException
{
- getResponseVals();
+ if (!gotResponseVals)
+ getResponseVals();
return responseCode;
}
public String getResponseMessage() throws IOException
{
- getResponseVals();
+ if (!gotResponseVals)
+ getResponseVals();
return responseMessage;
}
private void getResponseVals() throws IOException
{
+ // getHeaderField() will connect for us, but do it here first in
+ // order to pick up IOExceptions.
+ if (!connected)
+ connect();
+
+ gotResponseVals = true;
// Response is the first header received from the connection.
String respField = getHeaderField(0);
- if (! respField.startsWith("HTTP/"))
+
+ if (respField == null || ! respField.startsWith("HTTP/"))
{
// Set to default values on failure.
responseCode = -1;
@@ -158,10 +170,6 @@
responseCode = -1;
responseMessage = null;
}
- if (responseCode == HTTP_NOT_FOUND)
- throw new FileNotFoundException(url.toString());
- else if (responseCode >= 400)
- throw new IOException(url.toString() + " " + respField);
}
// TODO12: public Permission getPermission() throws IOException