1 package com.atlassian.httpclient.apache.httpcomponents;
2
3 import com.atlassian.httpclient.api.BannedHostException;
4 import com.atlassian.httpclient.api.HttpClient;
5 import com.atlassian.httpclient.api.factory.HttpClientOptions;
6 import com.atlassian.httpclient.api.factory.ProxyOptions;
7 import com.google.common.collect.ImmutableList;
8 import com.sun.net.httpserver.HttpExchange;
9 import com.sun.net.httpserver.HttpHandler;
10 import com.sun.net.httpserver.HttpsConfigurator;
11 import com.sun.net.httpserver.HttpsServer;
12 import org.junit.After;
13 import org.junit.Before;
14 import org.junit.Rule;
15 import org.junit.Test;
16 import org.junit.rules.ExpectedException;
17
18 import javax.net.ssl.KeyManagerFactory;
19 import javax.net.ssl.SSLContext;
20 import javax.net.ssl.SSLHandshakeException;
21 import javax.net.ssl.TrustManagerFactory;
22 import java.io.IOException;
23 import java.io.OutputStream;
24 import java.net.InetSocketAddress;
25 import java.security.*;
26 import java.security.cert.CertificateException;
27
28 import static org.hamcrest.Matchers.isA;
29 import static org.junit.Assert.assertEquals;
30
31 public final class ApacheAsyncHttpClientTest {
32 private HttpsServer server;
33
34 private int port;
35
36 @Rule
37 public ExpectedException expectedException = ExpectedException.none();
38
39 @Before
40 public void setUp() throws Exception {
41 server = HttpsServer.create(new InetSocketAddress(0), 0);
42 port = server.getAddress().getPort();
43 server.setHttpsConfigurator(new HttpsConfigurator(getSslContext()));
44 server.createContext("/", new NoOpHandler());
45 server.setExecutor(null);
46 server.start();
47 }
48
49 @After
50 public void tearDown() throws Exception {
51 if (server != null) {
52 server.stop(3);
53 }
54 }
55
56 @Test
57 public void testGetWhenNotTrustingSelfSignedCertificates() {
58 HttpClientOptions options = new HttpClientOptions();
59 options.setTrustSelfSignedCertificates(false);
60 final HttpClient httpClient = new ApacheAsyncHttpClient<Void>("not-trusty-client", options);
61 try {
62 httpClient.newRequest(serverUrl()).get().claim();
63 } catch (RuntimeException expected) {
64 assertEquals(SSLHandshakeException.class, expected.getCause().getClass());
65 }
66 }
67
68 @Test
69 public void testGoingToAWSEndpoint() {
70 HttpClientOptions options = new HttpClientOptions();
71 options.setTrustSelfSignedCertificates(true);
72 options.setBlacklistedAddresses(ImmutableList.of("169.0.0.0/8"));
73
74 final HttpClient client = new ApacheAsyncHttpClient<>("trust-client", options);
75
76
77 client.newRequest(serverUrl()).get().claim();
78 expectedException.expectCause(isA(BannedHostException.class));
79 client.newRequest("http://169.254.169.254").get().claim();
80 }
81
82 @Test
83 public void testGetWhenTrustingSelfSignedCertificates() {
84 HttpClientOptions options = new HttpClientOptions();
85 options.setTrustSelfSignedCertificates(true);
86 final HttpClient httpClient = new ApacheAsyncHttpClient<Void>("trusty-client", options);
87 httpClient.newRequest(serverUrl()).get().claim();
88 }
89
90 @Test
91 public void testGetWithoutAProxy() {
92 HttpClientOptions options = new HttpClientOptions();
93 options.setProxyOptions(ProxyOptions.ProxyOptionsBuilder.create().withNoProxy().build());
94 options.setTrustSelfSignedCertificates(true);
95 final HttpClient httpClient = new ApacheAsyncHttpClient<Void>("trusty-client", options);
96 httpClient.newRequest(serverUrl()).get().claim();
97 }
98
99 private SSLContext getSslContext() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException, KeyManagementException {
100 char[] passphrase = "password".toCharArray();
101 KeyStore ks = KeyStore.getInstance("JKS");
102 ks.load(this.getClass().getResourceAsStream("/keystore.jks"), passphrase);
103
104 KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
105 kmf.init(ks, passphrase);
106
107 TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
108 tmf.init(ks);
109
110 SSLContext ssl = SSLContext.getInstance("TLS");
111 ssl.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
112 return ssl;
113 }
114
115 private final class NoOpHandler implements HttpHandler {
116 public void handle(HttpExchange t) throws IOException {
117 String response = "This is the response";
118 t.sendResponseHeaders(200, response.length());
119 OutputStream os = t.getResponseBody();
120 os.write(response.getBytes());
121 os.close();
122 }
123 }
124
125 private String serverUrl() {
126 return String.format("https://localhost:%d/", port);
127 }
128 }