我正在编写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上进行了测试。