Question

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

Was it helpful?

Solution 3

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();
    }
}

OTHER TIPS

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.

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

As karoroberts said you have to check the length of the content sent in the POST. But you still can use BufferedReader.

Just have to check for the Content-Length header for the size of it and after finishing reading all the headers you can set a char array of that size and make the reading of the POST content:

char[] buffer = new char[contentLength]; request.read(buffer);

Where request is the BufferedReader. If you need the POST content in a string, you can use: String.valueOf(buffer);

Note: BufferedReader.read returns an int of the characters readed, so you could check there for inconsistencies with the Content-Length header.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top