2121import static org .junit .Assert .assertNull ;
2222import static org .junit .Assert .assertTrue ;
2323import static org .junit .Assert .fail ;
24+ import static org .mockserver .model .Header .header ;
25+ import static org .mockserver .model .HttpForward .forward ;
26+ import static org .mockserver .model .HttpRequest .request ;
27+ import static org .mockserver .model .HttpResponse .response ;
2428
29+ import com .google .api .client .http .GenericUrl ;
2530import com .google .api .client .http .HttpRequestFactory ;
2631import com .google .api .client .http .HttpResponseException ;
32+ import com .google .api .client .http .HttpTransport ;
2733import com .google .api .client .http .LowLevelHttpResponse ;
2834import com .google .api .client .json .JsonFactory ;
2935import com .google .api .client .util .GenericData ;
5359import org .junit .BeforeClass ;
5460import org .junit .Test ;
5561
62+ import org .mockserver .integration .ClientAndServer ;
63+ import org .mockserver .model .HttpForward .Scheme ;
64+ import org .mockserver .socket .PortFactory ;
65+
5666public class ApacheHttp2TransportIT {
5767 private static FirebaseApp app ;
5868 private static final GoogleCredentials MOCK_CREDENTIALS = new MockGoogleCredentials ("test_token" );
5969 private static final ImmutableMap <String , Object > payload =
6070 ImmutableMap .<String , Object >of ("foo" , "bar" );
6171
62- // Sets a 5 second delay before server response to simulate a slow network that
72+ // Sets a 5 second delay before server response to simulate a slow network that
6373 // results in a read timeout.
6474 private static final String DELAY_URL = "https://nghttp2.org/httpbin/delay/5" ;
6575 private static final String GET_URL = "https://nghttp2.org/httpbin/get" ;
@@ -69,9 +79,13 @@ public class ApacheHttp2TransportIT {
6979 private static Socket fillerSocket ;
7080 private static int port ;
7181
82+ private static ClientAndServer mockProxy ;
83+ private static ClientAndServer mockServer ;
84+
7285 @ BeforeClass
7386 public static void setUpClass () throws IOException {
74- // Start server socket with a backlog queue of 1 and a automatically assigned port
87+ // Start server socket with a backlog queue of 1 and a automatically assigned
88+ // port
7589 serverSocket = new ServerSocket (0 , 1 );
7690 port = serverSocket .getLocalPort ();
7791 // Fill the backlog queue to force socket to ignore future connections
@@ -89,14 +103,26 @@ public static void cleanUpClass() throws IOException {
89103 }
90104 }
91105
92-
93106 @ After
94107 public void cleanup () {
95108 if (app != null ) {
96109 app .delete ();
97110 }
111+
112+ if (mockProxy != null && mockProxy .isRunning ()) {
113+ mockProxy .close ();
114+ }
115+
116+ if (mockServer != null && mockServer .isRunning ()) {
117+ mockServer .close ();
118+ }
119+
120+ System .clearProperty ("http.proxyHost" );
121+ System .clearProperty ("http.proxyPort" );
122+ System .clearProperty ("https.proxyHost" );
123+ System .clearProperty ("https.proxyPort" );
98124 }
99-
125+
100126 @ Test (timeout = 10_000L )
101127 public void testUnauthorizedGetRequest () throws FirebaseException {
102128 ErrorHandlingHttpClient <FirebaseException > httpClient = getHttpClient (false );
@@ -115,7 +141,7 @@ public void testUnauthorizedPostRequest() throws FirebaseException {
115141
116142 @ Test (timeout = 10_000L )
117143 public void testConnectTimeoutAuthorizedGet () throws FirebaseException {
118- app = FirebaseApp .initializeApp (FirebaseOptions .builder ()
144+ app = FirebaseApp .initializeApp (FirebaseOptions .builder ()
119145 .setCredentials (MOCK_CREDENTIALS )
120146 .setConnectTimeout (100 )
121147 .build (), "test-app" );
@@ -270,6 +296,77 @@ public void process(
270296 assertTrue ("Expected to have called our test interceptor" , interceptorCalled .get ());
271297 }
272298
299+ @ Test (timeout = 10_000L )
300+ public void testVerifyProxyIsRespected () {
301+ try {
302+ System .setProperty ("https.proxyHost" , "localhost" );
303+ System .setProperty ("https.proxyPort" , "8080" );
304+
305+ HttpTransport transport = new ApacheHttp2Transport ();
306+ transport .createRequestFactory ().buildGetRequest (new GenericUrl (GET_URL )).execute ();
307+ fail ("No exception thrown for HTTP error response" );
308+ } catch (IOException e ) {
309+ assertEquals ("Connection exception in request" , e .getMessage ());
310+ assertTrue (e .getCause ().getMessage ().contains ("localhost:8080" ));
311+ }
312+ }
313+
314+ @ Test (timeout = 10_000L )
315+ public void testProxyMockHttp () throws Exception {
316+ // Start MockServer
317+ mockProxy = ClientAndServer .startClientAndServer (PortFactory .findFreePort ());
318+ mockServer = ClientAndServer .startClientAndServer (PortFactory .findFreePort ());
319+
320+ System .setProperty ("http.proxyHost" , "localhost" );
321+ System .setProperty ("http.proxyPort" , mockProxy .getPort ().toString ());
322+
323+ // Configure proxy to receieve requests and forward them to a mock destination
324+ // server
325+ mockProxy
326+ .when (
327+ request ())
328+ .forward (
329+ forward ()
330+ .withHost ("localhost" )
331+ .withPort (mockServer .getPort ())
332+ .withScheme (Scheme .HTTP ));
333+
334+ // Configure server to listen and respond
335+ mockServer
336+ .when (
337+ request ())
338+ .respond (
339+ response ()
340+ .withStatusCode (200 )
341+ .withBody ("Expected server response" ));
342+
343+ // Send a request through the proxy
344+ app = FirebaseApp .initializeApp (FirebaseOptions .builder ()
345+ .setCredentials (MOCK_CREDENTIALS )
346+ .setWriteTimeout (100 )
347+ .build (), "test-app" );
348+ ErrorHandlingHttpClient <FirebaseException > httpClient = getHttpClient (true , app );
349+ HttpRequestInfo request = HttpRequestInfo .buildGetRequest ("http://www.google.com" );
350+ IncomingHttpResponse response = httpClient .send (request );
351+
352+ // Verify that the proxy received request with destination host
353+ mockProxy .verify (
354+ request ()
355+ .withMethod ("GET" )
356+ .withPath ("/" )
357+ .withHeader (header ("Host" , "www.google.com" )));
358+
359+ // Verify the forwarded request is received by the server
360+ mockServer .verify (
361+ request ()
362+ .withMethod ("GET" )
363+ .withPath ("/" ));
364+
365+ // Verify response
366+ assertEquals (200 , response .getStatusCode ());
367+ assertEquals (response .getContent (), "Expected server response" );
368+ }
369+
273370 private static ErrorHandlingHttpClient <FirebaseException > getHttpClient (boolean authorized ,
274371 FirebaseApp app ) {
275372 HttpRequestFactory requestFactory ;
@@ -285,12 +382,11 @@ private static ErrorHandlingHttpClient<FirebaseException> getHttpClient(boolean
285382
286383 private static ErrorHandlingHttpClient <FirebaseException > getHttpClient (boolean authorized ) {
287384 app = FirebaseApp .initializeApp (FirebaseOptions .builder ()
288- .setCredentials (MOCK_CREDENTIALS )
289- .build (), "test-app" );
385+ .setCredentials (MOCK_CREDENTIALS )
386+ .build (), "test-app" );
290387 return getHttpClient (authorized , app );
291388 }
292389
293-
294390 private static class TestHttpErrorHandler implements HttpErrorHandler <FirebaseException > {
295391 @ Override
296392 public FirebaseException handleIOException (IOException e ) {
0 commit comments