@Override
    protected HttpObject filter(HttpObject obj) {
        if (obj instanceof HttpHeaders) {
            final HttpHeaders headers = (HttpHeaders) obj;

            // Skip informational headers.
            final String status = headers.get(HttpHeaderNames.STATUS);
            if (ArmeriaHttpUtil.isInformational(status)) {
                return obj;
            }

            if (headersReceived) {
                // Trailers, no modification.
                return obj;
            }

            if (status == null) {
                // Follow-up headers for informational headers, no modification.
                return obj;
            }

            headersReceived = true;

            final String contentEncoding = headers.get(HttpHeaderNames.CONTENT_ENCODING);
            if (contentEncoding != null) {
                final StreamDecoderFactory decoderFactory =
                        availableDecoders.get(Ascii.toLowerCase(contentEncoding));
                if (decoderFactory != null) {
                    decoder = decoderFactory.newDecoder(ctx.alloc(),
                                                        Ints.saturatedCast(ctx.maxResponseLength()));
                } else {
                    // The server returned an encoding that this response doesn't support.
                    // This shouldn't happen normally since we set Accept-Encoding.
                    if (strictContentEncoding) {
                        Exceptions.throwUnsafely(
                                new UnsupportedEncodingException("encoding: " + contentEncoding));
                    } else {
                        // Decoding is skipped.
                    }
                }
            }
            if (decoder != null) {
                // As the compressed content should be decoded, Content-Encoding and Content-Length
                // header are no longer valid.
                return headers.toBuilder()
                              .removeAndThen(HttpHeaderNames.CONTENT_ENCODING)
                              .removeAndThen(HttpHeaderNames.CONTENT_LENGTH)
                              .build();
            } else {
                return headers;
            }
        }

        assert obj instanceof HttpData;

        return decoder != null ? decoder.decode((HttpData) obj) : obj;
    }
A {@link FilteredHttpResponse} that applies HTTP decoding to {@link HttpObject}s as they are published.
core/src/main/java/com/linecorp/armeria/internal/common/encoding/DefaultHttpDecodedResponse.java