问题在servlet中读取请求体

时间:2010-08-06 09:56:08

标签: java http servlets post tomcat6

我正在编写一个HTTP代理,它是测试/验证的一部分 系统。代理过滤来自客户端设备的所有请求 并指导他们走向各种被测系统。

代理实现为转发每个请求的servlet 到目标系统,它处理GET和POST。有时候 改变目标系统的响应以适应各种测试 条件,但这不是问题的一部分。

转发请求时,将复制除此之外的所有标头 这是实际HTTP传输的一部分,如Content-Length和 连接头。

如果请求是HTTP POST,则请求的实体主体是 同时转发,这里有时它不起作用。

从servlet请求中读取实体主体的代码如下:

URL url = new URL(targetURL);
HttpURLConnection conn  = (HttpURLConnection)url.openConnection();
String method = request.getMethod();

java.util.Enumeration headers = request.getHeaderNames();
while(headers.hasMoreElements()) {

    String headerName = (String)headers.nextElement();
    String headerValue = request.getHeader(headerName);

    if (...) { // do various adaptive stuff based on header 

    }

    conn.setRequestProperty(headerName, headerValue);
}

//这是失败的部分

char postBody[] = new char[1024];
int len;

if(method.equals("POST")) {
    logger.debug("guiProxy, handle post, read request body");
    conn.setDoOutput(true);

    BufferedReader br = request.getReader();
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));

    do {
        logger.debug("Read request into buffer of size: " + postBody.length);

        len = br.read(postBody, 0, postBody.length);
        logger.debug("guiProxy, send request body, got " + len + " bytes from request");

        if(len != -1) {
            bw.write(postBody, 0, len);
        }
    } while(len != -1);
    bw.close();
}

所以发生的事情是第一次收到POST,-1 wirehark跟踪显示从请求阅读器读取字符 包含URL编码的post参数的实体主体在那里 它位于一个TCP段中,因此没有网络相关 差异。

第二次,br.read成功返回了232字节 POST请求实体主体和每个即将发出的请求都可以。

第一个和即将发布的POST请求之间的唯一区别是 在第一个,没有饼干存在,但在第二个, 存在一个映射到JSESSION的cookie。

这可能是因为实体不能获得的副作用 servlet容器中的请求处理已经读完了POST 参数,但为什么它适用于即将到来的请求。

我认为解决方案当然是忽略实体主体 POST请求包含URL编码数据并获取所有参数 从servlet请求改为使用getParameter并重新插入它们 输出请求。

尽管这很棘手,因为POST请求可能包含GET 参数,现在不在我们的应用程序中,而是实现它 正确的是一些工作。

所以我的问题基本上是:为什么读者来自 request.getReader()在读取和实体主体时返回-1 如果实体主体不可用,则出现在请求中 读取,然后getReader应该抛出非法状态异常。一世 我也尝试使用带有相同的getInputStream()的InputStream 结果

所有这些都在apache-tomcat-6.0.18上进行了测试。

2 个答案:

答案 0 :(得分:5)

  

所以我的问题基本上是:为什么request.getReader()的阅读器在阅读时会返回-1。

当没有身体或已经被阅读时,它将返回-1。你不能读两遍。确保请求/响应链中的任何内容都没有读过它。

  

并且请求中存在实体主体,如果实体主体不可读,则getReader应该抛出非法状态异常。

只有在你之前已经在请求上调用getInputStream()时才会抛出它,而不是在它不可用时。

  

我也尝试使用带有相同结果的getInputStream()的InputStream。

毕竟,我更喜欢流式传输字节而不是字符,因为你不需要考虑字符编码(你现在没有做到这一点,这可能导致未来的问题,当你得到这一切工作)。

答案 1 :(得分:1)

好像,移动

BufferedReader br = request.getReader()

在所有操作之前,读取请求(如request.getHeader())对我很有用。