View Javadoc
1   /*
2    * The MIT License (MIT)
3    *
4    * Copyright (c) 2013-2026 The Coveralls Maven Plugin Project Contributors:
5    *     https://github.com/hazendaz/coveralls-maven-plugin/graphs/contributors
6    *
7    * Permission is hereby granted, free of charge, to any person obtaining a copy
8    * of this software and associated documentation files (the "Software"), to deal
9    * in the Software without restriction, including without limitation the rights
10   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11   * copies of the Software, and to permit persons to whom the Software is
12   * furnished to do so, subject to the following conditions:
13   *
14   * The above copyright notice and this permission notice shall be included in
15   * all copies or substantial portions of the Software.
16   *
17   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23   * THE SOFTWARE.
24   */
25  package org.eluder.coveralls.maven.plugin.httpclient;
26  
27  import com.github.tomakehurst.wiremock.client.WireMock;
28  import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
29  import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
30  
31  import java.io.IOException;
32  import java.net.URI;
33  import java.net.http.HttpRequest;
34  import java.net.http.HttpResponse;
35  
36  import org.apache.maven.settings.Proxy;
37  import org.junit.jupiter.api.Assertions;
38  import org.junit.jupiter.api.Test;
39  import org.junit.jupiter.api.extension.RegisterExtension;
40  
41  /**
42   * The Class HttpClientFactoryTest.
43   */
44  class HttpClientFactoryTest {
45  
46      /** The Constant PROXY_PORT. */
47      static final int PROXY_PORT = 9797;
48  
49      /** The Constant TARGET_PORT. */
50      static final int TARGET_PORT = 9696;
51  
52      /** The Constant TARGET_URL. */
53      static final String TARGET_URL = "http://localhost:" + HttpClientFactoryTest.TARGET_PORT;
54  
55      /** The Constant STRING_RESPONSE_HANDLER. */
56      static final HttpResponse.BodyHandler<String> STRING_RESPONSE_HANDLER = HttpResponse.BodyHandlers.ofString();
57  
58      /** The target server. */
59      @RegisterExtension
60      static WireMockExtension targetServer = WireMockExtension.newInstance()
61              .options(WireMockConfiguration.wireMockConfig().port(HttpClientFactoryTest.TARGET_PORT).dynamicHttpsPort())
62              .configureStaticDsl(true).build();
63  
64      /** The proxy server. */
65      @RegisterExtension
66      static WireMockExtension proxyServer = WireMockExtension.newInstance()
67              .options(WireMockConfiguration.wireMockConfig().port(HttpClientFactoryTest.PROXY_PORT).dynamicHttpsPort())
68              .configureStaticDsl(true).build();
69  
70      /**
71       * Simple request.
72       *
73       * @throws IOException
74       *             Signals that an I/O exception has occurred.
75       * @throws InterruptedException
76       *             the interrupted exception
77       */
78      @Test
79      void simpleRequest() throws IOException, InterruptedException {
80          HttpClientFactoryTest.targetServer.stubFor(
81                  WireMock.get(WireMock.urlMatching(".*")).willReturn(WireMock.aResponse().withBody("Hello World!")));
82  
83          final var client = new HttpClientFactory(HttpClientFactoryTest.TARGET_URL).create();
84          final var response = client.send(
85                  HttpRequest.newBuilder().uri(URI.create(HttpClientFactoryTest.TARGET_URL)).GET().build(),
86                  HttpClientFactoryTest.STRING_RESPONSE_HANDLER);
87  
88          Assertions.assertEquals("Hello World!", response.body());
89      }
90  
91      /**
92       * Un authorized proxy request.
93       *
94       * @throws IOException
95       *             Signals that an I/O exception has occurred.
96       * @throws InterruptedException
97       *             the interrupted exception
98       */
99      @Test
100     void unAuthorizedProxyRequest() throws IOException, InterruptedException {
101         HttpClientFactoryTest.targetServer.stubFor(
102                 WireMock.get(WireMock.urlMatching(".*")).willReturn(WireMock.aResponse().withBody("Hello World!")));
103 
104         HttpClientFactoryTest.proxyServer.stubFor(
105                 WireMock.get(WireMock.urlMatching(".*")).willReturn(WireMock.aResponse().withBody("Hello Proxy!")));
106 
107         final var proxy = new Proxy();
108         proxy.setHost("localhost");
109         proxy.setPort(HttpClientFactoryTest.PROXY_PORT);
110         proxy.setProtocol("http");
111 
112         final var client = new HttpClientFactory(HttpClientFactoryTest.TARGET_URL).proxy(proxy).create();
113         final var response = client.send(
114                 HttpRequest.newBuilder().uri(URI.create(HttpClientFactoryTest.TARGET_URL)).GET().build(),
115                 HttpClientFactoryTest.STRING_RESPONSE_HANDLER);
116 
117         Assertions.assertEquals("Hello Proxy!", response.body());
118     }
119 
120     /**
121      * Authorized proxy request.
122      *
123      * @throws IOException
124      *             Signals that an I/O exception has occurred.
125      * @throws InterruptedException
126      *             the interrupted exception
127      */
128     @Test
129     void authorizedProxyRequest() throws IOException, InterruptedException {
130         HttpClientFactoryTest.targetServer.stubFor(
131                 WireMock.get(WireMock.urlMatching(".*")).willReturn(WireMock.aResponse().withBody("Hello World!")));
132 
133         HttpClientFactoryTest.proxyServer.stubFor(WireMock.get(WireMock.urlMatching(".*"))
134                 .withHeader("Proxy-Authorization", WireMock.matching("Basic Zm9vOmJhcg=="))
135                 .willReturn(WireMock.aResponse().withBody("Hello Proxy!")).atPriority(1));
136         HttpClientFactoryTest.proxyServer.stubFor(WireMock.any(WireMock.urlMatching(".*"))
137                 .willReturn(WireMock.aResponse().withStatus(407).withHeader("Proxy-Authenticate", "Basic"))
138                 .atPriority(2));
139 
140         final var proxy = new Proxy();
141         proxy.setHost("localhost");
142         proxy.setPort(HttpClientFactoryTest.PROXY_PORT);
143         proxy.setProtocol("http");
144         proxy.setUsername("foo");
145         proxy.setPassword("bar");
146 
147         final var client = new HttpClientFactory(HttpClientFactoryTest.TARGET_URL).proxy(proxy).create();
148         final var response = client.send(
149                 HttpRequest.newBuilder().uri(URI.create(HttpClientFactoryTest.TARGET_URL)).GET().build(),
150                 HttpClientFactoryTest.STRING_RESPONSE_HANDLER);
151 
152         Assertions.assertEquals("Hello Proxy!", response.body());
153     }
154 
155     /**
156      * Non proxied host request.
157      *
158      * @throws IOException
159      *             Signals that an I/O exception has occurred.
160      * @throws InterruptedException
161      *             the interrupted exception
162      */
163     @Test
164     void nonProxiedHostRequest() throws IOException, InterruptedException {
165         HttpClientFactoryTest.targetServer.stubFor(
166                 WireMock.get(WireMock.urlMatching(".*")).willReturn(WireMock.aResponse().withBody("Hello World!")));
167 
168         HttpClientFactoryTest.proxyServer.stubFor(
169                 WireMock.get(WireMock.urlMatching(".*")).willReturn(WireMock.aResponse().withBody("Hello Proxy!")));
170 
171         final var proxy = new Proxy();
172         proxy.setHost("localhost");
173         proxy.setPort(HttpClientFactoryTest.PROXY_PORT);
174         proxy.setProtocol("http");
175         proxy.setNonProxyHosts("localhost|example.com");
176 
177         final var client = new HttpClientFactory(HttpClientFactoryTest.TARGET_URL).proxy(proxy).create();
178         final var response = client.send(
179                 HttpRequest.newBuilder().uri(URI.create(HttpClientFactoryTest.TARGET_URL)).GET().build(),
180                 HttpClientFactoryTest.STRING_RESPONSE_HANDLER);
181 
182         Assertions.assertEquals("Hello World!", response.body());
183     }
184 
185     /**
186      * Null proxy request (proxy method with null should be a no-op).
187      *
188      * @throws IOException
189      *             Signals that an I/O exception has occurred.
190      * @throws InterruptedException
191      *             the interrupted exception
192      */
193     @Test
194     void nullProxyRequest() throws IOException, InterruptedException {
195         HttpClientFactoryTest.targetServer.stubFor(
196                 WireMock.get(WireMock.urlMatching(".*")).willReturn(WireMock.aResponse().withBody("Hello World!")));
197 
198         final var client = new HttpClientFactory(HttpClientFactoryTest.TARGET_URL).proxy(null).create();
199         final var response = client.send(
200                 HttpRequest.newBuilder().uri(URI.create(HttpClientFactoryTest.TARGET_URL)).GET().build(),
201                 HttpClientFactoryTest.STRING_RESPONSE_HANDLER);
202 
203         Assertions.assertEquals("Hello World!", response.body());
204     }
205 
206 }