smiley-http-proxy-servlet做代理时遇到的问题,报错failed to respond
背景
被代理的第三方接口基本上是POST请求,同时要求请求的Content-Type为application/x- www-form-urlencoded。结果测试时只要请求体携带参数,就会报错failed to respond,不携带参数就完好无损,通过不断的debug,和百度,最终找到了问题原因所在。
源码分析
- smiley-http-proxy-servlet的ProxyServlet就是一个servlet;
- 当前端请求代理地址时,首先经过各种FIlter,然后再调用该代理ProxyServlet的 service() 方法;
- 下面是service()方法重点部分
Object proxyRequest;
if (servletRequest.getHeader("Content-Length") == null && servletRequest.getHeader("Transfer-Encoding") == null) {
proxyRequest = new BasicHttpRequest(method, proxyRequestUri);
} else {
proxyRequest = this.newProxyRequestWithEntity(method, proxyRequestUri, servletRequest);
}
- 当然最终走的是newProxyRequestWithEntity方法,下面看看该方法源码
protected HttpRequest newProxyRequestWithEntity(String method, String proxyRequestUri, HttpServletRequest servletRequest) throws IOException {
HttpEntityEnclosingRequest eProxyRequest = new BasicHttpEntityEnclosingRequest(method, proxyRequestUri);
eProxyRequest.setEntity(new InputStreamEntity(servletRequest.getInputStream(), this.getContentLength(servletRequest)));
return eProxyRequest;
}
- 这里看到了最终是通过getInputStream将请求的Stream流传给新的代理请求Request
- 再调试的时候getInputStream一直拿不到数据,所以请求代理的时候报错failed to respond
问题原因
-
在项目的Filter过滤器链中,通过request.getParameter()获取了某个参数,所以在后面想再通过request.getInputStream()就不能获取了 -
那么为什么request.getInputStream()就不能获取了呢,这里就的说说request.getParameter()、request.getInputStream()和request.getReader()的区别了
request.getParameter()、request.getInputStream()和request.getReader()的区别
- 如果Post请求体是application/x- www-form-urlencoded,或是form表单提交。可以通过request.getParameter()方法来获取请求参数值。但当请求体不是该类型时,需要通过request.getInputStream()或request.getReader()方法来获取请求参数值。
- 当然请求体类型是application/x- www-form-urlencoded时也可以直接调用request.getInputStream()或request.getReader()方法来解析并获取请求参数,前提是还没调用request.getParameter()方法;
- 此时当request.getInputStream()或request.getReader()获取到请求数据后,无法再调request.getParameter()获取请求数据;
- 即对该类型的请求,三个方法互斥,只能调其中一个。
|