Skip to content

Commit 48111be

Browse files
committed
Add some proxy tests that really involve a proxy and a target server
1 parent 482ec38 commit 48111be

File tree

2 files changed

+229
-0
lines changed

2 files changed

+229
-0
lines changed
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
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+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
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 io.netty.handler.codec.http.HttpHeaders.Names.*;
17+
import static org.asynchttpclient.Dsl.*;
18+
import static org.asynchttpclient.test.TestUtils.*;
19+
20+
import java.io.IOException;
21+
import java.util.concurrent.ExecutionException;
22+
import java.util.concurrent.Future;
23+
24+
import javax.servlet.http.HttpServletRequest;
25+
import javax.servlet.http.HttpServletResponse;
26+
27+
import org.asynchttpclient.Realm.AuthScheme;
28+
import org.asynchttpclient.test.EchoHandler;
29+
import org.eclipse.jetty.proxy.ConnectHandler;
30+
import org.eclipse.jetty.server.Server;
31+
import org.slf4j.Logger;
32+
import org.slf4j.LoggerFactory;
33+
import org.testng.Assert;
34+
import org.testng.annotations.AfterClass;
35+
import org.testng.annotations.BeforeClass;
36+
import org.testng.annotations.Test;
37+
38+
/**
39+
* Test that validates that when having an HTTP proxy and trying to access an HTTPS through the proxy the proxy credentials should be passed during the CONNECT request.
40+
*/
41+
public class BasicHttpProxyToHttpsTest {
42+
43+
private static final Logger LOGGER = LoggerFactory.getLogger(BasicHttpProxyToHttpsTest.class);
44+
45+
private int httpPort;
46+
private int proxyPort;
47+
48+
private Server httpServer;
49+
private Server proxy;
50+
51+
@BeforeClass(alwaysRun = true)
52+
public void setUpGlobal() throws Exception {
53+
54+
httpPort = findFreePort();
55+
proxyPort = findFreePort();
56+
57+
// HTTP server
58+
httpServer = newJettyHttpsServer(httpPort);
59+
httpServer.setHandler(new EchoHandler());
60+
httpServer.start();
61+
62+
proxy = new Server(proxyPort);
63+
ConnectHandler connectHandler = new ConnectHandler() {
64+
65+
@Override
66+
protected boolean handleAuthentication(HttpServletRequest request, HttpServletResponse response, String address) {
67+
String authorization = request.getHeader(PROXY_AUTHORIZATION);
68+
if (authorization == null) {
69+
response.setStatus(HttpServletResponse.SC_PROXY_AUTHENTICATION_REQUIRED);
70+
response.setHeader(PROXY_AUTHENTICATE, "Basic realm=\"Fake Realm\"");
71+
return false;
72+
} else if (authorization.equals("Basic am9obmRvZTpwYXNz")) {
73+
return true;
74+
}
75+
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
76+
return false;
77+
}
78+
};
79+
proxy.setHandler(connectHandler);
80+
proxy.start();
81+
82+
LOGGER.info("Local HTTP Server (" + httpPort + "), Proxy (" + proxyPort + ") started successfully");
83+
}
84+
85+
@AfterClass(alwaysRun = true)
86+
public void tearDownGlobal() throws Exception {
87+
httpServer.stop();
88+
proxy.stop();
89+
}
90+
91+
@Test
92+
public void nonPreemptyProxyAuthWithHttpsTarget() throws IOException, InterruptedException, ExecutionException {
93+
try (AsyncHttpClient client = asyncHttpClient(config().setAcceptAnyCertificate(true))) {
94+
String targetUrl = "https://localhost:" + httpPort + "/foo/bar";
95+
Request request = get(targetUrl)//
96+
.setProxyServer(proxyServer("127.0.0.1", proxyPort).setRealm(realm(AuthScheme.BASIC, "johndoe", "pass")))//
97+
// .setRealm(realm(AuthScheme.BASIC, "user", "passwd"))//
98+
.build();
99+
Future<Response> responseFuture = client.executeRequest(request);
100+
Response response = responseFuture.get();
101+
102+
Assert.assertEquals(response.getStatusCode(), HttpServletResponse.SC_OK);
103+
Assert.assertEquals("/foo/bar", response.getHeader("X-pathInfo"));
104+
}
105+
}
106+
}

0 commit comments

Comments
 (0)