Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'jetty-server')
-rw-r--r--jetty-server/src/main/config/etc/jetty-http.xml4
-rw-r--r--jetty-server/src/main/config/etc/jetty-proxy-protocol-ssl.xml10
-rw-r--r--jetty-server/src/main/config/etc/jetty-proxy-protocol.xml10
-rw-r--r--jetty-server/src/main/config/modules/proxy-protocol-ssl.mod9
-rw-r--r--jetty-server/src/main/config/modules/proxy-protocol.mod9
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java41
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/ProxyConnectionFactory.java69
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/ServerConnectorTest.java48
8 files changed, 136 insertions, 64 deletions
diff --git a/jetty-server/src/main/config/etc/jetty-http.xml b/jetty-server/src/main/config/etc/jetty-http.xml
index 0cbc5a0871..ebeed5d1fc 100644
--- a/jetty-server/src/main/config/etc/jetty-http.xml
+++ b/jetty-server/src/main/config/etc/jetty-http.xml
@@ -26,10 +26,6 @@
<Arg name="selectors" type="int"><Property name="jetty.http.selectors" deprecated="http.selectors" default="-1"/></Arg>
<Arg name="factories">
<Array type="org.eclipse.jetty.server.ConnectionFactory">
- <!-- uncomment to support proxy protocol
- <Item>
- <New class="org.eclipse.jetty.server.ProxyConnectionFactory"/>
- </Item>-->
<Item>
<New class="org.eclipse.jetty.server.HttpConnectionFactory">
<Arg name="config"><Ref refid="httpConfig" /></Arg>
diff --git a/jetty-server/src/main/config/etc/jetty-proxy-protocol-ssl.xml b/jetty-server/src/main/config/etc/jetty-proxy-protocol-ssl.xml
new file mode 100644
index 0000000000..91452f2738
--- /dev/null
+++ b/jetty-server/src/main/config/etc/jetty-proxy-protocol-ssl.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
+
+<Configure id="sslConnector" class="org.eclipse.jetty.server.ServerConnector">
+ <Call name="addFirstConnectionFactory">
+ <Arg>
+ <New class="org.eclipse.jetty.server.ProxyConnectionFactory"/>
+ </Arg>
+ </Call>
+</Configure>
diff --git a/jetty-server/src/main/config/etc/jetty-proxy-protocol.xml b/jetty-server/src/main/config/etc/jetty-proxy-protocol.xml
new file mode 100644
index 0000000000..5169c4fddd
--- /dev/null
+++ b/jetty-server/src/main/config/etc/jetty-proxy-protocol.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
+
+<Configure id="httpConnector" class="org.eclipse.jetty.server.ServerConnector">
+ <Call name="addFirstConnectionFactory">
+ <Arg>
+ <New class="org.eclipse.jetty.server.ProxyConnectionFactory"/>
+ </Arg>
+ </Call>
+</Configure>
diff --git a/jetty-server/src/main/config/modules/proxy-protocol-ssl.mod b/jetty-server/src/main/config/modules/proxy-protocol-ssl.mod
new file mode 100644
index 0000000000..764d24b847
--- /dev/null
+++ b/jetty-server/src/main/config/modules/proxy-protocol-ssl.mod
@@ -0,0 +1,9 @@
+#
+# PROXY Protocol Module - SSL
+#
+
+[depend]
+ssl
+
+[xml]
+etc/jetty-proxy-protocol-ssl.xml
diff --git a/jetty-server/src/main/config/modules/proxy-protocol.mod b/jetty-server/src/main/config/modules/proxy-protocol.mod
new file mode 100644
index 0000000000..9df2700f4e
--- /dev/null
+++ b/jetty-server/src/main/config/modules/proxy-protocol.mod
@@ -0,0 +1,9 @@
+#
+# PROXY Protocol Module - HTTP
+#
+
+[depend]
+http
+
+[xml]
+etc/jetty-proxy-protocol.xml
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java
index f13aa1ad7e..bfd8206df9 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java
@@ -144,7 +144,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
private final Scheduler _scheduler;
private final ByteBufferPool _byteBufferPool;
private final Thread[] _acceptors;
- private final Set<EndPoint> _endpoints = Collections.newSetFromMap(new ConcurrentHashMap<EndPoint, Boolean>());
+ private final Set<EndPoint> _endpoints = Collections.newSetFromMap(new ConcurrentHashMap<>());
private final Set<EndPoint> _immutableEndPoints = Collections.unmodifiableSet(_endpoints);
private volatile CountDownLatch _stopping;
private long _idleTimeout = 30000;
@@ -191,7 +191,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
int cores = Runtime.getRuntime().availableProcessors();
if (acceptors < 0)
- acceptors=Math.max(1, Math.min(4,cores/8));
+ acceptors=Math.max(1, Math.min(4,cores/8));
if (acceptors > cores)
LOG.warn("Acceptors should be <= availableProcessors: " + this);
_acceptors = new Thread[acceptors];
@@ -303,7 +303,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
_stopping=null;
super.doStop();
-
+
for (Acceptor a : getBeans(Acceptor.class))
removeBean(a);
@@ -362,7 +362,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
{
synchronized (_factories)
{
- Set<ConnectionFactory> to_remove = new HashSet<ConnectionFactory>();
+ Set<ConnectionFactory> to_remove = new HashSet<>();
for (String key:factory.getProtocols())
{
key=StringUtil.asciiToLowerCase(key);
@@ -375,11 +375,11 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
}
_factories.put(key, factory);
}
-
+
// keep factories still referenced
for (ConnectionFactory f : _factories.values())
to_remove.remove(f);
-
+
// remove old factories
for (ConnectionFactory old: to_remove)
{
@@ -396,7 +396,20 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
LOG.debug("{} added {}", this, factory);
}
}
-
+
+ public void addFirstConnectionFactory(ConnectionFactory factory)
+ {
+ synchronized (_factories)
+ {
+ List<ConnectionFactory> existings = new ArrayList<>(_factories.values());
+ _factories.clear();
+ addConnectionFactory(factory);
+ for (ConnectionFactory existing : existings)
+ addConnectionFactory(existing);
+ _defaultProtocol = factory.getProtocol();
+ }
+ }
+
public void addIfAbsentConnectionFactory(ConnectionFactory factory)
{
synchronized (_factories)
@@ -460,8 +473,8 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
/* ------------------------------------------------------------ */
/** Set the acceptor thread priority delta.
* <p>This allows the acceptor thread to run at a different priority.
- * Typically this would be used to lower the priority to give preference
- * to handling previously accepted connections rather than accepting
+ * Typically this would be used to lower the priority to give preference
+ * to handling previously accepted connections rather than accepting
* new connections</p>
* @param acceptorPriorityDelta the acceptor priority delta
*/
@@ -532,7 +545,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
String name=thread.getName();
_name=String.format("%s-acceptor-%d@%x-%s",name,_id,hashCode(),AbstractConnector.this.toString());
thread.setName(_name);
-
+
int priority=thread.getPriority();
if (_acceptorPriorityDelta!=0)
thread.setPriority(Math.max(Thread.MIN_PRIORITY,Math.min(Thread.MAX_PRIORITY,priority+_acceptorPriorityDelta)));
@@ -574,7 +587,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
stopping.countDown();
}
}
-
+
@Override
public String toString()
{
@@ -583,7 +596,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
return String.format("acceptor-%d@%x", _id, hashCode());
return name;
}
-
+
}
@@ -636,7 +649,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
{
return _name;
}
-
+
/* ------------------------------------------------------------ */
/**
* Set a connector name. A context may be configured with
@@ -648,7 +661,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
{
_name=name;
}
-
+
@Override
public String toString()
{
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ProxyConnectionFactory.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ProxyConnectionFactory.java
index f810f4c55a..b72cf5718d 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/ProxyConnectionFactory.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ProxyConnectionFactory.java
@@ -35,11 +35,11 @@ import org.eclipse.jetty.util.log.Logger;
/* ------------------------------------------------------------ */
-/**
+/**
* ConnectionFactory for the PROXY Protocol.
* <p>This factory can be placed in front of any other connection factory
* to process the proxy line before the normal protocol handling</p>
- *
+ *
* @see <a href="http://www.haproxy.org/download/1.5/doc/proxy-protocol.txt">http://www.haproxy.org/download/1.5/doc/proxy-protocol.txt</a>
*/
public class ProxyConnectionFactory extends AbstractConnectionFactory
@@ -48,7 +48,7 @@ public class ProxyConnectionFactory extends AbstractConnectionFactory
private final String _next;
/* ------------------------------------------------------------ */
- /** Proxy Connection Factory that uses the next ConnectionFactory
+ /** Proxy Connection Factory that uses the next ConnectionFactory
* on the connector as the next protocol
*/
public ProxyConnectionFactory()
@@ -56,13 +56,13 @@ public class ProxyConnectionFactory extends AbstractConnectionFactory
super("proxy");
_next=null;
}
-
+
public ProxyConnectionFactory(String nextProtocol)
{
super("proxy");
_next=nextProtocol;
}
-
+
@Override
public Connection newConnection(Connector connector, EndPoint endp)
{
@@ -71,7 +71,7 @@ public class ProxyConnectionFactory extends AbstractConnectionFactory
{
for (Iterator<String> i = connector.getProtocols().iterator();i.hasNext();)
{
- String p=i.next();
+ String p=i.next();
if (getProtocol().equalsIgnoreCase(p))
{
next=i.next();
@@ -79,16 +79,16 @@ public class ProxyConnectionFactory extends AbstractConnectionFactory
}
}
}
-
+
return new ProxyConnection(endp,connector,next);
}
-
+
public static class ProxyConnection extends AbstractConnection
{
// 0 1 2 3 4 5 6
// 98765432109876543210987654321
// PROXY P R.R.R.R L.L.L.L R Lrn
-
+
private final int[] __size = {29,23,21,13,5,3,1};
private final Connector _connector;
private final String _next;
@@ -96,7 +96,7 @@ public class ProxyConnectionFactory extends AbstractConnectionFactory
private final String[] _field=new String[6];
private int _fields;
private int _length;
-
+
protected ProxyConnection(EndPoint endp, Connector connector, String next)
{
super(endp,connector.getExecutor());
@@ -110,9 +110,9 @@ public class ProxyConnectionFactory extends AbstractConnectionFactory
super.onOpen();
fillInterested();
}
-
+
@Override
- public void onFillable()
+ public void onFillable()
{
try
{
@@ -125,7 +125,7 @@ public class ProxyConnectionFactory extends AbstractConnectionFactory
buffer=BufferUtil.allocate(size);
else
BufferUtil.clear(buffer);
-
+
// Read data
int fill=getEndPoint().fill(buffer);
if (fill<0)
@@ -138,15 +138,15 @@ public class ProxyConnectionFactory extends AbstractConnectionFactory
fillInterested();
return;
}
-
+
_length+=fill;
if (_length>=108)
{
- LOG.warn("PROXY line too long {}",getEndPoint());
+ LOG.warn("PROXY line too long {} for {}",_length,getEndPoint());
close();
return;
}
-
+
// parse fields
while (buffer.hasRemaining())
{
@@ -160,61 +160,60 @@ public class ProxyConnectionFactory extends AbstractConnectionFactory
}
else if (b<' ')
{
- LOG.warn("Bad char {}",getEndPoint());
+ LOG.warn("Bad character {} for {}",b&0xFF,getEndPoint());
close();
return;
}
else
+ {
_builder.append((char)b);
+ }
}
else
{
if (b=='\n')
break loop;
- LOG.warn("Bad CRLF {}",getEndPoint());
+ LOG.warn("Bad CRLF for {}",getEndPoint());
close();
return;
-
}
}
}
-
+
// Check proxy
if (!"PROXY".equals(_field[0]))
{
- LOG.warn("Bad PROXY {}",getEndPoint());
+ LOG.warn("Not PROXY protocol for {}",getEndPoint());
close();
return;
}
-
- // Extract Addresses
+
+ // Extract Addresses
InetSocketAddress remote=new InetSocketAddress(_field[2],Integer.parseInt(_field[4]));
InetSocketAddress local =new InetSocketAddress(_field[3],Integer.parseInt(_field[5]));
-
+
// Create the next protocol
ConnectionFactory connectionFactory = _connector.getConnectionFactory(_next);
if (connectionFactory == null)
{
- LOG.info("{} next protocol '{}'",getEndPoint(), _next);
+ LOG.info("Next protocol '{}' for {}",_next,getEndPoint());
close();
return;
}
EndPoint endPoint = new ProxyEndPoint(getEndPoint(),remote,local);
- Connection newConnection = connectionFactory.newConnection(_connector, endPoint);
+ Connection newConnection = connectionFactory.newConnection(_connector, endPoint);
endPoint.upgrade(newConnection);
}
- catch (Throwable e)
+ catch (Throwable x)
{
- LOG.warn("Bad PROXY {} {}",e.toString(),getEndPoint());
- LOG.debug(e);
+ LOG.warn("PROXY error for "+getEndPoint(),x);
close();
}
}
}
-
-
+
public static class ProxyEndPoint implements EndPoint
{
private final EndPoint _endp;
@@ -233,7 +232,7 @@ public class ProxyConnectionFactory extends AbstractConnectionFactory
{
return _endp.isOptimizedForDirectBuffers();
}
-
+
public InetSocketAddress getLocalAddress()
{
return _local;
@@ -304,6 +303,12 @@ public class ProxyConnectionFactory extends AbstractConnectionFactory
_endp.fillInterested(callback);
}
+ @Override
+ public boolean isFillInterested()
+ {
+ return _endp.isFillInterested();
+ }
+
public void write(Callback callback, ByteBuffer... buffers) throws WritePendingException
{
_endp.write(callback,buffers);
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ServerConnectorTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ServerConnectorTest.java
index 8fc2a59106..c9432d880a 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/ServerConnectorTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ServerConnectorTest.java
@@ -18,23 +18,16 @@
package org.eclipse.jetty.server;
-import static org.hamcrest.Matchers.anyOf;
-import static org.hamcrest.Matchers.containsString;
-import static org.hamcrest.Matchers.instanceOf;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.junit.Assert.assertThat;
-
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.net.HttpURLConnection;
-import java.net.MalformedURLException;
import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
+import java.util.Collection;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@@ -49,6 +42,14 @@ import org.eclipse.jetty.toolchain.test.OS;
import org.eclipse.jetty.util.IO;
import org.junit.Test;
+import static org.hamcrest.Matchers.anyOf;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThat;
+
public class ServerConnectorTest
{
public static class ReuseInfoHandler extends AbstractHandler
@@ -79,9 +80,9 @@ public class ServerConnectorTest
{
t.printStackTrace(out);
}
-
+
out.printf("socket.getReuseAddress() = %b%n",socket.getReuseAddress());
-
+
baseRequest.setHandled(true);
}
}
@@ -97,7 +98,7 @@ public class ServerConnectorTest
return new URI(String.format("http://%s:%d/",host,port));
}
- private String getResponse(URI uri) throws MalformedURLException, IOException
+ private String getResponse(URI uri) throws IOException
{
HttpURLConnection http = (HttpURLConnection)uri.toURL().openConnection();
assertThat("Valid Response Code",http.getResponseCode(),anyOf(is(200),is(404)));
@@ -130,7 +131,7 @@ public class ServerConnectorTest
String response = getResponse(uri);
assertThat("Response",response,containsString("connector.getReuseAddress() = true"));
assertThat("Response",response,containsString("connector._reuseAddress() = true"));
-
+
// Java on Windows is incapable of propagating reuse-address this to the opened socket.
if (!OS.IS_WINDOWS)
{
@@ -166,7 +167,7 @@ public class ServerConnectorTest
String response = getResponse(uri);
assertThat("Response",response,containsString("connector.getReuseAddress() = true"));
assertThat("Response",response,containsString("connector._reuseAddress() = true"));
-
+
// Java on Windows is incapable of propagating reuse-address this to the opened socket.
if (!OS.IS_WINDOWS)
{
@@ -202,7 +203,7 @@ public class ServerConnectorTest
String response = getResponse(uri);
assertThat("Response",response,containsString("connector.getReuseAddress() = false"));
assertThat("Response",response,containsString("connector._reuseAddress() = false"));
-
+
// Java on Windows is incapable of propagating reuse-address this to the opened socket.
if (!OS.IS_WINDOWS)
{
@@ -214,4 +215,23 @@ public class ServerConnectorTest
server.stop();
}
}
+
+ @Test
+ public void testAddFirstConnectionFactory() throws Exception
+ {
+ Server server = new Server();
+ ServerConnector connector = new ServerConnector(server);
+ server.addConnector(connector);
+
+ HttpConnectionFactory http = new HttpConnectionFactory();
+ connector.addConnectionFactory(http);
+ ProxyConnectionFactory proxy = new ProxyConnectionFactory();
+ connector.addFirstConnectionFactory(proxy);
+
+ Collection<ConnectionFactory> factories = connector.getConnectionFactories();
+ assertEquals(2, factories.size());
+ assertSame(proxy, factories.iterator().next());
+ assertEquals(2, connector.getBeans(ConnectionFactory.class).size());
+ assertEquals(proxy.getProtocol(), connector.getDefaultProtocol());
+ }
}

Back to the top