Implemented CONNECT functionalities.
This commit is contained in:
parent
9abc3988fb
commit
3e4b7d7fb4
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,62 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 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.nio.ByteBuffer;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
|
||||
public class DownstreamConnection extends ProxyConnection
|
||||
{
|
||||
private final ByteBuffer buffer;
|
||||
|
||||
public DownstreamConnection(EndPoint endPoint, Executor executor, ByteBufferPool bufferPool, ConcurrentMap<String, Object> context, ConnectHandler connectHandler, ByteBuffer buffer)
|
||||
{
|
||||
super(endPoint, executor, bufferPool, context, connectHandler);
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpen()
|
||||
{
|
||||
super.onOpen();
|
||||
final int remaining = buffer.remaining();
|
||||
write(buffer, new Callback<Void>()
|
||||
{
|
||||
@Override
|
||||
public void completed(Void context)
|
||||
{
|
||||
LOG.debug("{} wrote initial {} bytes to server", DownstreamConnection.this, remaining);
|
||||
fillInterested();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(Void context, Throwable x)
|
||||
{
|
||||
LOG.debug(this + " failed to write initial " + remaining + " bytes to server", x);
|
||||
close();
|
||||
getConnection().close();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 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 java.nio.ByteBuffer;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.eclipse.jetty.io.AbstractConnection;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.ForkInvoker;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
public abstract class ProxyConnection extends AbstractConnection
|
||||
{
|
||||
protected static final Logger LOG = ConnectHandler.LOG;
|
||||
private final ForkInvoker<ByteBuffer> invoker = new ProxyForkInvoker();
|
||||
private final ByteBufferPool bufferPool;
|
||||
private final ConcurrentMap<String, Object> context;
|
||||
private final ConnectHandler connectHandler;
|
||||
private Connection connection;
|
||||
|
||||
protected ProxyConnection(EndPoint endp, Executor executor, ByteBufferPool bufferPool, ConcurrentMap<String, Object> context, ConnectHandler connectHandler)
|
||||
{
|
||||
super(endp, executor);
|
||||
this.bufferPool = bufferPool;
|
||||
this.context = context;
|
||||
this.connectHandler = connectHandler;
|
||||
}
|
||||
|
||||
public ByteBufferPool getByteBufferPool()
|
||||
{
|
||||
return bufferPool;
|
||||
}
|
||||
|
||||
public ConcurrentMap<String, Object> getContext()
|
||||
{
|
||||
return context;
|
||||
}
|
||||
|
||||
public ConnectHandler getConnectHandler()
|
||||
{
|
||||
return connectHandler;
|
||||
}
|
||||
|
||||
public Connection getConnection()
|
||||
{
|
||||
return connection;
|
||||
}
|
||||
|
||||
public void setConnection(Connection connection)
|
||||
{
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFillable()
|
||||
{
|
||||
ByteBuffer buffer = getByteBufferPool().acquire(getInputBufferSize(), true);
|
||||
fill(buffer);
|
||||
}
|
||||
|
||||
private void fill(final ByteBuffer buffer)
|
||||
{
|
||||
try
|
||||
{
|
||||
final int filled = connectHandler.read(getEndPoint(), buffer, getContext());
|
||||
LOG.debug("{} filled {} bytes", this, filled);
|
||||
if (filled > 0)
|
||||
{
|
||||
write(buffer, new Callback<Void>()
|
||||
{
|
||||
@Override
|
||||
public void completed(Void context)
|
||||
{
|
||||
LOG.debug("{} wrote {} bytes", this, filled);
|
||||
buffer.clear();
|
||||
invoker.invoke(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(Void context, Throwable x)
|
||||
{
|
||||
LOG.debug(this + " failed to write " + filled + " bytes", x);
|
||||
bufferPool.release(buffer);
|
||||
connection.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (filled == 0)
|
||||
{
|
||||
bufferPool.release(buffer);
|
||||
fillInterested();
|
||||
}
|
||||
else
|
||||
{
|
||||
bufferPool.release(buffer);
|
||||
connection.getEndPoint().shutdownOutput();
|
||||
}
|
||||
}
|
||||
catch (IOException x)
|
||||
{
|
||||
LOG.debug(this + " could not fill", x);
|
||||
bufferPool.release(buffer);
|
||||
close();
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
|
||||
protected void write(ByteBuffer buffer, Callback<Void> callback)
|
||||
{
|
||||
LOG.debug("{} writing {} bytes", this, buffer.remaining());
|
||||
connectHandler.write(getConnection().getEndPoint(), buffer, context, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s[l:%d<=>r:%d]",
|
||||
super.toString(),
|
||||
getEndPoint().getLocalAddress().getPort(),
|
||||
getEndPoint().getRemoteAddress().getPort());
|
||||
}
|
||||
|
||||
private class ProxyForkInvoker extends ForkInvoker<ByteBuffer>
|
||||
{
|
||||
private ProxyForkInvoker()
|
||||
{
|
||||
super(4);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fork(final ByteBuffer buffer)
|
||||
{
|
||||
getExecutor().execute(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
call(buffer);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void call(ByteBuffer buffer)
|
||||
{
|
||||
fill(buffer);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -124,11 +124,11 @@ public class ProxyServlet extends HttpServlet
|
|||
|
||||
String whiteList = config.getInitParameter("whiteList");
|
||||
if (whiteList != null)
|
||||
getWhitelistHosts().addAll(parseList(whiteList));
|
||||
getWhiteListHosts().addAll(parseList(whiteList));
|
||||
|
||||
String blackList = config.getInitParameter("blackList");
|
||||
if (blackList != null)
|
||||
getBlacklistHosts().addAll(parseList(blackList));
|
||||
getBlackListHosts().addAll(parseList(blackList));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -146,12 +146,12 @@ public class ProxyServlet extends HttpServlet
|
|||
this._timeout = timeout;
|
||||
}
|
||||
|
||||
public Set<String> getWhitelistHosts()
|
||||
public Set<String> getWhiteListHosts()
|
||||
{
|
||||
return _whiteList;
|
||||
}
|
||||
|
||||
public Set<String> getBlacklistHosts()
|
||||
public Set<String> getBlackListHosts()
|
||||
{
|
||||
return _blackList;
|
||||
}
|
||||
|
@ -313,12 +313,11 @@ public class ProxyServlet extends HttpServlet
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks the request hostname and path against whitelist and blacklist.
|
||||
* Checks the given {@code host} and {@code port} against whitelist and blacklist.
|
||||
*
|
||||
*
|
||||
* @param host host to check
|
||||
* @param host the host to check
|
||||
* @param port the port to check
|
||||
* @return true if request is allowed to be proxied
|
||||
* @return true if it is allowed to be proxy to the given host and port
|
||||
*/
|
||||
public boolean validateDestination(String host, int port)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 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.util.concurrent.Executor;
|
||||
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
|
||||
public class UpstreamConnection extends ProxyConnection
|
||||
{
|
||||
private ConnectHandler.ConnectContext connectContext;
|
||||
|
||||
public UpstreamConnection(EndPoint endPoint, Executor executor, ByteBufferPool bufferPool, ConnectHandler connectHandler, ConnectHandler.ConnectContext connectContext)
|
||||
{
|
||||
super(endPoint, executor, bufferPool, connectContext.getContext(), connectHandler);
|
||||
this.connectContext = connectContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpen()
|
||||
{
|
||||
super.onOpen();
|
||||
getConnectHandler().onConnectSuccess(connectContext, this);
|
||||
fillInterested();
|
||||
}
|
||||
}
|
|
@ -18,180 +18,62 @@
|
|||
|
||||
package org.eclipse.jetty.proxy;
|
||||
|
||||
/**
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.server.NetworkConnector;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.toolchain.test.http.SimpleHttpParser;
|
||||
import org.eclipse.jetty.toolchain.test.http.SimpleHttpResponse;
|
||||
import org.junit.After;
|
||||
|
||||
public abstract class AbstractConnectHandlerTest
|
||||
{
|
||||
// protected static Server server;
|
||||
// protected static Connector.NetConnector serverConnector;
|
||||
// protected static Server proxy;
|
||||
// protected static Connector proxyConnector;
|
||||
//
|
||||
// protected static void startServer(Connector.NetConnector connector, Handler handler) throws Exception
|
||||
// {
|
||||
// server = new Server();
|
||||
// serverConnector = connector;
|
||||
// server.addConnector(serverConnector);
|
||||
// server.setHandler(handler);
|
||||
// server.start();
|
||||
// }
|
||||
//
|
||||
// protected static void startProxy() throws Exception
|
||||
// {
|
||||
// proxy = new Server();
|
||||
// proxyConnector = new SelectChannelConnector();
|
||||
// proxy.addConnector(proxyConnector);
|
||||
// proxy.setHandler(new ConnectHandler());
|
||||
// proxy.start();
|
||||
// }
|
||||
//
|
||||
// @AfterClass
|
||||
// public static void stop() throws Exception
|
||||
// {
|
||||
// stopProxy();
|
||||
// stopServer();
|
||||
// }
|
||||
//
|
||||
// protected static void stopServer() throws Exception
|
||||
// {
|
||||
// server.stop();
|
||||
// server.join();
|
||||
// }
|
||||
//
|
||||
// protected static void stopProxy() throws Exception
|
||||
// {
|
||||
// proxy.stop();
|
||||
// proxy.join();
|
||||
// }
|
||||
//
|
||||
// protected Response readResponse(BufferedReader reader) throws IOException
|
||||
// {
|
||||
// // Simplified parser for HTTP responses
|
||||
// String line = reader.readLine();
|
||||
// if (line == null)
|
||||
// throw new EOFException();
|
||||
// Matcher responseLine = Pattern.compile("HTTP/1\\.1\\s+(\\d+)").matcher(line);
|
||||
// assertTrue(responseLine.lookingAt());
|
||||
// String code = responseLine.group(1);
|
||||
//
|
||||
// Map<String, String> headers = new LinkedHashMap<String, String>();
|
||||
// while ((line = reader.readLine()) != null)
|
||||
// {
|
||||
// if (line.trim().length() == 0)
|
||||
// break;
|
||||
//
|
||||
// Matcher header = Pattern.compile("([^:]+):\\s*(.*)").matcher(line);
|
||||
// assertTrue(header.lookingAt());
|
||||
// String headerName = header.group(1);
|
||||
// String headerValue = header.group(2);
|
||||
// headers.put(headerName.toLowerCase(), headerValue.toLowerCase());
|
||||
// }
|
||||
//
|
||||
// StringBuilder body;
|
||||
// if (headers.containsKey("content-length"))
|
||||
// {
|
||||
// int readLen = 0;
|
||||
// int length = Integer.parseInt(headers.get("content-length"));
|
||||
// body=new StringBuilder(length);
|
||||
// try
|
||||
// {
|
||||
// for (int i = 0; i < length; ++i)
|
||||
// {
|
||||
// char c = (char)reader.read();
|
||||
// body.append(c);
|
||||
// readLen++;
|
||||
//
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// catch (SocketTimeoutException e)
|
||||
// {
|
||||
// System.err.printf("Read %,d bytes (out of an expected %,d bytes)%n",readLen,length);
|
||||
// throw e;
|
||||
// }
|
||||
// }
|
||||
// else if ("chunked".equals(headers.get("transfer-encoding")))
|
||||
// {
|
||||
// body = new StringBuilder(64*1024);
|
||||
// while ((line = reader.readLine()) != null)
|
||||
// {
|
||||
// if ("0".equals(line))
|
||||
// {
|
||||
// line = reader.readLine();
|
||||
// assertEquals("", line);
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// try
|
||||
// {
|
||||
// Thread.sleep(5);
|
||||
// }
|
||||
// catch (InterruptedException e)
|
||||
// {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
//
|
||||
// int length = Integer.parseInt(line, 16);
|
||||
// for (int i = 0; i < length; ++i)
|
||||
// {
|
||||
// char c = (char)reader.read();
|
||||
// body.append(c);
|
||||
// }
|
||||
// line = reader.readLine();
|
||||
// assertEquals("", line);
|
||||
// }
|
||||
// }
|
||||
// else throw new IllegalStateException();
|
||||
//
|
||||
// return new Response(code, headers, body.toString().trim());
|
||||
// }
|
||||
//
|
||||
// protected Socket newSocket() throws IOException
|
||||
// {
|
||||
// Socket socket = new Socket("localhost", ((Connector.NetConnector)proxyConnector).getLocalPort());
|
||||
// socket.setSoTimeout(10000);
|
||||
// return socket;
|
||||
// }
|
||||
//
|
||||
// protected class Response
|
||||
// {
|
||||
// private final String code;
|
||||
// private final Map<String, String> headers;
|
||||
// private final String body;
|
||||
//
|
||||
// private Response(String code, Map<String, String> headers, String body)
|
||||
// {
|
||||
// this.code = code;
|
||||
// this.headers = headers;
|
||||
// this.body = body;
|
||||
// }
|
||||
//
|
||||
// public String getCode()
|
||||
// {
|
||||
// return code;
|
||||
// }
|
||||
//
|
||||
// public Map<String, String> getHeaders()
|
||||
// {
|
||||
// return headers;
|
||||
// }
|
||||
//
|
||||
// public String getBody()
|
||||
// {
|
||||
// return body;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String toString()
|
||||
// {
|
||||
// StringBuilder builder = new StringBuilder();
|
||||
// builder.append(code).append("\r\n");
|
||||
// for (Map.Entry<String, String> entry : headers.entrySet())
|
||||
// builder.append(entry.getKey()).append(": ").append(entry.getValue()).append("\r\n");
|
||||
// builder.append("\r\n");
|
||||
// builder.append(body);
|
||||
// return builder.toString();
|
||||
// }
|
||||
// }
|
||||
protected Server server;
|
||||
protected ServerConnector serverConnector;
|
||||
protected Server proxy;
|
||||
protected Connector proxyConnector;
|
||||
protected ConnectHandler connectHandler;
|
||||
|
||||
protected void prepareProxy() throws Exception
|
||||
{
|
||||
proxy = new Server();
|
||||
proxyConnector = new ServerConnector(proxy);
|
||||
proxy.addConnector(proxyConnector);
|
||||
connectHandler = new ConnectHandler();
|
||||
proxy.setHandler(connectHandler);
|
||||
proxy.start();
|
||||
}
|
||||
|
||||
@After
|
||||
public void dispose() throws Exception
|
||||
{
|
||||
disposeServer();
|
||||
disposeProxy();
|
||||
}
|
||||
|
||||
protected void disposeServer() throws Exception
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
|
||||
protected void disposeProxy() throws Exception
|
||||
{
|
||||
proxy.stop();
|
||||
}
|
||||
|
||||
protected SimpleHttpResponse readResponse(BufferedReader reader) throws IOException
|
||||
{
|
||||
return new SimpleHttpParser().readResponse(reader);
|
||||
}
|
||||
|
||||
protected Socket newSocket() throws IOException
|
||||
{
|
||||
Socket socket = new Socket("localhost", ((NetworkConnector)proxyConnector).getLocalPort());
|
||||
socket.setSoTimeout(5000);
|
||||
return socket;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,199 +18,184 @@
|
|||
|
||||
package org.eclipse.jetty.proxy;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.toolchain.test.http.SimpleHttpResponse;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
@Ignore
|
||||
public class ConnectHandlerSSLTest extends AbstractConnectHandlerTest
|
||||
{
|
||||
// @BeforeClass
|
||||
// public static void init() throws Exception
|
||||
// {
|
||||
// SslSelectChannelConnector connector = new SslSelectChannelConnector();
|
||||
// connector.setMaxIdleTime(3600000); // TODO remove
|
||||
//
|
||||
// String keyStorePath = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
|
||||
// SslContextFactory cf = connector.getSslContextFactory();
|
||||
// cf.setKeyStorePath(keyStorePath);
|
||||
// cf.setKeyStorePassword("storepwd");
|
||||
// cf.setKeyManagerPassword("keypwd");
|
||||
//
|
||||
// startServer(connector, new ServerHandler());
|
||||
// startProxy();
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void testGETRequest() throws Exception
|
||||
// {
|
||||
// String hostPort = "localhost:" + ((Connector.NetConnector)serverConnector).getLocalPort();
|
||||
// String request = "" +
|
||||
// "CONNECT " + hostPort + " HTTP/1.1\r\n" +
|
||||
// "Host: " + hostPort + "\r\n" +
|
||||
// "\r\n";
|
||||
// Socket socket = newSocket();
|
||||
// socket.setSoTimeout(3600000); // TODO remove
|
||||
// try
|
||||
// {
|
||||
// OutputStream output = socket.getOutputStream();
|
||||
// BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||
//
|
||||
// output.write(request.getBytes("UTF-8"));
|
||||
// output.flush();
|
||||
//
|
||||
// // Expect 200 OK from the CONNECT request
|
||||
// Response response = readResponse(input);
|
||||
// System.err.println(response);
|
||||
// assertEquals("200", response.getCode());
|
||||
//
|
||||
// // Be sure the buffered input does not have anything buffered
|
||||
// assertFalse(input.ready());
|
||||
//
|
||||
// // Upgrade the socket to SSL
|
||||
// SSLSocket sslSocket = wrapSocket(socket);
|
||||
// try
|
||||
// {
|
||||
// output = sslSocket.getOutputStream();
|
||||
// input = new BufferedReader(new InputStreamReader(sslSocket.getInputStream()));
|
||||
//
|
||||
// request =
|
||||
// "GET /echo HTTP/1.1\r\n" +
|
||||
// "Host: " + hostPort + "\r\n" +
|
||||
// "\r\n";
|
||||
// output.write(request.getBytes("UTF-8"));
|
||||
// output.flush();
|
||||
//
|
||||
// response = readResponse(input);
|
||||
// assertEquals("200", response.getCode());
|
||||
// assertEquals("GET /echo", response.getBody());
|
||||
// }
|
||||
// finally
|
||||
// {
|
||||
// sslSocket.close();
|
||||
// }
|
||||
// }
|
||||
// finally
|
||||
// {
|
||||
// socket.close();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void testPOSTRequests() throws Exception
|
||||
// {
|
||||
// String hostPort = "localhost:" + ((Connector.NetConnector)serverConnector).getLocalPort();
|
||||
// String request = "" +
|
||||
// "CONNECT " + hostPort + " HTTP/1.1\r\n" +
|
||||
// "Host: " + hostPort + "\r\n" +
|
||||
// "\r\n";
|
||||
// Socket socket = newSocket();
|
||||
// try
|
||||
// {
|
||||
// OutputStream output = socket.getOutputStream();
|
||||
// BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||
//
|
||||
// output.write(request.getBytes("UTF-8"));
|
||||
// output.flush();
|
||||
//
|
||||
// // Expect 200 OK from the CONNECT request
|
||||
// Response response = readResponse(input);
|
||||
// assertEquals("200", response.getCode());
|
||||
//
|
||||
// // Be sure the buffered input does not have anything buffered
|
||||
// assertFalse(input.ready());
|
||||
//
|
||||
// // Upgrade the socket to SSL
|
||||
// SSLSocket sslSocket = wrapSocket(socket);
|
||||
// try
|
||||
// {
|
||||
// output = sslSocket.getOutputStream();
|
||||
// input = new BufferedReader(new InputStreamReader(sslSocket.getInputStream()));
|
||||
//
|
||||
// for (int i = 0; i < 10; ++i)
|
||||
// {
|
||||
// request = "" +
|
||||
// "POST /echo?param=" + i + " HTTP/1.1\r\n" +
|
||||
// "Host: " + hostPort + "\r\n" +
|
||||
// "Content-Length: 5\r\n" +
|
||||
// "\r\n" +
|
||||
// "HELLO";
|
||||
// output.write(request.getBytes("UTF-8"));
|
||||
// output.flush();
|
||||
//
|
||||
// response = readResponse(input);
|
||||
// assertEquals("200", response.getCode());
|
||||
// assertEquals("POST /echo?param=" + i + "\r\nHELLO", response.getBody());
|
||||
// }
|
||||
// }
|
||||
// finally
|
||||
// {
|
||||
// sslSocket.close();
|
||||
// }
|
||||
// }
|
||||
// finally
|
||||
// {
|
||||
// socket.close();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private SSLSocket wrapSocket(Socket socket) throws Exception
|
||||
// {
|
||||
// SSLContext sslContext = SSLContext.getInstance("SSLv3");
|
||||
// sslContext.init(null, new TrustManager[]{new AlwaysTrustManager()}, new SecureRandom());
|
||||
// SSLSocketFactory socketFactory = sslContext.getSocketFactory();
|
||||
// SSLSocket sslSocket = (SSLSocket)socketFactory.createSocket(socket, socket.getInetAddress().getHostAddress(), socket.getPort(), true);
|
||||
// sslSocket.setUseClientMode(true);
|
||||
// sslSocket.startHandshake();
|
||||
// return sslSocket;
|
||||
// }
|
||||
//
|
||||
// private class AlwaysTrustManager implements X509TrustManager
|
||||
// {
|
||||
// public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException
|
||||
// {
|
||||
// }
|
||||
//
|
||||
// public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException
|
||||
// {
|
||||
// }
|
||||
//
|
||||
// public X509Certificate[] getAcceptedIssuers()
|
||||
// {
|
||||
// return new X509Certificate[]{};
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private static class ServerHandler extends AbstractHandler
|
||||
// {
|
||||
// public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException
|
||||
// {
|
||||
// request.setHandled(true);
|
||||
//
|
||||
// String uri = httpRequest.getRequestURI();
|
||||
// if ("/echo".equals(uri))
|
||||
// {
|
||||
// StringBuilder builder = new StringBuilder();
|
||||
// builder.append(httpRequest.getMethod()).append(" ").append(uri);
|
||||
// if (httpRequest.getQueryString() != null)
|
||||
// builder.append("?").append(httpRequest.getQueryString());
|
||||
//
|
||||
// ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
// InputStream input = httpRequest.getInputStream();
|
||||
// int read = -1;
|
||||
// while ((read = input.read()) >= 0)
|
||||
// baos.write(read);
|
||||
// baos.close();
|
||||
//
|
||||
// ServletOutputStream output = httpResponse.getOutputStream();
|
||||
// output.println(builder.toString());
|
||||
// output.write(baos.toByteArray());
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// throw new ServletException();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
private SslContextFactory sslContextFactory;
|
||||
|
||||
@Before
|
||||
public void prepare() throws Exception
|
||||
{
|
||||
sslContextFactory = new SslContextFactory();
|
||||
String keyStorePath = MavenTestingUtils.getTestResourceFile("keystore.jks").getAbsolutePath();
|
||||
sslContextFactory.setKeyStorePath(keyStorePath);
|
||||
sslContextFactory.setKeyStorePassword("storepwd");
|
||||
String trustStorePath = MavenTestingUtils.getTestResourceFile("truststore.jks").getAbsolutePath();
|
||||
sslContextFactory.setTrustStorePath(trustStorePath);
|
||||
sslContextFactory.setTrustStorePassword("storepwd");
|
||||
server = new Server();
|
||||
serverConnector = new ServerConnector(server, sslContextFactory);
|
||||
server.addConnector(serverConnector);
|
||||
server.setHandler(new ServerHandler());
|
||||
server.start();
|
||||
prepareProxy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGETRequest() throws Exception
|
||||
{
|
||||
String hostPort = "localhost:" + serverConnector.getLocalPort();
|
||||
String request = "" +
|
||||
"CONNECT " + hostPort + " HTTP/1.1\r\n" +
|
||||
"Host: " + hostPort + "\r\n" +
|
||||
"\r\n";
|
||||
try (Socket socket = newSocket())
|
||||
{
|
||||
OutputStream output = socket.getOutputStream();
|
||||
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||
|
||||
output.write(request.getBytes("UTF-8"));
|
||||
output.flush();
|
||||
|
||||
// Expect 200 OK from the CONNECT request
|
||||
SimpleHttpResponse response = readResponse(input);
|
||||
Assert.assertEquals("200", response.getCode());
|
||||
|
||||
// Be sure the buffered input does not have anything buffered
|
||||
Assert.assertFalse(input.ready());
|
||||
|
||||
// Upgrade the socket to SSL
|
||||
try (SSLSocket sslSocket = wrapSocket(socket))
|
||||
{
|
||||
output = sslSocket.getOutputStream();
|
||||
input = new BufferedReader(new InputStreamReader(sslSocket.getInputStream()));
|
||||
|
||||
request =
|
||||
"GET /echo HTTP/1.1\r\n" +
|
||||
"Host: " + hostPort + "\r\n" +
|
||||
"\r\n";
|
||||
output.write(request.getBytes("UTF-8"));
|
||||
output.flush();
|
||||
|
||||
response = readResponse(input);
|
||||
Assert.assertEquals("200", response.getCode());
|
||||
Assert.assertEquals("GET /echo", response.getBody());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPOSTRequests() throws Exception
|
||||
{
|
||||
String hostPort = "localhost:" + serverConnector.getLocalPort();
|
||||
String request = "" +
|
||||
"CONNECT " + hostPort + " HTTP/1.1\r\n" +
|
||||
"Host: " + hostPort + "\r\n" +
|
||||
"\r\n";
|
||||
try (Socket socket = newSocket())
|
||||
{
|
||||
OutputStream output = socket.getOutputStream();
|
||||
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||
|
||||
output.write(request.getBytes("UTF-8"));
|
||||
output.flush();
|
||||
|
||||
// Expect 200 OK from the CONNECT request
|
||||
SimpleHttpResponse response = readResponse(input);
|
||||
Assert.assertEquals("200", response.getCode());
|
||||
|
||||
// Be sure the buffered input does not have anything buffered
|
||||
Assert.assertFalse(input.ready());
|
||||
|
||||
// Upgrade the socket to SSL
|
||||
try (SSLSocket sslSocket = wrapSocket(socket))
|
||||
{
|
||||
output = sslSocket.getOutputStream();
|
||||
input = new BufferedReader(new InputStreamReader(sslSocket.getInputStream()));
|
||||
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
request = "" +
|
||||
"POST /echo?param=" + i + " HTTP/1.1\r\n" +
|
||||
"Host: " + hostPort + "\r\n" +
|
||||
"Content-Length: 5\r\n" +
|
||||
"\r\n" +
|
||||
"HELLO";
|
||||
output.write(request.getBytes("UTF-8"));
|
||||
output.flush();
|
||||
|
||||
response = readResponse(input);
|
||||
Assert.assertEquals("200", response.getCode());
|
||||
Assert.assertEquals("POST /echo?param=" + i + "\r\nHELLO", response.getBody());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private SSLSocket wrapSocket(Socket socket) throws Exception
|
||||
{
|
||||
SSLContext sslContext = sslContextFactory.getSslContext();
|
||||
SSLSocketFactory socketFactory = sslContext.getSocketFactory();
|
||||
SSLSocket sslSocket = (SSLSocket)socketFactory.createSocket(socket, socket.getInetAddress().getHostAddress(), socket.getPort(), true);
|
||||
sslSocket.setUseClientMode(true);
|
||||
sslSocket.startHandshake();
|
||||
return sslSocket;
|
||||
}
|
||||
|
||||
private static class ServerHandler extends AbstractHandler
|
||||
{
|
||||
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException
|
||||
{
|
||||
request.setHandled(true);
|
||||
|
||||
String uri = httpRequest.getRequestURI();
|
||||
if ("/echo".equals(uri))
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(httpRequest.getMethod()).append(" ").append(uri);
|
||||
if (httpRequest.getQueryString() != null)
|
||||
builder.append("?").append(httpRequest.getQueryString());
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
InputStream input = httpRequest.getInputStream();
|
||||
int read;
|
||||
while ((read = input.read()) >= 0)
|
||||
baos.write(read);
|
||||
baos.close();
|
||||
|
||||
ServletOutputStream output = httpResponse.getOutputStream();
|
||||
output.println(builder.toString());
|
||||
output.write(baos.toByteArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ServletException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,61 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 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;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
*/
|
||||
//@RunWith(MockitoJUnitRunner.class)
|
||||
public class ConnectHandlerUnitTest
|
||||
{
|
||||
// @Mock
|
||||
// private EndPoint endPoint;
|
||||
//
|
||||
// // TODO update for jetty-9
|
||||
// @Test
|
||||
// @Ignore
|
||||
// public void testPartialWritesWithNonFullBuffer() throws IOException
|
||||
// {
|
||||
// /*
|
||||
// ConnectHandler connectHandler = new ConnectHandler();
|
||||
// final byte[] bytes = "foo bar".getBytes();
|
||||
// Buffer buffer = new ByteArrayBuffer(bytes.length * 2);
|
||||
// buffer.put(bytes);
|
||||
// when(endPoint.flush(buffer)).thenAnswer(new Answer<Object>()
|
||||
// {
|
||||
// public Object answer(InvocationOnMock invocation)
|
||||
// {
|
||||
// Object[] args = invocation.getArguments();
|
||||
// Buffer buffer = (Buffer)args[0];
|
||||
// int skip = bytes.length/2;
|
||||
// buffer.skip(skip);
|
||||
// return skip;
|
||||
// }
|
||||
// });
|
||||
// when(endPoint.blockWritable(anyInt())).thenReturn(true);
|
||||
//
|
||||
// // method to test
|
||||
// connectHandler.write(endPoint,buffer,null);
|
||||
//
|
||||
// assertThat(buffer.length(),is(0));
|
||||
// */
|
||||
// }
|
||||
//
|
||||
//
|
||||
}
|
|
@ -536,12 +536,12 @@ public class ProxyServletTest
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testProxyWhitelist() throws Exception
|
||||
public void testProxyWhiteList() throws Exception
|
||||
{
|
||||
prepareProxy(new ProxyServlet());
|
||||
prepareServer(new EmptyHttpServlet());
|
||||
int port = serverConnector.getLocalPort();
|
||||
proxyServlet.getWhitelistHosts().add("127.0.0.1:" + port);
|
||||
proxyServlet.getWhiteListHosts().add("127.0.0.1:" + port);
|
||||
|
||||
// Try with the wrong host
|
||||
ContentResponse response = client.newRequest("localhost", port)
|
||||
|
@ -557,12 +557,12 @@ public class ProxyServletTest
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testProxyBlacklist() throws Exception
|
||||
public void testProxyBlackList() throws Exception
|
||||
{
|
||||
prepareProxy(new ProxyServlet());
|
||||
prepareServer(new EmptyHttpServlet());
|
||||
int port = serverConnector.getLocalPort();
|
||||
proxyServlet.getBlacklistHosts().add("localhost:" + port);
|
||||
proxyServlet.getBlackListHosts().add("localhost:" + port);
|
||||
|
||||
// Try with the wrong host
|
||||
ContentResponse response = client.newRequest("localhost", port)
|
||||
|
@ -744,6 +744,12 @@ public class ProxyServletTest
|
|||
Assert.assertTrue(response.getHeaders().containsKey(PROXIED_HEADER));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProxyAuthentication() throws Exception
|
||||
{
|
||||
// TODO:
|
||||
}
|
||||
|
||||
private static class EmptyHttpServlet extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue