Как декодировать сжатое Gzip тело запроса в Spring MVC

У меня есть клиент, который отправляет данные с

CONTENT-ENCODING deflate

У меня есть такой код

@RequestMapping(value = "/connect", method = RequestMethod.POST)
@ResponseBody
public Map onConnect(@RequestBody String body){}

В настоящее время 'тело» распечатывает искаженные, сжатые данные. Есть ли способ заставить Spring MVC автоматически распаковывать его?

 SJuan7619 мая 2013 г., 21:13
Просто предположение, но неSpring поддерживает HTTP фильтры?
 Blauhirn29 апр. 2018 г., 17:30
не знаю, почему есть 5 вопросов, задающих одно и то же на SO, но вот одно из решений:stackoverflow.com/a/29096025/3779853

Ответы на вопрос(3)

Насколько я знаю, Tomcat неЯ не могу это поддержать, хотя вы можете написать фильтр.

Обычный способ справиться с этим - поместить Tomcat (или любой другой Java-контейнер,используется за сервером Apache, который настроен для обработки сжатых тел запросов.

 Adam10 окт. 2017 г., 13:13
 megalucio07 февр. 2018 г., 17:53
Что если, например, вы хотите распаковать, чтобы записать сообщение? Этот случай должен быть обработан приложением fiigure ...
Решение Вопроса

так что данные, поступающие в Spring, уже дефлированы.

Надеюсь, эти две ссылки помогут вам начать.

http://www.javablog.fr/javaweb-gzip-compression-protocol-http-filter-gzipresponsewrapper-gzipresponsewrapper.htmlhttp://srlawr.blogspot.com/2011/09/creating-custom-filter-in-spring.html
 Aryan Venkat03 авг. 2018 г., 10:37
@Erik Nedwidek Как мы добавим этот фильтр Gzip в Spring Web Flux (с Netty), а я нет?там нет ServletRequest?
 Happier16 мар. 2015 г., 08:26
Задан вопрос о запросе gzip вместо ответа.

Вам нужно написать собственный фильтр, чтобы разархивировать тело gzipped запросов. Так как вы будете читать весь поток ввода из запроса, вам также необходимо переопределить метод парсинга параметров. Это фильтр, который яЯ использую в моем коде. Поддерживает только сжатые POST-запросы, но вы можете обновить его, чтобы при необходимости использовать другие типы запросов. Также будьте осторожны, чтобы разобрать параметры I 'Используя библиотеку гуавы, вы можете взять свою отсюда:http://central.maven.org/maven2/com/google/guava/guava/}

public class GzipBodyDecompressFilter extends Filter {

@Override
public void init(FilterConfig filterConfig) throws ServletException {

}
/**
 * Analyzes servlet request for possible gzipped body.
 * When Content-Encoding header has "gzip" value and request method is POST we read all the
 * gzipped stream and is it haz any data unzip it. In case when gzip Content-Encoding header
 * specified but body is not actually in gzip format we will throw ZipException.
 *
 * @param servletRequest  servlet request
 * @param servletResponse servlet response
 * @param chain           filter chain
 * @throws IOException      throws when fails
 * @throws ServletException thrown when fails
 */
@Override
public final void doFilter(final ServletRequest servletRequest,
                           final ServletResponse servletResponse,
                           final FilterChain chain) throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest) servletRequest;
    HttpServletResponse response = (HttpServletResponse) servletResponse;
    boolean isGzipped = request.getHeader(HttpHeaders.CONTENT_ENCODING) != null
            && request.getHeader(HttpHeaders.CONTENT_ENCODING).contains("gzip");
    boolean requestTypeSupported = HttpMethods.POST.equals(request.getMethod());
    if (isGzipped && !requestTypeSupported) {
        throw new IllegalStateException(request.getMethod()
                + " is not supports gzipped body of parameters."
                + " Only POST requests are currently supported.");
    }
    if (isGzipped && requestTypeSupported) {
        request = new GzippedInputStreamWrapper((HttpServletRequest) servletRequest);
    }
    chain.doFilter(request, response);

}

