代码之家  ›  专栏  ›  技术社区  ›  Ernelli

servlet中读取请求主体时出现问题

  •  2
  • Ernelli  · 技术社区  · 14 年前

    我正在编写HTTP代理,它是测试/验证的一部分 系统。代理筛选来自客户端设备的所有请求 并引导他们进入测试中的各个系统。

    代理作为servlet实现,其中每个请求都被转发。 对于目标系统,它处理get和post。有时 改变目标系统的响应以适应各种测试 条件,但这不是问题的一部分。

    转发请求时,除了那些邮件头外,所有邮件头都会被复制 这是实际HTTP传输的一部分,如内容长度和 连接头。

    如果请求是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();
    }
    

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

    第二次,br.read成功返回 Post请求实体体和每个即将到来的请求也可以工作。

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

    是否是实体实体实体不可用的副作用,因为 servlet容器中的请求处理allready已读取日志 参数,但为什么它在即将到来的请求上工作。

    我认为解决方案当然是忽略 发布包含URL编码数据的请求并获取所有参数 来自servlet请求,而不是使用getParameter并重新插入它们 传入传出请求。

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

    所以我的问题是:为什么读者 REQUEST.GetReader()RETURN-1当读取实体时 如果实体主体不可用于 正在读取,则GetReader应引发非法状态异常。我 还尝试使用getinputstream()对inputstream执行相同操作 结果。

    所有这些都在Apache-Tomcat-6.0.18上进行了测试。

    2 回复  |  直到 12 年前
        1
  •  5
  •   BalusC    14 年前

    所以我的问题基本上是:为什么读请求中的reader.getreader()在读时返回-1。

    当没有尸体或尸体 已经 读过。你不能读两遍。确保请求/响应链中之前没有任何内容读取过它。

    请求中存在实体体,如果实体体不可读取,则getreader应引发非法状态异常。

    只有当你已经打过电话的时候才会扔 getInputStream() 根据之前的请求,而不是当它不可用时。

    我还尝试使用getInputStream()对inputstream进行处理,结果相同。

    毕竟,比起字符,我更喜欢流式字节,因为这样您就不需要考虑字符编码(到目前为止,您还没有这样做,这可能会导致将来的问题,当您将所有这些都发挥作用时)。

        2
  •  1
  •   kleopatra Aji kattacherry    12 年前

    看来,这很感人

    BufferedReader br = request.getReader()
    

    在所有操作之前,那个读请求(如request.getheader())对我很有效。