1
+ /*
2
+ * Copyright (c) 2016 AsyncHttpClient Project. All rights reserved.
3
+ *
4
+ * This program is licensed to you under the Apache License Version 2.0,
5
+ * and you may not use this file except in compliance with the Apache License Version 2.0.
6
+ * You may obtain a copy of the Apache License Version 2.0 at
7
+ * http://www.apache.org/licenses/LICENSE-2.0.
8
+ *
9
+ * Unless required by applicable law or agreed to in writing,
10
+ * software distributed under the Apache License Version 2.0 is distributed on an
11
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
13
+ */
14
+ package org .asynchttpclient ;
15
+
16
+ import static org .asynchttpclient .Dsl .*;
17
+ import static org .asynchttpclient .test .TestUtils .*;
18
+ import static io .netty .handler .codec .http .HttpHeaders .Names .*;
19
+
20
+ import java .io .IOException ;
21
+ import java .util .concurrent .ExecutionException ;
22
+ import java .util .concurrent .Future ;
23
+
24
+ import javax .servlet .ServletException ;
25
+ import javax .servlet .ServletRequest ;
26
+ import javax .servlet .ServletResponse ;
27
+ import javax .servlet .http .HttpServletRequest ;
28
+ import javax .servlet .http .HttpServletResponse ;
29
+
30
+ import org .asynchttpclient .Realm .AuthScheme ;
31
+ import org .asynchttpclient .test .EchoHandler ;
32
+ import org .eclipse .jetty .proxy .AsyncProxyServlet ;
33
+ import org .eclipse .jetty .server .Server ;
34
+ import org .eclipse .jetty .servlet .ServletHandler ;
35
+ import org .eclipse .jetty .servlet .ServletHolder ;
36
+ import org .slf4j .Logger ;
37
+ import org .slf4j .LoggerFactory ;
38
+ import org .testng .Assert ;
39
+ import org .testng .annotations .AfterClass ;
40
+ import org .testng .annotations .BeforeClass ;
41
+ import org .testng .annotations .Test ;
42
+
43
+ /**
44
+ * Test that validates that when having an HTTP proxy and trying to access an HTTP through the proxy the proxy credentials should be passed after it gets a 407 response.
45
+ */
46
+ public class BasicHttpProxyToHttpTest {
47
+
48
+ private static final Logger LOGGER = LoggerFactory .getLogger (BasicHttpProxyToHttpTest .class );
49
+
50
+ private int httpPort ;
51
+ private int proxyPort ;
52
+
53
+ private Server httpServer ;
54
+ private Server proxy ;
55
+
56
+ @ SuppressWarnings ("serial" )
57
+ public static class BasicAuthProxyServlet extends AsyncProxyServlet {
58
+
59
+ @ Override
60
+ public void service (ServletRequest req , ServletResponse res ) throws ServletException , IOException {
61
+ LOGGER .debug (">>> got a request !" );
62
+
63
+ HttpServletRequest httpReq = (HttpServletRequest ) req ;
64
+ HttpServletResponse httpRes = (HttpServletResponse ) res ;
65
+
66
+ String authorization = httpReq .getHeader (PROXY_AUTHORIZATION );
67
+ if (authorization == null ) {
68
+ httpRes .setStatus (HttpServletResponse .SC_PROXY_AUTHENTICATION_REQUIRED );
69
+ httpRes .setHeader (PROXY_AUTHENTICATE , "Basic realm=\" Fake Realm\" " );
70
+ httpRes .getOutputStream ().flush ();
71
+
72
+ } else if (authorization .equals ("Basic am9obmRvZTpwYXNz" )) {
73
+ super .service (req , res );
74
+
75
+ } else {
76
+ httpRes .setStatus (HttpServletResponse .SC_UNAUTHORIZED );
77
+ httpRes .getOutputStream ().flush ();
78
+ }
79
+ }
80
+ }
81
+
82
+ @ BeforeClass (alwaysRun = true )
83
+ public void setUpGlobal () throws Exception {
84
+
85
+ httpPort = findFreePort ();
86
+ proxyPort = findFreePort ();
87
+
88
+ httpServer = newJettyHttpServer (httpPort );
89
+ httpServer .setHandler (new EchoHandler ());
90
+ httpServer .start ();
91
+
92
+ proxy = new Server (proxyPort );
93
+ ServletHandler servletHandler = new ServletHandler ();
94
+ ServletHolder servletHolder = servletHandler .addServletWithMapping (BasicAuthProxyServlet .class , "/*" );
95
+ servletHolder .setInitParameter ("maxThreads" , "5" );
96
+ proxy .setHandler (servletHandler );
97
+ proxy .start ();
98
+
99
+ LOGGER .info ("Local HTTP Server (" + httpPort + "), Proxy (" + proxyPort + ") started successfully" );
100
+ }
101
+
102
+ @ AfterClass (alwaysRun = true )
103
+ public void tearDownGlobal () throws Exception {
104
+ httpServer .stop ();
105
+ proxy .stop ();
106
+ }
107
+
108
+ @ Test
109
+ public void nonPreemptyProxyAuthWithPlainHttpTarget () throws IOException , InterruptedException , ExecutionException {
110
+ try (AsyncHttpClient client = asyncHttpClient ()) {
111
+ String targetUrl = "http://localhost:" + httpPort + "/foo/bar" ;
112
+ Request request = get (targetUrl )//
113
+ .setProxyServer (proxyServer ("127.0.0.1" , proxyPort ).setRealm (realm (AuthScheme .BASIC , "johndoe" , "pass" )))//
114
+ //.setRealm(realm(AuthScheme.BASIC, "user", "passwd"))//
115
+ .build ();
116
+ Future <Response > responseFuture = client .executeRequest (request );
117
+ Response response = responseFuture .get ();
118
+
119
+ Assert .assertEquals (response .getStatusCode (), HttpServletResponse .SC_OK );
120
+ Assert .assertEquals ("/foo/bar" , response .getHeader ("X-pathInfo" ));
121
+ }
122
+ }
123
+ }
0 commit comments