Skip to content

Commit 06fc3c1

Browse files
committed
Introduce a config option to use LAX ClientCookieEncoder instead of the default STRICT, close AsyncHttpClient#1416
Motivation: Some users might not be ready to use the STRICT encoder if their server requires invalid cookie values (which is a security issue). Modification: Introduce a config option to switch from STRICT to LAX encoder. Result: Easier migration path when using invalid cookies
1 parent f91f40d commit 06fc3c1

File tree

5 files changed

+32
-4
lines changed

5 files changed

+32
-4
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,11 @@ public interface AsyncHttpClientConfig {
193193
*/
194194
boolean isDisableUrlEncodingForBoundRequests();
195195

196+
/**
197+
* @return true if AHC is to use a LAX cookie encoder, eg accept illegal chars in cookie value
198+
*/
199+
boolean isUseLaxCookieEncoder();
200+
196201
/**
197202
* In the case of a POST/Redirect/Get scenario where the server uses a 302 for the redirect, should AHC respond to the redirect with a GET or whatever the original method was.
198203
* Unless configured otherwise, for a 302, AHC, will use a GET for this case.

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ public class DefaultAsyncHttpClientConfig implements AsyncHttpClientConfig {
7171
private final Realm realm;
7272
private final int maxRequestRetry;
7373
private final boolean disableUrlEncodingForBoundRequests;
74+
private final boolean useLaxCookieEncoder;
7475
private final boolean disableZeroCopy;
7576
private final boolean keepEncodingHeader;
7677
private final ProxyServerSelector proxyServerSelector;
@@ -146,6 +147,7 @@ private DefaultAsyncHttpClientConfig(//
146147
Realm realm,//
147148
int maxRequestRetry,//
148149
boolean disableUrlEncodingForBoundRequests,//
150+
boolean useLaxCookieEncoder,//
149151
boolean disableZeroCopy,//
150152
boolean keepEncodingHeader,//
151153
ProxyServerSelector proxyServerSelector,//
@@ -222,6 +224,7 @@ private DefaultAsyncHttpClientConfig(//
222224
this.realm = realm;
223225
this.maxRequestRetry = maxRequestRetry;
224226
this.disableUrlEncodingForBoundRequests = disableUrlEncodingForBoundRequests;
227+
this.useLaxCookieEncoder = useLaxCookieEncoder;
225228
this.disableZeroCopy = disableZeroCopy;
226229
this.keepEncodingHeader = keepEncodingHeader;
227230
this.proxyServerSelector = proxyServerSelector;
@@ -336,6 +339,11 @@ public boolean isDisableUrlEncodingForBoundRequests() {
336339
return disableUrlEncodingForBoundRequests;
337340
}
338341

342+
@Override
343+
public boolean isUseLaxCookieEncoder() {
344+
return useLaxCookieEncoder;
345+
}
346+
339347
@Override
340348
public boolean isDisableZeroCopy() {
341349
return disableZeroCopy;
@@ -627,6 +635,7 @@ public static class Builder {
627635
private Realm realm;
628636
private int maxRequestRetry = defaultMaxRequestRetry();
629637
private boolean disableUrlEncodingForBoundRequests = defaultDisableUrlEncodingForBoundRequests();
638+
private boolean useLaxCookieEncoder = defaultUseLaxCookieEncoder();
630639
private boolean disableZeroCopy = defaultDisableZeroCopy();
631640
private boolean keepEncodingHeader = defaultKeepEncodingHeader();
632641
private ProxyServerSelector proxyServerSelector;
@@ -817,6 +826,11 @@ public Builder setDisableUrlEncodingForBoundRequests(boolean disableUrlEncodingF
817826
return this;
818827
}
819828

829+
public Builder setUseLaxCookieEncoder(boolean useLaxCookieEncoder) {
830+
this.useLaxCookieEncoder = useLaxCookieEncoder;
831+
return this;
832+
}
833+
820834
public Builder setDisableZeroCopy(boolean disableZeroCopy) {
821835
this.disableZeroCopy = disableZeroCopy;
822836
return this;
@@ -1147,6 +1161,7 @@ public DefaultAsyncHttpClientConfig build() {
11471161
realm, //
11481162
maxRequestRetry, //
11491163
disableUrlEncodingForBoundRequests, //
1164+
useLaxCookieEncoder, //
11501165
disableZeroCopy, //
11511166
keepEncodingHeader, //
11521167
resolveProxyServerSelector(), //

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ public static boolean defaultDisableUrlEncodingForBoundRequests() {
111111
return AsyncHttpClientConfigHelper.getAsyncHttpClientConfig().getBoolean(ASYNC_CLIENT_CONFIG_ROOT + "disableUrlEncodingForBoundRequests");
112112
}
113113

114+
public static boolean defaultUseLaxCookieEncoder() {
115+
return AsyncHttpClientConfigHelper.getAsyncHttpClientConfig().getBoolean(ASYNC_CLIENT_CONFIG_ROOT + "useLaxCookieEncoder");
116+
}
117+
114118
public static boolean defaultUseOpenSsl() {
115119
return AsyncHttpClientConfigHelper.getAsyncHttpClientConfig().getBoolean(ASYNC_CLIENT_CONFIG_ROOT + "useOpenSsl");
116120
}

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,11 @@ public final class NettyRequestFactory {
5757
public static final String GZIP_DEFLATE = HttpHeaderValues.GZIP + "," + HttpHeaderValues.DEFLATE;
5858

5959
private final AsyncHttpClientConfig config;
60+
private final ClientCookieEncoder cookieEncoder;
6061

6162
public NettyRequestFactory(AsyncHttpClientConfig config) {
6263
this.config = config;
64+
cookieEncoder = config.isUseLaxCookieEncoder() ? ClientCookieEncoder.LAX : ClientCookieEncoder.STRICT;
6365
}
6466

6567
private NettyBody body(Request request, boolean connect) {
@@ -107,7 +109,7 @@ private NettyBody body(Request request, boolean connect) {
107109
nettyBody = new NettyInputStreamBody(inStreamGenerator.getInputStream(), inStreamGenerator.getContentLength());
108110

109111
} else if (request.getBodyGenerator() instanceof ReactiveStreamsBodyGenerator) {
110-
ReactiveStreamsBodyGenerator reactiveStreamsBodyGenerator = (ReactiveStreamsBodyGenerator)request.getBodyGenerator();
112+
ReactiveStreamsBodyGenerator reactiveStreamsBodyGenerator = (ReactiveStreamsBodyGenerator) request.getBodyGenerator();
111113
nettyBody = new NettyReactiveStreamsBody(reactiveStreamsBodyGenerator.getPublisher(), reactiveStreamsBodyGenerator.getContentLength());
112114

113115
} else if (request.getBodyGenerator() != null) {
@@ -167,16 +169,17 @@ public NettyRequest newNettyRequest(Request request, boolean forceConnect, Proxy
167169
// assign headers as configured on request
168170
headers.set(request.getHeaders());
169171

170-
if (isNonEmpty(request.getCookies()))
171-
headers.set(COOKIE, ClientCookieEncoder.STRICT.encode(request.getCookies()));
172+
if (isNonEmpty(request.getCookies())) {
173+
headers.set(COOKIE, cookieEncoder.encode(request.getCookies()));
174+
}
172175

173176
String userDefinedAcceptEncoding = headers.get(ACCEPT_ENCODING);
174177
if (userDefinedAcceptEncoding != null) {
175178
// we don't support Brotly ATM
176179
if (userDefinedAcceptEncoding.endsWith(BROTLY_ACCEPT_ENCODING_SUFFIX)) {
177180
headers.set(ACCEPT_ENCODING, userDefinedAcceptEncoding.subSequence(0, userDefinedAcceptEncoding.length() - BROTLY_ACCEPT_ENCODING_SUFFIX.length()));
178181
}
179-
182+
180183
} else if (config.isCompressionEnforced()) {
181184
headers.set(ACCEPT_ENCODING, GZIP_DEFLATE);
182185
}

client/src/main/resources/ahc-default.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ org.asynchttpclient.strict302Handling=false
2121
org.asynchttpclient.keepAlive=true
2222
org.asynchttpclient.maxRequestRetry=5
2323
org.asynchttpclient.disableUrlEncodingForBoundRequests=false
24+
org.asynchttpclient.useLaxCookieEncoder=false
2425
org.asynchttpclient.removeQueryParamOnRedirect=true
2526
org.asynchttpclient.useOpenSsl=false
2627
org.asynchttpclient.useInsecureTrustManager=false

0 commit comments

Comments
 (0)