【问题标题】:How to handle compressed (gzip) HTTP requests (NOT response) in JAVA servlet - Simple Example?如何在 JAVA servlet 中处理压缩(gzip)HTTP 请求(非响应) - 简单示例?
【发布时间】:2020-07-07 21:46:54
【问题描述】:

我在这个问题上苦苦挣扎了很长一段时间;并在找到一个简单的解决方案后......想问一个问题和答案!

关于堆栈溢出问题已经以不同的方式多次提出,accepted solutions 要么是 partially correct and complex,要么是谈论 response 压缩。

汇总有关该主题的一些旧问答:

【问题讨论】:

标签: java servlets compression httprequest gzip


【解决方案1】:

一个简单的解决方案是使用过滤器。 (See servlet-filter tutorial)

创建一个 Servlet 过滤器:

  • 确保首先/在任何使用请求正文的过滤器之前调用过滤器。

我。在 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>

二。过滤器类代码:

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() {}
}

三。接下来是 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));
    }
}

现在剩下的就是如何发送压缩请求了?

Postman 尚不支持发送压缩的HttpRequest 正文。您仍然可以通过使用 binary 选项并使用包含正确编码的请求正文的 gzip 压缩文件来使其工作。

一种方法是使用带有pako compression library 的nodejs 脚本。对于多部分/表单数据请求,请参阅 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)
})

注意事项:

  • 我们使用Content-Encoding: application/gzip 标头来指定请求被压缩。是的,这是标准的。
  • 不要使用Content-Type,因为它不适用于multipart/form-data。
  • HTTP 协议一直在假设 HttpRequest 的大小与 HttpResponse 相比相形见绌。
  • 此外,由于假定浏览器/客户端的计算能力有限,标准是压缩响应而不是请求。浏览器不能原生压缩,但可以原生解压。
  • 但是,不幸的是,在许多开发人员推动代码多年之后;一些 HTTP API 演变为消耗大量字符串/数据!!
  • 让 java servlet 可以选择处理压缩请求是小菜一碟。

【讨论】:

    猜你喜欢
    • 2010-12-17
    • 1970-01-01
    • 2011-05-21
    • 1970-01-01
    • 1970-01-01
    • 2012-02-12
    • 1970-01-01
    • 2012-08-22
    相关资源
    最近更新 更多