/**
 * @inheritDoc
 */
@Override
public final void destroy() {
}

/**
 * Wrapper class that detects if the request is gzipped and ungzipps it.
 */
final class GzippedInputStreamWrapper extends HttpServletRequestWrapper {
    /**
     * Default encoding that is used when post parameters are parsed.
     */
    public static final String DEFAULT_ENCODING = "ISO-8859-1";

    /**
     * Serialized bytes array that is a result of unzipping gzipped body.
     */
    private byte[] bytes;

    /**
     * Constructs a request object wrapping the given request.
     * In case if Content-Encoding contains "gzip" we wrap the input stream into byte array
     * to original input stream has nothing in it but hew wrapped input stream always returns
     * reproducible ungzipped input stream.
     *
     * @param request request which input stream will be wrapped.
     * @throws java.io.IOException when input stream reqtieval failed.
     */
    public GzippedInputStreamWrapper(final HttpServletRequest request) throws IOException {
        super(request);
        try {
            final InputStream in = new GZIPInputStream(request.getInputStream());
            bytes = ByteStreams.toByteArray(in);
        } catch (EOFException e) {
            bytes = new byte[0];
        }
    }


    /**
     * @return reproduceable input stream that is either equal to initial servlet input
     * stream(if it was not zipped) or returns unzipped input stream.
     * @throws IOException if fails.
     */
    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream sourceStream = new ByteArrayInputStream(bytes);
        return new ServletInputStream() {
            public int read() throws IOException {
                return sourceStream.read();
            }

            public void close() throws IOException {
                super.close();
                sourceStream.close();
            }
        };
    }

    /**
     * Need to override getParametersMap because we initially read the whole input stream and
     * servlet container won't have access to the input stream data.
     *
     * @return parsed parameters list. Parameters get parsed only when Content-Type
     * "application/x-www-form-urlencoded" is set.
     */
    @Override
    public Map getParameterMap() {
        String contentEncodingHeader = getHeader(HttpHeaders.CONTENT_TYPE);
        if (!Strings.isNullOrEmpty(contentEncodingHeader)
                && contentEncodingHeader.contains("application/x-www-form-urlencoded")) {
            Map params = new HashMap(super.getParameterMap());
            try {
                params.putAll(parseParams(new String(bytes)));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            return params;
        } else {
            return super.getParameterMap();
        }
    }

    /**
     * parses params from the byte input stream.
     *
     * @param body request body serialized to string.
     * @return parsed parameters map.
     * @throws UnsupportedEncodingException if encoding provided is not supported.
     */
    private Map<string, string[]=""> parseParams(final String body)
            throws UnsupportedEncodingException {
        String characterEncoding = getCharacterEncoding();
        if (null == characterEncoding) {
            characterEncoding = DEFAULT_ENCODING;
        }
        final Multimap<string, string=""> parameters = ArrayListMultimap.create();
        for (String pair : body.split("&")) {
            if (Strings.isNullOrEmpty(pair)) {
                continue;
            }
            int idx = pair.indexOf("=");

            String key = null;
            if (idx > 0) {
                key = URLDecoder.decode(pair.substring(0, idx), characterEncoding);
            } else {
                key = pair;
            }
            String value = null;
            if (idx > 0 && pair.length() > idx + 1) {
                value = URLDecoder.decode(pair.substring(idx + 1), characterEncoding);
            } else {
                value = null;
            }
            parameters.put(key, value);
        }
        return Maps.transformValues(parameters.asMap(),
                new Function<collection<string>, String[]>() {
                    @Nullable
                    @Override
                    public String[] apply(final Collection<string> input) {
                        return Iterables.toArray(input, String.class);
                    }
                });
    }
}
</string></collection<string></string,></string,>

 stowns09 мая 2018 г., 19:32
Мне пришлось добавить charset = utf-8 в мой заголовок типа контента по запросу, и тогда это работало прекрасно!'Content-Type' : 'application/json; charset=utf-8'

Ваш ответ на вопрос