2

I have written one proxy for intercepting the http requests for my tomcat.

every request would go through my proxy and do some checking before it reaches the tomcat server. i am doing it by binding the port using TCP/IP written in java.

All the requests(GET and POST) are successfully able to route to tomcat server except the file upload (multipart POST form) submissions.

even though i am able to get all the bytes in the TCP/IP and able to flush the data back to tomcat server, somehow the data is getting truncated/lost

is there any special things like encoding etc.. that i need to do when dealing with file stream content??

below is my sample code...


protected void processData(InputStream input, OutputStream output) throws IOException
    {
        // reads a line of text from an InputStream
        StringBuffer data = new StringBuffer("");
        StringBuffer data2 = new StringBuffer("");
        StringBuffer data3 = new StringBuffer("");
        StringBuffer data4 = new StringBuffer("");
        int c;

        try
        {
            while ((c = input.read()) >= 0)
            {
                data.append((char) c);

                // check for an end-of-line character
                if ((c == 0) || (c == 10) || (c == 13))
                {
                    output.write(data.toString().getBytes(), 0, data.length());
                    data4.append(data.toString());
                    data = new StringBuffer();
                    count = 0;
                }
                else
                {
                    if (count > 6)
                    {
                        if (input.available() == 1)
                        {
                            data.append((char) input.read());
                        }
                        data2.append(data.toString());
                        data4.append(data.toString());
                        output.write(data.toString().getBytes(), 0, data
                            .toString().length());
                        data = new StringBuffer();
                    }
                    else
                    {
                        if (count == 6)
                        {
                            if (data.toString().toLowerCase()
                                .indexOf("get /") == 0
                                || data.toString().toLowerCase()
                                    .indexOf("post /") == 0)
                            {
                                count = 0;
                                contentLength = -1;

                                // continue read data(header info)
                                while ((line = readLine(input, data)) != null)
                                {
                                    data = new StringBuffer();

                                // do my own stuff here dealing with headers

                                    if (StringUtils.isBlank(line))
                                    {
data4.append(line);
                                        output.write(line.getBytes(), 0,
                                            line.length());

                                        break;
                                    }

                                    line += "\r\n";
                                    output.write(line.getBytes(), 0,
                                        line.length());
                                    data4.append(line);
                                    output.flush();

                                }
                            }
                            else
                            {
                                if (input.available() == 1)
                                {
                                    data.append((char) input.read());
                                }
                            }
                        }
                        else
                        {
                            if (input.available() == 1)
                            {
                                data.append((char) input.read());
                                output.write(data.toString().getBytes(), 0,
                                    data.toString().length());
                                data4.append(data.toString());
                                data3.append(data.toString());
                                data = new StringBuffer();
                            }
                        }
                    }
                    count++;
                }
                if (processbody)
                    total++;

                if (contentLength > 0 && contentLength == total)
                {
                    log.debug("post data2: "
                        + (data2.toString() != null ? data2.toString() : " "));
                    log.debug("post data3: "
                        + (data3.toString() != null ? data3.toString() : " "));
                    log.debug("post data4: "
                        + (data4.toString() != null ? data4.toString() : " "));
                    output.flush();
                }
            }
        }
        catch (Exception e)
        {
            log.error("Error ", e);
        }
        finally
        {
        }
    }


3
  • Encoding is a non-issue when you work with InputStream/OutputStream only (and thus no Reader/Writer). As to the concrete problem, it would help if you update the question to include the smallest possible code snippet which (re)produces the problem, complete with real examples of actual input and output bytes. Commented Feb 13, 2011 at 5:10
  • 1
    Why not implement this by filter? Commented Feb 13, 2011 at 5:21
  • @Alexey Sviridov There are some limitations to servlet filter, e.g. if you want to drop a request (for example, in case of an attack) before it is fully recieved, you cannot do it with servlet filter. You need to provide some mechanism before it reaches tomcat. Commented Feb 13, 2011 at 5:49

2 Answers 2

1

There are a few flaws in your code:

  1. You read each byte from InputStream and then cast it into a char and appends it to string builder. If the stream is encoded characters, e.g. chinese, greek, any special characters, this will fail to properly decode the stream into readable string. Or if the stream is purely binary or ascii, string isn't the best to store your stream. This can easy happen when you submit a file multipart request.

  2. I am not an expert in concurrency (so I might be saying non sense here) but what would happen if there are more than one connection coming at the same time. You should becareful about this.

From what I see, you want to deal with the header of the http request, so there is no reason you should not be using servlet filter as Alexey Sviridov suggested. You can implement your own filter to intercept the header and do something with it. The benefit of using filter is that you can let the servlet API to parse your requested header for you and you will not need to worry about when to read/write your input/output stream.

However, if you intend to intercept the header of the request and decide whether the request should be passed onto your tomcat or servlet container, or doing anything which is not in the scope of servlet ability, you should look at the http proxy libraries. Here is example:

http://proxies.xhaus.com/java/

There is a previous question about writting HTTP Proxy in Java on stack overflow.

Regrettably, I don't want to encourage you to write your own http proxy. There are too many concerns you have to take into account.

Sign up to request clarification or add additional context in comments.

1 Comment

thanks very much for your reply. yes you are right. the problem was because of conveting the byte into char. i have changed my code to only read and convert the bytes to char for the header part. the rest i just read and write.
0

You're doing this much the hard way. Just read bytes and write them to the the other side. You don't care about strings or string buffers or line termination characters.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.