mirror of
https://github.com/jetty/jetty.project.git
synced 2025-03-02 20:09:21 +00:00
Implemented FastCGIProxyServlet and handling of idle timeouts.
This commit is contained in:
parent
642f8c1ee1
commit
b08e415ca0
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty.fcgi</groupId>
|
<groupId>org.eclipse.jetty.fcgi</groupId>
|
||||||
<artifactId>fcgi-parent</artifactId>
|
<artifactId>fcgi-parent</artifactId>
|
||||||
<version>9.1.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
@ -20,17 +20,17 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-util</artifactId>
|
<artifactId>jetty-util</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${jetty-version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-io</artifactId>
|
<artifactId>jetty-io</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${jetty-version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-http</artifactId>
|
<artifactId>jetty-http</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${jetty-version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
package org.eclipse.jetty.fcgi.generator;
|
package org.eclipse.jetty.fcgi.generator;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
|
|
||||||
@ -108,6 +109,22 @@ public class Flusher
|
|||||||
if (active != null)
|
if (active != null)
|
||||||
active.failed(x);
|
active.failed(x);
|
||||||
active = null;
|
active = null;
|
||||||
|
|
||||||
|
List<Generator.Result> pending = new ArrayList<>();
|
||||||
|
synchronized (queue)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
Generator.Result result = queue.poll();
|
||||||
|
if (result != null)
|
||||||
|
pending.add(result);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Generator.Result result : pending)
|
||||||
|
result.failed(x);
|
||||||
|
|
||||||
super.failed(x);
|
super.failed(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty.fcgi</groupId>
|
<groupId>org.eclipse.jetty.fcgi</groupId>
|
||||||
<artifactId>fcgi-parent</artifactId>
|
<artifactId>fcgi-parent</artifactId>
|
||||||
<version>9.1.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
@ -21,7 +21,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-client</artifactId>
|
<artifactId>jetty-client</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${jetty-version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -19,14 +19,15 @@
|
|||||||
package org.eclipse.jetty.fcgi.client.http;
|
package org.eclipse.jetty.fcgi.client.http;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
import org.eclipse.jetty.client.HttpChannel;
|
import org.eclipse.jetty.client.HttpChannel;
|
||||||
import org.eclipse.jetty.client.HttpDestination;
|
|
||||||
import org.eclipse.jetty.client.HttpExchange;
|
import org.eclipse.jetty.client.HttpExchange;
|
||||||
import org.eclipse.jetty.fcgi.generator.Flusher;
|
import org.eclipse.jetty.fcgi.generator.Flusher;
|
||||||
import org.eclipse.jetty.fcgi.generator.Generator;
|
import org.eclipse.jetty.fcgi.generator.Generator;
|
||||||
import org.eclipse.jetty.http.HttpField;
|
import org.eclipse.jetty.http.HttpField;
|
||||||
import org.eclipse.jetty.http.HttpVersion;
|
import org.eclipse.jetty.http.HttpVersion;
|
||||||
|
import org.eclipse.jetty.io.IdleTimeout;
|
||||||
|
|
||||||
public class HttpChannelOverFCGI extends HttpChannel
|
public class HttpChannelOverFCGI extends HttpChannel
|
||||||
{
|
{
|
||||||
@ -36,13 +37,15 @@ public class HttpChannelOverFCGI extends HttpChannel
|
|||||||
private final HttpReceiverOverFCGI receiver;
|
private final HttpReceiverOverFCGI receiver;
|
||||||
private HttpVersion version;
|
private HttpVersion version;
|
||||||
|
|
||||||
public HttpChannelOverFCGI(HttpDestination destination, Flusher flusher, int request)
|
public HttpChannelOverFCGI(final HttpConnectionOverFCGI connection, Flusher flusher, int request, long idleTimeout)
|
||||||
{
|
{
|
||||||
super(destination);
|
super(connection.getHttpDestination());
|
||||||
this.flusher = flusher;
|
this.flusher = flusher;
|
||||||
this.request = request;
|
this.request = request;
|
||||||
this.sender = new HttpSenderOverFCGI(this);
|
this.sender = new HttpSenderOverFCGI(this);
|
||||||
this.receiver = new HttpReceiverOverFCGI(this);
|
this.receiver = new HttpReceiverOverFCGI(this);
|
||||||
|
IdleTimeout idle = new FCGIIdleTimeout(connection);
|
||||||
|
idle.setIdleTimeout(idleTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getRequest()
|
protected int getRequest()
|
||||||
@ -64,13 +67,14 @@ public class HttpChannelOverFCGI extends HttpChannel
|
|||||||
@Override
|
@Override
|
||||||
public void proceed(HttpExchange exchange, boolean proceed)
|
public void proceed(HttpExchange exchange, boolean proceed)
|
||||||
{
|
{
|
||||||
throw new UnsupportedOperationException();
|
sender.proceed(exchange, proceed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean abort(Throwable cause)
|
public boolean abort(Throwable cause)
|
||||||
{
|
{
|
||||||
throw new UnsupportedOperationException();
|
sender.abort(cause);
|
||||||
|
return receiver.abort(cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void responseBegin(int code, String reason)
|
protected void responseBegin(int code, String reason)
|
||||||
@ -111,8 +115,33 @@ public class HttpChannelOverFCGI extends HttpChannel
|
|||||||
receiver.responseSuccess(exchange);
|
receiver.responseSuccess(exchange);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void flush(Generator.Result... result)
|
protected void flush(Generator.Result... results)
|
||||||
{
|
{
|
||||||
flusher.flush(result);
|
flusher.flush(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FCGIIdleTimeout extends IdleTimeout
|
||||||
|
{
|
||||||
|
private final HttpConnectionOverFCGI connection;
|
||||||
|
|
||||||
|
public FCGIIdleTimeout(HttpConnectionOverFCGI connection)
|
||||||
|
{
|
||||||
|
super(connection.getHttpDestination().getHttpClient().getScheduler());
|
||||||
|
this.connection = connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onIdleExpired(TimeoutException timeout)
|
||||||
|
{
|
||||||
|
LOG.debug("Idle timeout for request {}", request);
|
||||||
|
abort(timeout);
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOpen()
|
||||||
|
{
|
||||||
|
return connection.getEndPoint().isOpen();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,7 @@ public class HttpClientTransportOverFCGI extends AbstractHttpClientTransport
|
|||||||
{
|
{
|
||||||
HttpDestination destination = (HttpDestination)context.get(HTTP_DESTINATION_CONTEXT_KEY);
|
HttpDestination destination = (HttpDestination)context.get(HTTP_DESTINATION_CONTEXT_KEY);
|
||||||
HttpConnectionOverFCGI connection = new HttpConnectionOverFCGI(endPoint, destination);
|
HttpConnectionOverFCGI connection = new HttpConnectionOverFCGI(endPoint, destination);
|
||||||
|
LOG.debug("Created {}", connection);
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Promise<Connection> promise = (Promise<Connection>)context.get(HTTP_CONNECTION_PROMISE_CONTEXT_KEY);
|
Promise<Connection> promise = (Promise<Connection>)context.get(HTTP_CONNECTION_PROMISE_CONTEXT_KEY);
|
||||||
promise.succeeded(connection);
|
promise.succeeded(connection);
|
||||||
|
@ -18,10 +18,12 @@
|
|||||||
|
|
||||||
package org.eclipse.jetty.fcgi.client.http;
|
package org.eclipse.jetty.fcgi.client.http;
|
||||||
|
|
||||||
|
import java.io.EOFException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
import org.eclipse.jetty.client.HttpClient;
|
import org.eclipse.jetty.client.HttpClient;
|
||||||
import org.eclipse.jetty.client.HttpConnection;
|
import org.eclipse.jetty.client.HttpConnection;
|
||||||
@ -134,12 +136,24 @@ public class HttpConnectionOverFCGI extends AbstractConnection implements Connec
|
|||||||
|
|
||||||
private void shutdown()
|
private void shutdown()
|
||||||
{
|
{
|
||||||
getEndPoint().shutdownOutput();
|
for (HttpChannelOverFCGI channel : channels.values())
|
||||||
|
channel.abort(new EOFException());
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean onReadTimeout()
|
||||||
|
{
|
||||||
|
for (HttpChannelOverFCGI channel : channels.values())
|
||||||
|
channel.abort(new TimeoutException());
|
||||||
|
close();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close()
|
public void close()
|
||||||
{
|
{
|
||||||
|
getHttpDestination().close(this);
|
||||||
getEndPoint().shutdownOutput();
|
getEndPoint().shutdownOutput();
|
||||||
LOG.debug("{} oshut", this);
|
LOG.debug("{} oshut", this);
|
||||||
getEndPoint().close();
|
getEndPoint().close();
|
||||||
@ -168,9 +182,9 @@ public class HttpConnectionOverFCGI extends AbstractConnection implements Connec
|
|||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
return String.format("%s@%x(l:%s <-> r:%s)",
|
return String.format("%s@%h(l:%s <-> r:%s)",
|
||||||
HttpConnection.class.getSimpleName(),
|
getClass().getSimpleName(),
|
||||||
hashCode(),
|
this,
|
||||||
getEndPoint().getLocalAddress(),
|
getEndPoint().getLocalAddress(),
|
||||||
getEndPoint().getRemoteAddress());
|
getEndPoint().getRemoteAddress());
|
||||||
}
|
}
|
||||||
@ -190,7 +204,7 @@ public class HttpConnectionOverFCGI extends AbstractConnection implements Connec
|
|||||||
|
|
||||||
// FCGI may be multiplexed, so create one channel for each request.
|
// FCGI may be multiplexed, so create one channel for each request.
|
||||||
int id = acquireRequest();
|
int id = acquireRequest();
|
||||||
HttpChannelOverFCGI channel = new HttpChannelOverFCGI(getHttpDestination(), flusher, id);
|
HttpChannelOverFCGI channel = new HttpChannelOverFCGI(HttpConnectionOverFCGI.this, flusher, id, request.getIdleTimeout());
|
||||||
channels.put(id, channel);
|
channels.put(id, channel);
|
||||||
channel.associate(exchange);
|
channel.associate(exchange);
|
||||||
channel.send();
|
channel.send();
|
||||||
@ -201,6 +215,12 @@ public class HttpConnectionOverFCGI extends AbstractConnection implements Connec
|
|||||||
{
|
{
|
||||||
HttpConnectionOverFCGI.this.close();
|
HttpConnectionOverFCGI.this.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return HttpConnectionOverFCGI.this.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ResponseListener implements ClientParser.Listener
|
private class ResponseListener implements ClientParser.Listener
|
||||||
|
@ -67,10 +67,6 @@ public class HttpSenderOverFCGI extends HttpSender
|
|||||||
fcgiHeaders.put(FCGI.Headers.SERVER_PROTOCOL, request.getVersion().asString());
|
fcgiHeaders.put(FCGI.Headers.SERVER_PROTOCOL, request.getVersion().asString());
|
||||||
fcgiHeaders.put(FCGI.Headers.GATEWAY_INTERFACE, "CGI/1.1");
|
fcgiHeaders.put(FCGI.Headers.GATEWAY_INTERFACE, "CGI/1.1");
|
||||||
fcgiHeaders.put(FCGI.Headers.SERVER_SOFTWARE, "Jetty/" + Jetty.VERSION);
|
fcgiHeaders.put(FCGI.Headers.SERVER_SOFTWARE, "Jetty/" + Jetty.VERSION);
|
||||||
// TODO: need to pass SERVER_NAME, SERVER_ADDR, SERVER_PORT, REMOTE_ADDR, REMOTE_PORT
|
|
||||||
// TODO: if the FCGI transport is used within a ProxyServlet, they must have certain values
|
|
||||||
// TODO: for example the remote address is taken from the ProxyServlet request
|
|
||||||
// TODO: if used standalone, they must have other values.
|
|
||||||
|
|
||||||
// Translate remaining HTTP header into the HTTP_* format
|
// Translate remaining HTTP header into the HTTP_* format
|
||||||
for (HttpField field : headers)
|
for (HttpField field : headers)
|
||||||
|
@ -46,7 +46,6 @@ public abstract class AbstractHttpClientServerTest
|
|||||||
|
|
||||||
ServerFCGIConnectionFactory fcgiConnectionFactory = new ServerFCGIConnectionFactory(new HttpConfiguration());
|
ServerFCGIConnectionFactory fcgiConnectionFactory = new ServerFCGIConnectionFactory(new HttpConfiguration());
|
||||||
connector = new ServerConnector(server, fcgiConnectionFactory);
|
connector = new ServerConnector(server, fcgiConnectionFactory);
|
||||||
connector.setPort(9000);
|
|
||||||
|
|
||||||
server.addConnector(connector);
|
server.addConnector(connector);
|
||||||
server.setHandler(handler);
|
server.setHandler(handler);
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
package org.eclipse.jetty.fcgi.client.http;
|
package org.eclipse.jetty.fcgi.client.http;
|
||||||
|
|
||||||
|
import java.io.EOFException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
@ -47,7 +48,7 @@ import org.junit.Test;
|
|||||||
public class HttpClientTest extends AbstractHttpClientServerTest
|
public class HttpClientTest extends AbstractHttpClientServerTest
|
||||||
{
|
{
|
||||||
@Test
|
@Test
|
||||||
public void test_GET_ResponseWithoutContent() throws Exception
|
public void testGETResponseWithoutContent() throws Exception
|
||||||
{
|
{
|
||||||
start(new EmptyServerHandler());
|
start(new EmptyServerHandler());
|
||||||
|
|
||||||
@ -60,7 +61,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test_GET_ResponseWithContent() throws Exception
|
public void testGETResponseWithContent() throws Exception
|
||||||
{
|
{
|
||||||
final byte[] data = new byte[]{0, 1, 2, 3, 4, 5, 6, 7};
|
final byte[] data = new byte[]{0, 1, 2, 3, 4, 5, 6, 7};
|
||||||
start(new AbstractHandler()
|
start(new AbstractHandler()
|
||||||
@ -84,7 +85,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test_GET_WithParameters_ResponseWithContent() throws Exception
|
public void testGETWithParametersResponseWithContent() throws Exception
|
||||||
{
|
{
|
||||||
final String paramName1 = "a";
|
final String paramName1 = "a";
|
||||||
final String paramName2 = "b";
|
final String paramName2 = "b";
|
||||||
@ -116,7 +117,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test_GET_WithParametersMultiValued_ResponseWithContent() throws Exception
|
public void testGETWithParametersMultiValuedResponseWithContent() throws Exception
|
||||||
{
|
{
|
||||||
final String paramName1 = "a";
|
final String paramName1 = "a";
|
||||||
final String paramName2 = "b";
|
final String paramName2 = "b";
|
||||||
@ -152,7 +153,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test_POST_WithParameters() throws Exception
|
public void testPOSTWithParameters() throws Exception
|
||||||
{
|
{
|
||||||
final String paramName = "a";
|
final String paramName = "a";
|
||||||
final String paramValue = "\u20AC";
|
final String paramValue = "\u20AC";
|
||||||
@ -183,7 +184,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test_PUT_WithParameters() throws Exception
|
public void testPUTWithParameters() throws Exception
|
||||||
{
|
{
|
||||||
final String paramName = "a";
|
final String paramName = "a";
|
||||||
final String paramValue = "\u20AC";
|
final String paramValue = "\u20AC";
|
||||||
@ -215,7 +216,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test_POST_WithParameters_WithContent() throws Exception
|
public void testPOSTWithParametersWithContent() throws Exception
|
||||||
{
|
{
|
||||||
final byte[] content = {0, 1, 2, 3};
|
final byte[] content = {0, 1, 2, 3};
|
||||||
final String paramName = "a";
|
final String paramName = "a";
|
||||||
@ -248,7 +249,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test_POST_WithContent_NotifiesRequestContentListener() throws Exception
|
public void testPOSTWithContentNotifiesRequestContentListener() throws Exception
|
||||||
{
|
{
|
||||||
final byte[] content = {0, 1, 2, 3};
|
final byte[] content = {0, 1, 2, 3};
|
||||||
start(new EmptyServerHandler());
|
start(new EmptyServerHandler());
|
||||||
@ -274,7 +275,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test_POST_WithContent_TracksProgress() throws Exception
|
public void testPOSTWithContentTracksProgress() throws Exception
|
||||||
{
|
{
|
||||||
start(new EmptyServerHandler());
|
start(new EmptyServerHandler());
|
||||||
|
|
||||||
@ -301,7 +302,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test_GZIP_ContentEncoding() throws Exception
|
public void testGZIPContentEncoding() throws Exception
|
||||||
{
|
{
|
||||||
final byte[] data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
final byte[] data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||||
start(new AbstractHandler()
|
start(new AbstractHandler()
|
||||||
@ -328,7 +329,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
|
|||||||
|
|
||||||
@Slow
|
@Slow
|
||||||
@Test
|
@Test
|
||||||
public void test_Request_IdleTimeout() throws Exception
|
public void testRequestIdleTimeout() throws Exception
|
||||||
{
|
{
|
||||||
final long idleTimeout = 1000;
|
final long idleTimeout = 1000;
|
||||||
start(new AbstractHandler()
|
start(new AbstractHandler()
|
||||||
@ -374,6 +375,56 @@ public class HttpClientTest extends AbstractHttpClientServerTest
|
|||||||
Assert.assertEquals(200, response.getStatus());
|
Assert.assertEquals(200, response.getStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConnectionIdleTimeout() throws Exception
|
||||||
|
{
|
||||||
|
final long idleTimeout = 1000;
|
||||||
|
start(new AbstractHandler()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
baseRequest.setHandled(true);
|
||||||
|
TimeUnit.MILLISECONDS.sleep(2 * idleTimeout);
|
||||||
|
}
|
||||||
|
catch (InterruptedException x)
|
||||||
|
{
|
||||||
|
throw new ServletException(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
connector.setIdleTimeout(idleTimeout);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
client.newRequest("localhost", connector.getLocalPort())
|
||||||
|
.scheme(scheme)
|
||||||
|
.idleTimeout(4 * idleTimeout, TimeUnit.MILLISECONDS)
|
||||||
|
.timeout(3 * idleTimeout, TimeUnit.MILLISECONDS)
|
||||||
|
.send();
|
||||||
|
Assert.fail();
|
||||||
|
}
|
||||||
|
catch (ExecutionException x)
|
||||||
|
{
|
||||||
|
Assert.assertTrue(x.getCause() instanceof EOFException);
|
||||||
|
}
|
||||||
|
|
||||||
|
connector.setIdleTimeout(5 * idleTimeout);
|
||||||
|
|
||||||
|
// Make another request to be sure the connection is recreated
|
||||||
|
ContentResponse response = client.newRequest("localhost", connector.getLocalPort())
|
||||||
|
.scheme(scheme)
|
||||||
|
.idleTimeout(4 * idleTimeout, TimeUnit.MILLISECONDS)
|
||||||
|
.timeout(3 * idleTimeout, TimeUnit.MILLISECONDS)
|
||||||
|
.send();
|
||||||
|
|
||||||
|
Assert.assertNotNull(response);
|
||||||
|
Assert.assertEquals(200, response.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSendToIPv6Address() throws Exception
|
public void testSendToIPv6Address() throws Exception
|
||||||
{
|
{
|
||||||
@ -389,7 +440,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test_HEAD_With_ResponseContentLength() throws Exception
|
public void testHEADWithResponseContentLength() throws Exception
|
||||||
{
|
{
|
||||||
final int length = 1024;
|
final int length = 1024;
|
||||||
start(new AbstractHandler()
|
start(new AbstractHandler()
|
||||||
|
47
fcgi-proxy/pom.xml
Normal file
47
fcgi-proxy/pom.xml
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>fcgi-parent</artifactId>
|
||||||
|
<groupId>org.eclipse.jetty.fcgi</groupId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>fcgi-proxy</artifactId>
|
||||||
|
<name>Jetty :: FastCGI :: Proxy</name>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.servlet</groupId>
|
||||||
|
<artifactId>javax.servlet-api</artifactId>
|
||||||
|
<version>3.1.0</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty.fcgi</groupId>
|
||||||
|
<artifactId>fcgi-http-client-transport</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-proxy</artifactId>
|
||||||
|
<version>${jetty-version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-server</artifactId>
|
||||||
|
<version>${jetty-version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-servlet</artifactId>
|
||||||
|
<version>${jetty-version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,76 @@
|
|||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2013 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.fcgi.proxy;
|
||||||
|
|
||||||
|
import javax.servlet.ServletConfig;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.client.HttpClient;
|
||||||
|
import org.eclipse.jetty.client.api.Request;
|
||||||
|
import org.eclipse.jetty.fcgi.FCGI;
|
||||||
|
import org.eclipse.jetty.fcgi.client.http.HttpClientTransportOverFCGI;
|
||||||
|
import org.eclipse.jetty.http.HttpFields;
|
||||||
|
import org.eclipse.jetty.proxy.ProxyServlet;
|
||||||
|
|
||||||
|
public class FastCGIProxyServlet extends ProxyServlet.Transparent
|
||||||
|
{
|
||||||
|
public static final String SCRIPT_ROOT_INIT_PARAM = "scriptRoot";
|
||||||
|
private static final String REMOTE_ADDR_ATTRIBUTE = FastCGIProxyServlet.class.getName() + ".remoteAddr";
|
||||||
|
private static final String REMOTE_PORT_ATTRIBUTE = FastCGIProxyServlet.class.getName() + ".remotePort";
|
||||||
|
private static final String SERVER_ADDR_ATTRIBUTE = FastCGIProxyServlet.class.getName() + ".serverAddr";
|
||||||
|
private static final String SERVER_PORT_ATTRIBUTE = FastCGIProxyServlet.class.getName() + ".serverPort";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected HttpClient newHttpClient()
|
||||||
|
{
|
||||||
|
ServletConfig config = getServletConfig();
|
||||||
|
String scriptRoot = config.getInitParameter(SCRIPT_ROOT_INIT_PARAM);
|
||||||
|
if (scriptRoot == null)
|
||||||
|
throw new IllegalArgumentException("Mandatory parameter '" + SCRIPT_ROOT_INIT_PARAM + "' not configured");
|
||||||
|
return new HttpClient(new ProxyHttpClientTransportOverFCGI(scriptRoot), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void customizeProxyRequest(Request proxyRequest, HttpServletRequest request)
|
||||||
|
{
|
||||||
|
proxyRequest.attribute(REMOTE_ADDR_ATTRIBUTE, request.getRemoteAddr());
|
||||||
|
proxyRequest.attribute(REMOTE_PORT_ATTRIBUTE, String.valueOf(request.getRemotePort()));
|
||||||
|
proxyRequest.attribute(SERVER_ADDR_ATTRIBUTE, request.getLocalAddr());
|
||||||
|
proxyRequest.attribute(SERVER_PORT_ATTRIBUTE, String.valueOf(request.getLocalPort()));
|
||||||
|
super.customizeProxyRequest(proxyRequest, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ProxyHttpClientTransportOverFCGI extends HttpClientTransportOverFCGI
|
||||||
|
{
|
||||||
|
public ProxyHttpClientTransportOverFCGI(String scriptRoot)
|
||||||
|
{
|
||||||
|
super(scriptRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void customize(Request request, HttpFields fastCGIHeaders)
|
||||||
|
{
|
||||||
|
super.customize(request, fastCGIHeaders);
|
||||||
|
fastCGIHeaders.put(FCGI.Headers.REMOTE_ADDR, (String)request.getAttributes().get(REMOTE_ADDR_ATTRIBUTE));
|
||||||
|
fastCGIHeaders.put(FCGI.Headers.REMOTE_PORT, (String)request.getAttributes().get(REMOTE_PORT_ATTRIBUTE));
|
||||||
|
fastCGIHeaders.put(FCGI.Headers.SERVER_ADDR, (String)request.getAttributes().get(SERVER_ADDR_ATTRIBUTE));
|
||||||
|
fastCGIHeaders.put(FCGI.Headers.SERVER_PORT, (String)request.getAttributes().get(SERVER_PORT_ATTRIBUTE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2013 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.fcgi.proxy;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.server.Server;
|
||||||
|
import org.eclipse.jetty.server.ServerConnector;
|
||||||
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
|
|
||||||
|
public class FastCGIProxyServer
|
||||||
|
{
|
||||||
|
public static void main(String[] args) throws Exception
|
||||||
|
{
|
||||||
|
Server server = new Server();
|
||||||
|
ServerConnector connector = new ServerConnector(server);
|
||||||
|
connector.setPort(8080);
|
||||||
|
server.addConnector(connector);
|
||||||
|
|
||||||
|
ServletContextHandler context = new ServletContextHandler(server, "/");
|
||||||
|
ServletHolder servletHolder = new ServletHolder(FastCGIProxyServlet.class);
|
||||||
|
servletHolder.setInitParameter(FastCGIProxyServlet.SCRIPT_ROOT_INIT_PARAM, "/var/www/php-fcgi");
|
||||||
|
servletHolder.setInitParameter("proxyTo", "http://localhost:9000/");
|
||||||
|
servletHolder.setInitParameter("prefix", "/");
|
||||||
|
context.addServlet(servletHolder, "/*");
|
||||||
|
|
||||||
|
server.start();
|
||||||
|
}
|
||||||
|
}
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty.fcgi</groupId>
|
<groupId>org.eclipse.jetty.fcgi</groupId>
|
||||||
<artifactId>fcgi-parent</artifactId>
|
<artifactId>fcgi-parent</artifactId>
|
||||||
<version>9.1.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
@ -21,7 +21,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-server</artifactId>
|
<artifactId>jetty-server</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${jetty-version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
8
pom.xml
8
pom.xml
@ -11,13 +11,19 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.eclipse.jetty.fcgi</groupId>
|
<groupId>org.eclipse.jetty.fcgi</groupId>
|
||||||
<artifactId>fcgi-parent</artifactId>
|
<artifactId>fcgi-parent</artifactId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<name>Jetty :: FastCGI</name>
|
<name>Jetty :: FastCGI</name>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<jetty-version>9.1.0-SNAPSHOT</jetty-version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
<module>fcgi-core</module>
|
<module>fcgi-core</module>
|
||||||
<module>fcgi-http-client-transport</module>
|
<module>fcgi-http-client-transport</module>
|
||||||
<module>fcgi-server</module>
|
<module>fcgi-server</module>
|
||||||
|
<module>fcgi-proxy</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
@ -40,7 +46,6 @@
|
|||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
-->
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.felix</groupId>
|
<groupId>org.apache.felix</groupId>
|
||||||
<artifactId>maven-bundle-plugin</artifactId>
|
<artifactId>maven-bundle-plugin</artifactId>
|
||||||
@ -69,6 +74,7 @@
|
|||||||
</archive>
|
</archive>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
-->
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user