views:

409

answers:

3

Hello,

Looking for a bit of help, I have currently written a HTTP server. It currently handles GET requests fine. However, whilst using POST the buffered reader seems to hang. When the request is stopped the rest of the input stream is read via the buffered reader. I have found a few things on google. I have tried changing the CRLF and the protocol version from 1.1 to 1.0 (browsers automatically make requests as 1.1) Any ideas or help would be appreciated. Thanks

+2  A: 

Wouldn't write my own implementation. Look at the following existing components, if you want:

Hans Doggen
If I could write "seconded" more than once without feeling silly, yeah, that's the route to go.
Dean J
sorry i meant server NOT client.
Hugh
Still, Apache HttpComponents is the way to go.
Bombe
Yeah, why on earth anyone would want to write a Java HTTP server is beyond me (even more so than client) -- just use Jetty, Tomcat, Grizzly, or any of n+1 other alternatives. I mean, unless it's an assignment on a college course or so.
StaxMan
+3  A: 

I agree with Hans that you should use a standard and well-tested library to do this. However, if you are writing a server to learn about HTTP, here's some info on doing what you want to do.

You really can't use a BufferedReader because it buffers the input and might read too many bytes from the socket. That's why your code is hanging, the BufferedReader is trying to read more bytes than are available on the socket (since the POST data doesn't have an end of line), and it is waiting for more bytes (which will never be available).

The process to simply parse a POST request is to use the InputStream directly

  • For each line in the header read a byte at a time until you get a '\r' and then a '\n'

  • Look for a line that starts with "Content-Length: ", extract the number at the end of that line.

  • When you get a header line that is empty, you're done with headers.

  • Now read exactly the # of bytes that came from the Content-Length header.

Now you can write your response.

karoberts
A: 

This is not safe! But shows how to get the POST data during an Input Stream after the initial HTTP Headers.

This also only works for POST data coming in as "example=true&bad=false" etc.

private HashMap hashMap = new HashMap();
private StringBuffer buff = new StringBuffer();
private int c = 0;
private String[] post;    public PostInputStream(InputStream in) {

    try {
        //Initalizes avaliable buff
        if (in.available() != 0) {
            this.buff.appendCodePoint((this.c = in.read()));
            while (0 != in.available()) {
                //Console.output(buff.toString());
                buff.appendCodePoint((this.c = in.read()));
            }

            this.post = buff.toString().split("&");

            for (int i = 0; i < this.post.length; i++) {
                String[] n = this.post[i].split("=");
                if (n.length == 2) {
                    hashMap.put(URLDecoder.decode(n[0], "UTF-8"), URLDecoder.decode(n[1], "UTF-8"));
                } else {
                    Console.error("Malformed Post Request.");
                }
            }
        } else {
            Console.error("No POST Data");
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
Hugh