[英]How to handle compressed (gzip) HTTP requests (NOT response) in JAVA servlet - Simple Example?
I struggled with this problem for quite some time;我在这个问题上挣扎了很长一段时间; and after finding a simple solution... wanted to ask a question & answer!!
在找到一个简单的解决方案之后......想问一个问题和答案!
The question has been asked in different ways multiple times on stack overflow, and the accepted solutions
are either partially correct and complex
or talk about response
compression.这个问题在堆栈溢出时以不同的方式被多次提出,并且
accepted solutions
要么是partially correct and complex
的,要么是关于response
压缩的。
Aggregating some old Q&A on this topic:汇总有关此主题的一些旧问答:
wrong accepted ans/partially correct & complex subsequent ans.错误接受的答案/部分正确和复杂的后续答案。
The accepted ans is wrong.接受的答案是错误的。 It's about
RESPONSE
compression and not REQUEST
.这是关于
RESPONSE
压缩而不是REQUEST
。
Similar Questions - terminated at "NO request compression"类似问题 - 以“无请求压缩”终止
A specific question & ans for Spring RestTemplate framework: How to zip- compress HTTP request with Spring RestTemplate? Spring RestTemplate 框架的具体问题和解答: 如何使用 Spring RestTemplate 压缩 HTTP 请求?
A simple solution is by using a filter.一个简单的解决方案是使用过滤器。 ( See servlet-filter tutorial )
(参见 servlet-filter 教程)
Create a Servlet Filter:创建一个 Servlet 过滤器:
I. Register filter in web.xml:一、web.xml中的寄存器过滤器:
<filter>
<filter-name>GzipRequestFilter</filter-name>
<filter-class>com...pkg...GzipRequestFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>GzipRequestFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
II.二、 Code for filter class:
滤波器代码 class:
public class GzipRequestFilter implements Filter {
// Optional but recommended.
private static final Set<String> METHODS_TO_IGNORE = ImmutableSet.of("GET", "OPTIONS", "HEAD");
@Override
public void doFilter(
final ServletRequest request,
final ServletResponse response,
final FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String method = httpServletRequest.getMethod().toUpperCase();
String encoding = Strings.nullToEmpty(
httpServletRequest.getHeader(HttpHeaders.CONTENT_ENCODING));
if (METHODS_TO_IGNORE.contains(method) || !encoding.contains("application/gzip")) {
chain.doFilter(request, response); // pass through
return;
}
HttpServletRequestWrapper requestInflated = new GzippedInputStreamWrapper(httpServletRequest);
chain.doFilter(requestInflated, response);
}
@Override
public void init(final FilterConfig filterConfig) throws ServletException {}
@Override
public void destroy() {}
}
III.三、 Followed by code for GzipInputStream wrapper:
接下来是 GzipInputStream 包装器的代码:
// Simple Wrapper class to inflate body of a gzipped HttpServletRequest.
final class GzippedInputStreamWrapper extends HttpServletRequestWrapper {
private GZIPInputStream inputStream;
GzippedInputStreamWrapper(final HttpServletRequest request) throws IOException {
super(request);
inputStream = new GZIPInputStream(request.getInputStream());
}
@Override
public ServletInputStream getInputStream() throws IOException {
return new ServletInputStream() {
// NOTE: Later versions of javax.servlet library may require more overrides.
public int read() throws IOException {
return inputStream.read();
}
public void close() throws IOException {
super.close();
inputStream.close();
}
};
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(inputStream));
}
}
Now what remains is how to send a compressed request?现在剩下的是如何发送压缩请求?
Postman does not yet support sending compressed HttpRequest
bodies. Postman 尚不支持发送压缩的
HttpRequest
正文。 You can still make it work by using the binary
option and use a gzipped file containing the properly encoded request body.您仍然可以通过使用
binary
选项并使用包含正确编码的请求正文的 gzip 压缩文件来使其工作。
One way is using a nodejs script with pako
compression library .一种方法是使用带有
pako
压缩库的 nodejs 脚本。 For a multipart/form-data request see form-data
library对于 multipart/form-data 请求,请参见
form-data
library
const pako = require('pako')
const axios = require('axios')
var params = qs.stringify({
'num': 42,
'str': 'A string param',
});
data = pako.gzip(Buffer.from(params));
var config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Encoding': 'application/gzip';
},
}
await axios.post(
'http://url-for-post-api-accepting-urlencoded',
data,
config,
).then((res) => {
console.log(`status: ${res.status} | data: ${res.data}`)
}).catch((error) => {
console.error(error)
})
NOTES:笔记:
Content-Encoding: application/gzip
header to specify that a request is compressed.Content-Encoding: application/gzip
header 来指定请求被压缩。 Yes this is standard.Content-Type
as it will not work with multipart/form-data
.Content-Type
,因为它不适用于multipart/form-data
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.