@ -37,10 +37,10 @@ import java.security.cert.X509Certificate;
import java.time.Duration ;
import java.util.Arrays ;
import java.util.Collection ;
import java.util.Collections ;
import java.util.Date ;
import java.util.EnumSet ;
import java.util.HashMap ;
import java.util.LinkedHashMap ;
import java.util.List ;
import java.util.Locale ;
import java.util.Map ;
@ -51,6 +51,7 @@ import java.util.concurrent.Callable;
import java.util.concurrent.Future ;
import java.util.concurrent.FutureTask ;
import java.util.concurrent.RunnableFuture ;
import java.util.concurrent.TimeUnit ;
import java.util.concurrent.atomic.AtomicBoolean ;
import java.util.concurrent.atomic.AtomicReference ;
import java.util.function.Supplier ;
@ -78,20 +79,23 @@ import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse ;
import jakarta.servlet.http.HttpSession ;
import org.apache.catalina.webresources.TomcatURLStreamHandlerFactory ;
import org.apache.http.HttpResponse ;
import org.apache.http.client.HttpClient ;
import org.apache.http.client.entity.InputStreamFactory ;
import org.apache.http.client.methods.HttpGet ;
import org.apache.http.client.protocol.HttpClientContext ;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory ;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy ;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler ;
import org.apache.http.impl.client.HttpClientBuilder ;
import org.apache.http.impl.client.HttpClients ;
import org.apache.http.impl.client.StandardHttpRequestRetryHandler ;
import org.apache.http.protocol.HttpContext ;
import org.apache.http.ssl.SSLContextBuilder ;
import org.apache.http.ssl.TrustStrategy ;
import org.apache.hc.client5.http.classic.HttpClient ;
import org.apache.hc.client5.http.classic.methods.HttpGet ;
import org.apache.hc.client5.http.entity.InputStreamFactory ;
import org.apache.hc.client5.http.impl.DefaultHttpRequestRetryStrategy ;
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder ;
import org.apache.hc.client5.http.impl.classic.HttpClients ;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager ;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder ;
import org.apache.hc.client5.http.protocol.HttpClientContext ;
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory ;
import org.apache.hc.client5.http.ssl.TrustSelfSignedStrategy ;
import org.apache.hc.core5.http.HttpResponse ;
import org.apache.hc.core5.http.io.HttpClientResponseHandler ;
import org.apache.hc.core5.http.protocol.HttpContext ;
import org.apache.hc.core5.ssl.SSLContextBuilder ;
import org.apache.hc.core5.ssl.TrustStrategy ;
import org.apache.hc.core5.util.TimeValue ;
import org.apache.jasper.EmbeddedServletOptions ;
import org.apache.jasper.servlet.JspServlet ;
import org.assertj.core.api.ThrowableAssert.ThrowingCallable ;
@ -178,23 +182,7 @@ public abstract class AbstractServletWebServerFactoryTests {
private final HttpClientContext httpClientContext = HttpClientContext . create ( ) ;
private final Supplier < HttpClientBuilder > httpClientBuilder = ( ) - > HttpClients . custom ( )
. setRetryHandler ( new StandardHttpRequestRetryHandler ( 10 , false ) {
@Override
public boolean retryRequest ( IOException exception , int executionCount , HttpContext context ) {
boolean retry = super . retryRequest ( exception , executionCount , context ) ;
if ( retry ) {
try {
Thread . sleep ( 200 ) ;
}
catch ( InterruptedException ex ) {
Thread . currentThread ( ) . interrupt ( ) ;
}
}
return retry ;
}
} ) ;
. setRetryStrategy ( new DefaultHttpRequestRetryStrategy ( 10 , TimeValue . of ( 200 , TimeUnit . MILLISECONDS ) ) ) ;
@AfterEach
void tearDown ( ) {
@ -446,8 +434,7 @@ public abstract class AbstractServletWebServerFactoryTests {
this . webServer . start ( ) ;
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory (
new SSLContextBuilder ( ) . loadTrustMaterial ( null , new TrustSelfSignedStrategy ( ) ) . build ( ) ) ;
HttpClient httpClient = HttpClients . custom ( ) . setSSLSocketFactory ( socketFactory ) . build ( ) ;
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory ( httpClient ) ;
HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory ( socketFactory ) ;
assertThatExceptionOfType ( SSLException . class )
. isThrownBy ( ( ) - > getResponse ( getLocalUrl ( "https" , "/hello" ) , requestFactory ) ) ;
}
@ -460,8 +447,7 @@ public abstract class AbstractServletWebServerFactoryTests {
this . webServer . start ( ) ;
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory (
new SSLContextBuilder ( ) . loadTrustMaterial ( null , new TrustSelfSignedStrategy ( ) ) . build ( ) ) ;
HttpClient httpClient = HttpClients . custom ( ) . setSSLSocketFactory ( socketFactory ) . build ( ) ;
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory ( httpClient ) ;
HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory ( socketFactory ) ;
assertThat ( getResponse ( getLocalUrl ( "https" , "/hello" ) , requestFactory ) ) . contains ( "scheme=https" ) ;
}
@ -476,8 +462,9 @@ public abstract class AbstractServletWebServerFactoryTests {
this . webServer . start ( ) ;
TrustStrategy trustStrategy = new SerialNumberValidatingTrustSelfSignedStrategy ( "3a3aaec8" ) ;
SSLContext sslContext = new SSLContextBuilder ( ) . loadTrustMaterial ( null , trustStrategy ) . build ( ) ;
HttpClient httpClient = HttpClients . custom ( ) . setSSLSocketFactory ( new SSLConnectionSocketFactory ( sslContext ) )
. build ( ) ;
PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder . create ( )
. setSSLSocketFactory ( new SSLConnectionSocketFactory ( sslContext ) ) . build ( ) ;
HttpClient httpClient = HttpClients . custom ( ) . setConnectionManager ( connectionManager ) . build ( ) ;
String response = getResponse ( getLocalUrl ( "https" , "/hello" ) ,
new HttpComponentsClientHttpRequestFactory ( httpClient ) ) ;
assertThat ( response ) . contains ( "scheme=https" ) ;
@ -506,7 +493,9 @@ public abstract class AbstractServletWebServerFactoryTests {
this . webServer . start ( ) ;
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory (
new SSLContextBuilder ( ) . loadTrustMaterial ( null , new TrustSelfSignedStrategy ( ) ) . build ( ) ) ;
HttpClient httpClient = this . httpClientBuilder . get ( ) . setSSLSocketFactory ( socketFactory ) . build ( ) ;
PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder . create ( )
. setSSLSocketFactory ( socketFactory ) . build ( ) ;
HttpClient httpClient = this . httpClientBuilder . get ( ) . setConnectionManager ( connectionManager ) . build ( ) ;
ClientHttpResponse response = getClientResponse ( getLocalUrl ( "https" , "/hello" ) , HttpMethod . GET ,
new HttpComponentsClientHttpRequestFactory ( httpClient ) ) ;
assertThat ( response . getHeaders ( ) . get ( "Server" ) ) . isNullOrEmpty ( ) ;
@ -521,8 +510,9 @@ public abstract class AbstractServletWebServerFactoryTests {
this . webServer . start ( ) ;
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory (
new SSLContextBuilder ( ) . loadTrustMaterial ( null , new TrustSelfSignedStrategy ( ) ) . build ( ) ) ;
HttpClient httpClient = this . httpClientBuilder . get ( ) . setSSLSocketFactory ( socketFactory )
. setRetryHandler ( new DefaultHttpRequestRetryHandler ( 10 , false ) ) . build ( ) ;
PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder . create ( )
. setSSLSocketFactory ( socketFactory ) . build ( ) ;
HttpClient httpClient = this . httpClientBuilder . get ( ) . setConnectionManager ( connectionManager ) . build ( ) ;
ClientHttpResponse response = getClientResponse ( getLocalUrl ( "https" , "/hello" ) , HttpMethod . GET ,
new HttpComponentsClientHttpRequestFactory ( httpClient ) ) ;
assertThat ( response . getHeaders ( ) . get ( "Server" ) ) . containsExactly ( "MyServer" ) ;
@ -536,8 +526,7 @@ public abstract class AbstractServletWebServerFactoryTests {
this . webServer . start ( ) ;
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory (
new SSLContextBuilder ( ) . loadTrustMaterial ( null , new TrustSelfSignedStrategy ( ) ) . build ( ) ) ;
HttpClient httpClient = this . httpClientBuilder . get ( ) . setSSLSocketFactory ( socketFactory ) . build ( ) ;
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory ( httpClient ) ;
HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory ( socketFactory ) ;
assertThat ( getResponse ( getLocalUrl ( "https" , "/test.txt" ) , requestFactory ) ) . isEqualTo ( "test" ) ;
}
@ -553,8 +542,7 @@ public abstract class AbstractServletWebServerFactoryTests {
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory (
new SSLContextBuilder ( ) . loadTrustMaterial ( null , new TrustSelfSignedStrategy ( ) )
. loadKeyMaterial ( keyStore , "secret" . toCharArray ( ) ) . build ( ) ) ;
HttpClient httpClient = this . httpClientBuilder . get ( ) . setSSLSocketFactory ( socketFactory ) . build ( ) ;
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory ( httpClient ) ;
HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory ( socketFactory ) ;
assertThat ( getResponse ( getLocalUrl ( "https" , "/test.txt" ) , requestFactory ) ) . isEqualTo ( "test" ) ;
}
@ -570,8 +558,7 @@ public abstract class AbstractServletWebServerFactoryTests {
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory (
new SSLContextBuilder ( ) . loadTrustMaterial ( null , new TrustSelfSignedStrategy ( ) )
. loadKeyMaterial ( keyStore , "secret" . toCharArray ( ) ) . build ( ) ) ;
HttpClient httpClient = this . httpClientBuilder . get ( ) . setSSLSocketFactory ( socketFactory ) . build ( ) ;
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory ( httpClient ) ;
HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory ( socketFactory ) ;
assertThat ( getResponse ( getLocalUrl ( "https" , "/test.txt" ) , requestFactory ) ) . isEqualTo ( "test" ) ;
}
@ -588,8 +575,7 @@ public abstract class AbstractServletWebServerFactoryTests {
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory (
new SSLContextBuilder ( ) . loadTrustMaterial ( null , new TrustSelfSignedStrategy ( ) )
. loadKeyMaterial ( keyStore , "password" . toCharArray ( ) ) . build ( ) ) ;
HttpClient httpClient = this . httpClientBuilder . get ( ) . setSSLSocketFactory ( socketFactory ) . build ( ) ;
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory ( httpClient ) ;
HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory ( socketFactory ) ;
assertThat ( getResponse ( getLocalUrl ( "https" , "/test.txt" ) , requestFactory ) ) . isEqualTo ( "test" ) ;
}
@ -602,8 +588,7 @@ public abstract class AbstractServletWebServerFactoryTests {
this . webServer . start ( ) ;
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory (
new SSLContextBuilder ( ) . loadTrustMaterial ( null , new TrustSelfSignedStrategy ( ) ) . build ( ) ) ;
HttpClient httpClient = this . httpClientBuilder . get ( ) . setSSLSocketFactory ( socketFactory ) . build ( ) ;
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory ( httpClient ) ;
HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory ( socketFactory ) ;
String localUrl = getLocalUrl ( "https" , "/test.txt" ) ;
assertThatIOException ( ) . isThrownBy ( ( ) - > getResponse ( localUrl , requestFactory ) ) ;
}
@ -621,8 +606,7 @@ public abstract class AbstractServletWebServerFactoryTests {
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory (
new SSLContextBuilder ( ) . loadTrustMaterial ( null , new TrustSelfSignedStrategy ( ) )
. loadKeyMaterial ( keyStore , "password" . toCharArray ( ) ) . build ( ) ) ;
HttpClient httpClient = this . httpClientBuilder . get ( ) . setSSLSocketFactory ( socketFactory ) . build ( ) ;
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory ( httpClient ) ;
HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory ( socketFactory ) ;
assertThat ( getResponse ( getLocalUrl ( "https" , "/test.txt" ) , requestFactory ) ) . isEqualTo ( "test" ) ;
}
@ -635,8 +619,7 @@ public abstract class AbstractServletWebServerFactoryTests {
this . webServer . start ( ) ;
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory (
new SSLContextBuilder ( ) . loadTrustMaterial ( null , new TrustSelfSignedStrategy ( ) ) . build ( ) ) ;
HttpClient httpClient = this . httpClientBuilder . get ( ) . setSSLSocketFactory ( socketFactory ) . build ( ) ;
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory ( httpClient ) ;
HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory ( socketFactory ) ;
assertThat ( getResponse ( getLocalUrl ( "https" , "/test.txt" ) , requestFactory ) ) . isEqualTo ( "test" ) ;
}
@ -659,8 +642,7 @@ public abstract class AbstractServletWebServerFactoryTests {
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory (
new SSLContextBuilder ( ) . loadTrustMaterial ( null , new TrustSelfSignedStrategy ( ) )
. loadKeyMaterial ( keyStore , "password" . toCharArray ( ) ) . build ( ) ) ;
HttpClient httpClient = this . httpClientBuilder . get ( ) . setSSLSocketFactory ( socketFactory ) . build ( ) ;
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory ( httpClient ) ;
HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory ( socketFactory ) ;
assertThat ( getResponse ( getLocalUrl ( "https" , "/test.txt" ) , requestFactory ) ) . isEqualTo ( "test" ) ;
then ( sslStoreProvider ) . should ( atLeastOnce ( ) ) . getKeyStore ( ) ;
then ( sslStoreProvider ) . should ( atLeastOnce ( ) ) . getTrustStore ( ) ;
@ -742,11 +724,19 @@ public abstract class AbstractServletWebServerFactoryTests {
this . webServer . start ( ) ;
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory (
new SSLContextBuilder ( ) . loadTrustMaterial ( null , new TrustSelfSignedStrategy ( ) ) . build ( ) ) ;
HttpClient httpClient = this . httpClientBuilder . get ( ) . setSSLSocketFactory ( socketFactory ) . build ( ) ;
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory ( httpClient ) ;
HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory ( socketFactory ) ;
assertThat ( getResponse ( getLocalUrl ( "https" , "/hello" ) , requestFactory ) ) . contains ( "scheme=https" ) ;
}
private HttpComponentsClientHttpRequestFactory createHttpComponentsRequestFactory (
SSLConnectionSocketFactory socketFactory ) {
PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder . create ( )
. setSSLSocketFactory ( socketFactory ) . build ( ) ;
HttpClient httpClient = this . httpClientBuilder . get ( ) . setConnectionManager ( connectionManager ) . build ( ) ;
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory ( httpClient ) ;
return requestFactory ;
}
private String getStoreType ( String keyStore ) {
return keyStore . endsWith ( ".p12" ) ? "pkcs12" : null ;
}
@ -938,7 +928,8 @@ public abstract class AbstractServletWebServerFactoryTests {
this . webServer = factory . getWebServer ( new ServletRegistrationBean < > ( new ExampleServlet ( false , true ) , "/hello" ) ) ;
this . webServer . start ( ) ;
TestGzipInputStreamFactory inputStreamFactory = new TestGzipInputStreamFactory ( ) ;
Map < String , InputStreamFactory > contentDecoderMap = Collections . singletonMap ( "gzip" , inputStreamFactory ) ;
LinkedHashMap < String , InputStreamFactory > contentDecoderMap = new LinkedHashMap < > ( ) ;
contentDecoderMap . put ( "gzip" , inputStreamFactory ) ;
getResponse ( getLocalUrl ( "/hello" ) , new HttpComponentsClientHttpRequestFactory (
this . httpClientBuilder . get ( ) . setContentDecoderRegistry ( contentDecoderMap ) . build ( ) ) ) ;
assertThat ( inputStreamFactory . wasCompressionUsed ( ) ) . isTrue ( ) ;
@ -1267,9 +1258,11 @@ public abstract class AbstractServletWebServerFactoryTests {
protected Future < Object > initiateGetRequest ( HttpClient httpClient , int port , String path ) {
RunnableFuture < Object > getRequest = new FutureTask < > ( ( ) - > {
try {
HttpResponse response = httpClient . execute ( new HttpGet ( "http://localhost:" + port + path ) ) ;
response . getEntity ( ) . getContent ( ) . close ( ) ;
return response ;
return httpClient . execute ( new HttpGet ( "http://localhost:" + port + path ) ,
( HttpClientResponseHandler < HttpResponse > ) ( response ) - > {
response . getEntity ( ) . getContent ( ) . close ( ) ;
return response ;
} ) ;
}
catch ( Exception ex ) {
return ex ;
@ -1306,7 +1299,8 @@ public abstract class AbstractServletWebServerFactoryTests {
HttpMethod method ) throws Exception {
String testContent = setUpFactoryForCompression ( contentSize , mimeTypes , excludedUserAgents ) ;
TestGzipInputStreamFactory inputStreamFactory = new TestGzipInputStreamFactory ( ) ;
Map < String , InputStreamFactory > contentDecoderMap = Collections . singletonMap ( "gzip" , inputStreamFactory ) ;
LinkedHashMap < String , InputStreamFactory > contentDecoderMap = new LinkedHashMap < > ( ) ;
contentDecoderMap . put ( "gzip" , inputStreamFactory ) ;
String response = getResponse ( getLocalUrl ( "/test.txt" ) , method ,
new HttpComponentsClientHttpRequestFactory ( HttpClientBuilder . create ( ) . setUserAgent ( "testUserAgent" )
. setContentDecoderRegistry ( contentDecoderMap ) . build ( ) ) ) ;