459352 - AsyncMiddleManServlet should set "Host:" header correctly in proxy to remote request headers.

Fixed by removing the host header during the copy, so that HttpClient
correctly sets it by looking at the request target.
This commit is contained in:
Simone Bordet 2015-02-10 15:29:44 +01:00
parent 12e2f9e6c8
commit 4462e6a01e
3 changed files with 152 additions and 22 deletions

View File

@ -402,7 +402,7 @@ public abstract class AbstractProxyServlet extends HttpServlet
String headerName = headerNames.nextElement();
String lowerHeaderName = headerName.toLowerCase(Locale.ENGLISH);
if (_hostHeader != null && HttpHeader.HOST.is(headerName))
if (HttpHeader.HOST.is(headerName))
continue;
// Remove hop-by-hop headers.

View File

@ -907,24 +907,31 @@ public class ProxyServletTest
Assert.assertEquals(value1, cookies.get(0).getValue());
HttpClient client2 = prepareClient();
String value2 = "2";
ContentResponse response2 = client2.newRequest("localhost", serverConnector.getLocalPort())
.header(name, value2)
.timeout(5, TimeUnit.SECONDS)
.send();
Assert.assertEquals(200, response2.getStatus());
Assert.assertTrue(response2.getHeaders().containsKey(PROXIED_HEADER));
cookies = client2.getCookieStore().getCookies();
Assert.assertEquals(1, cookies.size());
Assert.assertEquals(name, cookies.get(0).getName());
Assert.assertEquals(value2, cookies.get(0).getValue());
try
{
String value2 = "2";
ContentResponse response2 = client2.newRequest("localhost", serverConnector.getLocalPort())
.header(name, value2)
.timeout(5, TimeUnit.SECONDS)
.send();
Assert.assertEquals(200, response2.getStatus());
Assert.assertTrue(response2.getHeaders().containsKey(PROXIED_HEADER));
cookies = client2.getCookieStore().getCookies();
Assert.assertEquals(1, cookies.size());
Assert.assertEquals(name, cookies.get(0).getName());
Assert.assertEquals(value2, cookies.get(0).getValue());
// Make a third request to be sure the proxy does not mix cookies
ContentResponse response3 = client.newRequest("localhost", serverConnector.getLocalPort())
.timeout(5, TimeUnit.SECONDS)
.send();
Assert.assertEquals(200, response3.getStatus());
Assert.assertTrue(response3.getHeaders().containsKey(PROXIED_HEADER));
// Make a third request to be sure the proxy does not mix cookies
ContentResponse response3 = client.newRequest("localhost", serverConnector.getLocalPort())
.timeout(5, TimeUnit.SECONDS)
.send();
Assert.assertEquals(200, response3.getStatus());
Assert.assertTrue(response3.getHeaders().containsKey(PROXIED_HEADER));
}
finally
{
client2.stop();
}
}
@Test
@ -967,7 +974,6 @@ public class ProxyServletTest
}
});
HttpClient client = prepareClient();
InputStreamResponseListener listener = new InputStreamResponseListener();
int port = serverConnector.getLocalPort();
client.newRequest("localhost", port).send(listener);
@ -1039,7 +1045,6 @@ public class ProxyServletTest
}
});
HttpClient client = prepareClient();
InputStreamResponseListener listener = new InputStreamResponseListener();
int port = serverConnector.getLocalPort();
client.newRequest("localhost", port).send(listener);
@ -1099,7 +1104,6 @@ public class ProxyServletTest
proxyContext.start();
prepareServer(new EmptyHttpServlet());
HttpClient client = prepareClient();
ContentResponse response = client.newRequest("localhost", serverConnector.getLocalPort()).send();
Assert.assertEquals(200, response.getStatus());
@ -1132,7 +1136,6 @@ public class ProxyServletTest
}
});
HttpClient client = prepareClient();
Request request = client.newRequest("localhost", serverConnector.getLocalPort());
for (Map.Entry<String, String> entry : hopHeaders.entrySet())
request.header(entry.getKey(), entry.getValue());

View File

@ -0,0 +1,127 @@
//
// ========================================================================
// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.proxy;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.toolchain.test.TestTracker;
import org.junit.After;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
public class ReverseProxyTest
{
@Rule
public final TestTracker tracker = new TestTracker();
private HttpClient client;
private Server proxy;
private ServerConnector proxyConnector;
private Server server;
private ServerConnector serverConnector;
private void startProxy() throws Exception
{
proxy = new Server();
HttpConfiguration configuration = new HttpConfiguration();
configuration.setSendDateHeader(false);
configuration.setSendServerVersion(false);
proxyConnector = new ServerConnector(proxy, new HttpConnectionFactory(configuration));
proxy.addConnector(proxyConnector);
ServletContextHandler proxyContext = new ServletContextHandler(proxy, "/", true, false);
ServletHolder proxyServletHolder = new ServletHolder(new AsyncMiddleManServlet()
{
@Override
protected String rewriteTarget(HttpServletRequest clientRequest)
{
StringBuilder builder = new StringBuilder();
builder.append(clientRequest.getScheme()).append("://localhost:");
builder.append(serverConnector.getLocalPort());
builder.append(clientRequest.getRequestURI());
String query = clientRequest.getQueryString();
if (query != null)
builder.append("?").append(query);
return builder.toString();
}
});
proxyContext.addServlet(proxyServletHolder, "/*");
proxy.start();
}
private void startServer(HttpServlet servlet) throws Exception
{
server = new Server();
serverConnector = new ServerConnector(server);
server.addConnector(serverConnector);
ServletContextHandler appCtx = new ServletContextHandler(server, "/", true, false);
ServletHolder appServletHolder = new ServletHolder(servlet);
appCtx.addServlet(appServletHolder, "/*");
server.start();
}
private void startClient() throws Exception
{
client = new HttpClient();
client.start();
}
@After
public void dispose() throws Exception
{
client.stop();
proxy.stop();
server.stop();
}
@Test
public void testClientHostHeaderUpdatedWhenSentToServer() throws Exception
{
startServer(new HttpServlet()
{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
Assert.assertEquals(request.getServerPort(), serverConnector.getLocalPort());
}
});
startProxy();
startClient();
ContentResponse response = client.newRequest("localhost", proxyConnector.getLocalPort()).send();
Assert.assertEquals(200, response.getStatus());
}
}