Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,6 @@ public class BrotliInputStreamFactory implements InputStreamFactory {
*/
public static final String ENCODING = "br";

@Override
public String getContentEncoding() {
return ENCODING;
}

/**
* Default instance of {@link BrotliInputStreamFactory}.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,6 @@ public class DeflateInputStreamFactory implements InputStreamFactory {
*/
public static final String ENCODING = "deflate";

@Override
public String getContentEncoding() {
return ENCODING;
}

/**
* Default instance of {@link DeflateInputStreamFactory}.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,6 @@ public class GZIPInputStreamFactory implements InputStreamFactory {
*/
public static final String ENCODING = "gzip";

@Override
public String getContentEncoding() {
return ENCODING;
}

/**
* Default instance of {@link GZIPInputStreamFactory}.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,21 +38,4 @@ public interface InputStreamFactory {

InputStream create(InputStream inputStream) throws IOException;

/**
* Returns the canonical {@code Content-Encoding} token handled by this
* factory (for example {@code "gzip"}, {@code "deflate"}, {@code "br"}).
* <p>
* Implementations that do <strong>not</strong> represent a HTTP
* content-decoder should simply inherit the default implementation,
* which returns an empty string.
*
* @return the lower-case encoding token, or an empty string when the
* factory is not intended for HTTP content-decoding
*
* @since 5.6
*/
default String getContentEncoding() {
return "";
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ final class CommonsCompressDecoderFactory implements InputStreamFactory {
this.encoding = encoding.toLowerCase(Locale.ROOT);
}

@Override
public String getContentEncoding() {
return encoding;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,6 @@ public String token() {
* @return the matching enum constant, or {@code null} if none
*/
public static ContentCoding fromToken(final String token) {
return TOKEN_LOOKUP.get(
token == null ? null : token.toLowerCase(Locale.ROOT)
);
return token != null ? TOKEN_LOOKUP.get(token.toLowerCase(Locale.ROOT)) : null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,14 @@

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.zip.GZIPInputStream;

import org.apache.hc.client5.http.classic.ExecChain;
import org.apache.hc.client5.http.classic.ExecChainHandler;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.entity.DecompressingEntity;
import org.apache.hc.client5.http.entity.DeflateInputStream;
import org.apache.hc.client5.http.entity.InputStreamFactory;
import org.apache.hc.client5.http.entity.compress.ContentCoding;
import org.apache.hc.client5.http.entity.compress.ContentDecoderRegistry;
Expand All @@ -60,7 +57,6 @@
import org.apache.hc.core5.http.message.MessageSupport;
import org.apache.hc.core5.http.message.ParserCursor;
import org.apache.hc.core5.util.Args;
import org.brotli.dec.BrotliInputStream;

/**
* Request execution handler in the classic request execution chain
Expand All @@ -81,68 +77,40 @@ public final class ContentCompressionExec implements ExecChainHandler {
private final Lookup<InputStreamFactory> decoderRegistry;
private final boolean ignoreUnknown;

private static final Map<ContentCoding, InputStreamFactory> DECODERS = ContentDecoderRegistry.getRegistry();

/**
* Pre-built list of all supported tokens (plus X-GZIP alias) for
* the Accept-Encoding header, to avoid reconstructing it every time.
*/
private static final List<String> DEFAULT_ACCEPT_ENCODINGS;
static {
final List<String> tmp = new ArrayList<>(DECODERS.size() + 1);
for (final ContentCoding coding : DECODERS.keySet()) {
tmp.add(coding.token());
}
// add x-gzip alias if gzip is present
if (DECODERS.containsKey(ContentCoding.GZIP)) {
tmp.add(ContentCoding.X_GZIP.token());
}
DEFAULT_ACCEPT_ENCODINGS = Collections.unmodifiableList(tmp);
}

public ContentCompressionExec(
final List<String> acceptEncoding,
final Lookup<InputStreamFactory> decoderRegistry,
final boolean ignoreUnknown) {

final List<String> encodingsHeader = acceptEncoding != null ? acceptEncoding : DEFAULT_ACCEPT_ENCODINGS;

this.acceptEncoding = MessageSupport.headerOfTokens(HttpHeaders.ACCEPT_ENCODING, encodingsHeader);

if (decoderRegistry != null) {
this.decoderRegistry = decoderRegistry;
} else {
final RegistryBuilder<InputStreamFactory> builder = RegistryBuilder.create();
DECODERS.forEach((coding, factory) ->
builder.register(coding.token(), factory));
// register the x-gzip alias again
if (DECODERS.containsKey(ContentCoding.GZIP)) {
builder.register(ContentCoding.X_GZIP.token(), DECODERS.get(ContentCoding.GZIP));
}
this.decoderRegistry = builder.build();
}

this.acceptEncoding = MessageSupport.headerOfTokens(HttpHeaders.ACCEPT_ENCODING,
Args.notEmpty(acceptEncoding, "Encoding list"));
this.decoderRegistry = Args.notNull(decoderRegistry, "Decoder register");
this.ignoreUnknown = ignoreUnknown;
}

public ContentCompressionExec(final boolean ignoreUnknown) {
this(null, null, ignoreUnknown);
final Map<ContentCoding, InputStreamFactory> decoderMap = ContentDecoderRegistry.getRegistry();
final RegistryBuilder<InputStreamFactory> builder = RegistryBuilder.create();
final List<String> acceptEncodingList = new ArrayList<>(decoderMap.size() + 1);
decoderMap.forEach((coding, factory) -> {
acceptEncodingList.add(coding.token());
builder.register(coding.token(), factory);
});
// register the x-gzip alias again
if (decoderMap.containsKey(ContentCoding.GZIP)) {
acceptEncodingList.add(ContentCoding.X_GZIP.token());
builder.register(ContentCoding.X_GZIP.token(), decoderMap.get(ContentCoding.GZIP));
}
this.acceptEncoding = MessageSupport.headerOfTokens(HttpHeaders.ACCEPT_ENCODING, acceptEncodingList);
this.decoderRegistry = builder.build();
this.ignoreUnknown = ignoreUnknown;
}

/**
* Handles {@code gzip} and {@code deflate} compressed entities by using the following
* decoders:
* <ul>
* <li>gzip - see {@link GZIPInputStream}</li>
* <li>deflate - see {@link DeflateInputStream}</li>
* <li>brotli - see {@link BrotliInputStream}</li>
* </ul>
*/
public ContentCompressionExec() {
this(null, null, true);
this(true);
}


@Override
public ClassicHttpResponse execute(
final ClassicHttpRequest request,
Expand Down