Skip to content

Commit 975241f

Browse files
gerdriesselmannGerd Riesselmann
andauthored
Allow disabling automatic decompression (#1871)
Adds new config option "isEnableAutomaticDecompression()" to config and builders. If set to true (default), behavior is as prior: Automatic decompression of compressed content by Netty HTTP client. If set to false, the content will not get decompressed automatically, but is passed to AsyncHandler as retrieved from the server. This is independent of config option isCompressionEnforced(). Added comments, to make this clear. We needed this feature to implement an efficient asynchronous proxy, which avoids overhead of decompressing content and compressing it again afterwards. --------- Co-authored-by: Gerd Riesselmann <[email protected]>
1 parent 7048c26 commit 975241f

File tree

6 files changed

+61
-61
lines changed

6 files changed

+61
-61
lines changed

client/src/main/java/org/asynchttpclient/AsyncHttpClientConfig.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,13 @@ public interface AsyncHttpClientConfig {
146146
*/
147147
boolean isCompressionEnforced();
148148

149+
/**
150+
* If automatic content decompression is enabled.
151+
*
152+
* @return true if content decompression is enabled
153+
*/
154+
boolean isEnableAutomaticDecompression();
155+
149156
/**
150157
* Return the {@link ThreadFactory} an {@link AsyncHttpClient} use for handling asynchronous response.
151158
*

client/src/main/java/org/asynchttpclient/DefaultAsyncHttpClientConfig.java

Lines changed: 33 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -44,62 +44,7 @@
4444
import java.util.concurrent.ThreadFactory;
4545
import java.util.function.Consumer;
4646

47-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultAcquireFreeChannelTimeout;
48-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultAggregateWebSocketFrameFragments;
49-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultChunkedFileChunkSize;
50-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultCompressionEnforced;
51-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultConnectTimeout;
52-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultConnectionPoolCleanerPeriod;
53-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultConnectionTtl;
54-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultDisableHttpsEndpointIdentificationAlgorithm;
55-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultDisableUrlEncodingForBoundRequests;
56-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultDisableZeroCopy;
57-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultEnableWebSocketCompression;
58-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultEnabledCipherSuites;
59-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultEnabledProtocols;
60-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultExpiredCookieEvictionDelay;
61-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultFilterInsecureCipherSuites;
62-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultFollowRedirect;
63-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultHandshakeTimeout;
64-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultHashedWheelTimerSize;
65-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultHashedWheelTimerTickDuration;
66-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultHttpClientCodecInitialBufferSize;
67-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultHttpClientCodecMaxChunkSize;
68-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultHttpClientCodecMaxHeaderSize;
69-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultHttpClientCodecMaxInitialLineLength;
70-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultIoThreadsCount;
71-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultKeepAlive;
72-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultKeepEncodingHeader;
73-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultMaxConnections;
74-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultMaxConnectionsPerHost;
75-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultMaxRedirects;
76-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultMaxRequestRetry;
77-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultPooledConnectionIdleTimeout;
78-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultReadTimeout;
79-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultRequestTimeout;
80-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultShutdownQuietPeriod;
81-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultShutdownTimeout;
82-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultSoKeepAlive;
83-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultSoLinger;
84-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultSoRcvBuf;
85-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultSoReuseAddress;
86-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultSoSndBuf;
87-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultSslSessionCacheSize;
88-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultSslSessionTimeout;
89-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultStrict302Handling;
90-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultTcpNoDelay;
91-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultThreadPoolName;
92-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultUseInsecureTrustManager;
93-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultUseLaxCookieEncoder;
94-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultUseNativeTransport;
95-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultUseOnlyEpollNativeTransport;
96-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultUseOpenSsl;
97-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultUseProxyProperties;
98-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultUseProxySelector;
99-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultUserAgent;
100-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultValidateResponseHeaders;
101-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultWebSocketMaxBufferSize;
102-
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultWebSocketMaxFrameSize;
47+
import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.*;
10348

10449
/**
10550
* Configuration class to use with a {@link AsyncHttpClient}. System property can be also used to configure this object default behavior by doing: <br>
@@ -114,6 +59,8 @@ public class DefaultAsyncHttpClientConfig implements AsyncHttpClientConfig {
11459
private final int maxRedirects;
11560
private final boolean strict302Handling;
11661
private final boolean compressionEnforced;
62+
63+
private final boolean enableAutomaticDecompression;
11764
private final String userAgent;
11865
private final Realm realm;
11966
private final int maxRequestRetry;
@@ -203,6 +150,7 @@ private DefaultAsyncHttpClientConfig(// http
203150
int maxRedirects,
204151
boolean strict302Handling,
205152
boolean compressionEnforced,
153+
boolean enableAutomaticDecompression,
206154
String userAgent,
207155
Realm realm,
208156
int maxRequestRetry,
@@ -292,6 +240,7 @@ private DefaultAsyncHttpClientConfig(// http
292240
this.maxRedirects = maxRedirects;
293241
this.strict302Handling = strict302Handling;
294242
this.compressionEnforced = compressionEnforced;
243+
this.enableAutomaticDecompression = enableAutomaticDecompression;
295244
this.userAgent = userAgent;
296245
this.realm = realm;
297246
this.maxRequestRetry = maxRequestRetry;
@@ -410,6 +359,11 @@ public boolean isCompressionEnforced() {
410359
return compressionEnforced;
411360
}
412361

362+
@Override
363+
public boolean isEnableAutomaticDecompression() {
364+
return enableAutomaticDecompression;
365+
}
366+
413367
@Override
414368
public String getUserAgent() {
415369
return userAgent;
@@ -777,6 +731,7 @@ public static class Builder {
777731
private int maxRedirects = defaultMaxRedirects();
778732
private boolean strict302Handling = defaultStrict302Handling();
779733
private boolean compressionEnforced = defaultCompressionEnforced();
734+
private boolean enableAutomaticDecompression = defaultEnableAutomaticDecompression();
780735
private String userAgent = defaultUserAgent();
781736
private Realm realm;
782737
private int maxRequestRetry = defaultMaxRequestRetry();
@@ -869,6 +824,7 @@ public Builder(AsyncHttpClientConfig config) {
869824
maxRedirects = config.getMaxRedirects();
870825
strict302Handling = config.isStrict302Handling();
871826
compressionEnforced = config.isCompressionEnforced();
827+
enableAutomaticDecompression = config.isEnableAutomaticDecompression();
872828
userAgent = config.getUserAgent();
873829
realm = config.getRealm();
874830
maxRequestRetry = config.getMaxRequestRetry();
@@ -963,11 +919,31 @@ public Builder setStrict302Handling(final boolean strict302Handling) {
963919
return this;
964920
}
965921

922+
/**
923+
* If true, AHC will add Accept-Encoding HTTP header to each request
924+
*
925+
* If false (default), AHC will either leave AcceptEncoding header as is
926+
* (if enableAutomaticDecompression is false) or will remove unsupported
927+
* algorithms (if enableAutomaticDecompression is true)
928+
*/
966929
public Builder setCompressionEnforced(boolean compressionEnforced) {
967930
this.compressionEnforced = compressionEnforced;
968931
return this;
969932
}
970933

934+
935+
/*
936+
* If true (default), AHC will add a Netty HttpContentDecompressor, so compressed
937+
* content will automatically get decompressed.
938+
*
939+
* If set to false, response will be delivered as is received. Decompression must
940+
* be done by calling code.
941+
*/
942+
public Builder setEnableAutomaticDecompression(boolean enable) {
943+
this.enableAutomaticDecompression = enable;
944+
return this;
945+
}
946+
971947
public Builder setUserAgent(String userAgent) {
972948
this.userAgent = userAgent;
973949
return this;
@@ -1390,6 +1366,7 @@ public DefaultAsyncHttpClientConfig build() {
13901366
maxRedirects,
13911367
strict302Handling,
13921368
compressionEnforced,
1369+
enableAutomaticDecompression,
13931370
userAgent,
13941371
realm,
13951372
maxRequestRetry,

client/src/main/java/org/asynchttpclient/config/AsyncHttpClientConfigDefaults.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ public final class AsyncHttpClientConfigDefaults {
3636
public static final String FOLLOW_REDIRECT_CONFIG = "followRedirect";
3737
public static final String MAX_REDIRECTS_CONFIG = "maxRedirects";
3838
public static final String COMPRESSION_ENFORCED_CONFIG = "compressionEnforced";
39+
40+
public static final String ENABLE_AUTOMATIC_DECOMPRESSION_CONFIG = "enableAutomaticDecompression";
3941
public static final String USER_AGENT_CONFIG = "userAgent";
4042
public static final String ENABLED_PROTOCOLS_CONFIG = "enabledProtocols";
4143
public static final String ENABLED_CIPHER_SUITES_CONFIG = "enabledCipherSuites";
@@ -147,6 +149,10 @@ public static boolean defaultCompressionEnforced() {
147149
return AsyncHttpClientConfigHelper.getAsyncHttpClientConfig().getBoolean(ASYNC_CLIENT_CONFIG_ROOT + COMPRESSION_ENFORCED_CONFIG);
148150
}
149151

152+
public static boolean defaultEnableAutomaticDecompression() {
153+
return AsyncHttpClientConfigHelper.getAsyncHttpClientConfig().getBoolean(ASYNC_CLIENT_CONFIG_ROOT + ENABLE_AUTOMATIC_DECOMPRESSION_CONFIG);
154+
}
155+
150156
public static String defaultUserAgent() {
151157
return AsyncHttpClientConfigHelper.getAsyncHttpClientConfig().getString(ASYNC_CLIENT_CONFIG_ROOT + USER_AGENT_CONFIG);
152158
}

client/src/main/java/org/asynchttpclient/netty/channel/ChannelManager.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,8 +244,14 @@ public void configureBootstraps(NettyRequestSender requestSender) {
244244
@Override
245245
protected void initChannel(Channel ch) {
246246
ChannelPipeline pipeline = ch.pipeline()
247-
.addLast(HTTP_CLIENT_CODEC, newHttpClientCodec())
248-
.addLast(INFLATER_HANDLER, newHttpContentDecompressor())
247+
.addLast(HTTP_CLIENT_CODEC, newHttpClientCodec());
248+
249+
if (config.isEnableAutomaticDecompression()) {
250+
// Add automatic decompression if desired
251+
pipeline = pipeline.addLast(INFLATER_HANDLER, newHttpContentDecompressor());
252+
}
253+
254+
pipeline = pipeline
249255
.addLast(CHUNKED_WRITER_HANDLER, new ChunkedWriteHandler())
250256
.addLast(AHC_HTTP_HANDLER, httpHandler);
251257

client/src/main/java/org/asynchttpclient/netty/request/NettyRequestFactory.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,13 @@ public NettyRequest newNettyRequest(Request request, boolean performConnectReque
172172

173173
String userDefinedAcceptEncoding = headers.get(ACCEPT_ENCODING);
174174
if (userDefinedAcceptEncoding != null) {
175-
// we don't support Brotly ATM
176-
headers.set(ACCEPT_ENCODING, filterOutBrotliFromAcceptEncoding(userDefinedAcceptEncoding));
177-
175+
if (config.isEnableAutomaticDecompression()) {
176+
// we don't support Brotli ATM, for automatic decompression.
177+
// For manual decompression by user, any encoding may suite, so leave untouched
178+
headers.set(ACCEPT_ENCODING, filterOutBrotliFromAcceptEncoding(userDefinedAcceptEncoding));
179+
}
178180
} else if (config.isCompressionEnforced()) {
181+
// Add Accept Encoding header if compression is enforced
179182
headers.set(ACCEPT_ENCODING, GZIP_DEFLATE);
180183
}
181184
}

client/src/main/resources/org/asynchttpclient/config/ahc-default.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ org.asynchttpclient.connectionTtl=-PT0.001S
1111
org.asynchttpclient.followRedirect=false
1212
org.asynchttpclient.maxRedirects=5
1313
org.asynchttpclient.compressionEnforced=false
14+
org.asynchttpclient.enableAutomaticDecompression=true
1415
org.asynchttpclient.userAgent=AHC/2.1
1516
org.asynchttpclient.enabledProtocols=TLSv1.2, TLSv1.1, TLSv1
1617
org.asynchttpclient.enabledCipherSuites=

0 commit comments

Comments
 (0)