Fixed code and tests, first clean build.

This commit is contained in:
Simone Bordet 2013-10-23 16:00:43 +02:00
parent b08e415ca0
commit 24d4a971d2
6 changed files with 96 additions and 74 deletions

View File

@ -45,6 +45,12 @@ public class ResponseContentParser extends StreamContentParser
this.listener = listener;
}
@Override
public void noContent()
{
// Does nothing, since for responses the end of content is signaled via a FCGI_END_REQUEST frame
}
@Override
protected void onContent(ByteBuffer buffer)
{

View File

@ -40,15 +40,15 @@ public class ClientParserTest
final int id = 13;
HttpFields fields = new HttpFields();
final String statusName = "Status";
final int code = 200;
final int statusCode = 200;
final String statusMessage = "OK";
final String contentTypeName = "Content-Type";
final String contentTypeValue = "text/html;charset=utf-8";
fields.put(contentTypeName, contentTypeValue);
ByteBufferPool byteBufferPool = new MappedByteBufferPool();
ServerGenerator generator = new ServerGenerator(byteBufferPool);
Generator.Result result = generator.generateResponseHeaders(id, code, "OK", fields, null);
Generator.Result result = generator.generateResponseHeaders(id, statusCode, statusMessage, fields, null);
// Use the fundamental theorem of arithmetic to test the results.
// This way we know onHeader() has been called the right number of
@ -61,20 +61,26 @@ public class ClientParserTest
final AtomicInteger params = new AtomicInteger(1);
ClientParser parser = new ClientParser(new ClientParser.Listener.Adapter()
{
@Override
public void onBegin(int request, int code, String reason)
{
Assert.assertEquals(statusCode, code);
Assert.assertEquals(statusMessage, reason);
params.set(params.get() * primes[0]);
}
@Override
public void onHeader(int request, HttpField field)
{
Assert.assertEquals(id, request);
switch (field.getName())
{
case statusName:
Assert.assertTrue(field.getValue().startsWith(String.valueOf(code)));
params.set(params.get() * primes[0]);
break;
case contentTypeName:
Assert.assertEquals(contentTypeValue, field.getValue());
params.set(params.get() * primes[1]);
break;
default:
break;
}
}
@ -100,15 +106,11 @@ public class ClientParserTest
{
final int id = 13;
HttpFields fields = new HttpFields();
final int code = 200;
final String contentTypeName = "Content-Length";
final String contentTypeValue = "0";
fields.put(contentTypeName, contentTypeValue);
fields.put("Content-Length", "0");
ByteBufferPool byteBufferPool = new MappedByteBufferPool();
ServerGenerator generator = new ServerGenerator(byteBufferPool);
Generator.Result result1 = generator.generateResponseHeaders(id, code, "OK", fields, null);
Generator.Result result1 = generator.generateResponseHeaders(id, 200, "OK", fields, null);
Generator.Result result2 = generator.generateResponseContent(id, null, true, null);
final AtomicInteger verifier = new AtomicInteger();

View File

@ -136,9 +136,12 @@ public class HttpConnectionOverFCGI extends AbstractConnection implements Connec
private void shutdown()
{
// First close then abort, to be sure that the
// connection cannot be reused from an onFailure()
// handler or by blocking code waiting for completion.
close();
for (HttpChannelOverFCGI channel : channels.values())
channel.abort(new EOFException());
close();
}
@Override

View File

@ -45,9 +45,9 @@ public class HttpSenderOverFCGI extends HttpSender
// FastCGI headers based on the URI
URI uri = request.getURI();
String path = uri.getPath();
String path = uri.getRawPath();
fcgiHeaders.put(FCGI.Headers.REQUEST_URI, path);
String query = uri.getQuery();
String query = uri.getRawQuery();
fcgiHeaders.put(FCGI.Headers.QUERY_STRING, query == null ? "" : query);
int lastSegment = path.lastIndexOf('/');
String scriptName = lastSegment < 0 ? path : path.substring(lastSegment);

View File

@ -19,7 +19,7 @@
package org.eclipse.jetty.fcgi.server;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
@ -28,6 +28,7 @@ import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jetty.fcgi.FCGI;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.Connector;
@ -42,12 +43,12 @@ public class HttpChannelOverFCGI extends HttpChannel<ByteBuffer>
{
private static final Logger LOG = Log.getLogger(HttpChannelOverFCGI.class);
private final List<HttpField> fields = new ArrayList<>();
private final Dispatcher dispatcher;
private String method;
private String uri;
private String path;
private String query;
private String version;
private boolean started;
private List<HttpField> fields;
public HttpChannelOverFCGI(Connector connector, HttpConfiguration configuration, EndPoint endPoint, HttpTransport transport, HttpInput<ByteBuffer> input)
{
@ -58,57 +59,37 @@ public class HttpChannelOverFCGI extends HttpChannel<ByteBuffer>
protected void header(HttpField field)
{
if (FCGI.Headers.REQUEST_METHOD.equalsIgnoreCase(field.getName()))
{
method = field.getValue();
if (uri != null && version != null)
startRequest();
}
else if (FCGI.Headers.REQUEST_URI.equalsIgnoreCase(field.getName()))
{
uri = field.getValue();
if (method != null && version != null)
startRequest();
}
path = field.getValue();
else if (FCGI.Headers.QUERY_STRING.equalsIgnoreCase(field.getName()))
query = field.getValue();
else if (FCGI.Headers.SERVER_PROTOCOL.equalsIgnoreCase(field.getName()))
{
version = field.getValue();
if (method != null && uri != null)
startRequest();
}
else
{
if (started)
{
resumeHeaders();
convertHeader(field);
}
else
{
if (fields == null)
fields = new ArrayList<>();
fields.add(field);
}
}
fields.add(field);
}
private void startRequest()
@Override
public boolean headerComplete()
{
started = true;
startRequest(null, method, ByteBuffer.wrap(uri.getBytes(Charset.forName("UTF-8"))), HttpVersion.fromString(version));
resumeHeaders();
}
String uri = path;
if (query != null && query.length() > 0)
uri += "?" + query;
startRequest(HttpMethod.fromString(method), method, ByteBuffer.wrap(uri.getBytes(StandardCharsets.UTF_8)),
HttpVersion.fromString(version));
private void resumeHeaders()
{
if (fields != null)
for (HttpField fcgiField : fields)
{
for (HttpField field : fields)
convertHeader(field);
fields = null;
HttpField httpField = convertHeader(fcgiField);
if (httpField != null)
parsedHeader(httpField);
}
return super.headerComplete();
}
private void convertHeader(HttpField field)
private HttpField convertHeader(HttpField field)
{
String name = field.getName();
if (name.startsWith("HTTP_"))
@ -124,17 +105,9 @@ public class HttpChannelOverFCGI extends HttpChannel<ByteBuffer>
httpName.append(Character.toUpperCase(part.charAt(0)));
httpName.append(part.substring(1).toLowerCase(Locale.ENGLISH));
}
field = new HttpField(httpName.toString(), field.getValue());
return new HttpField(httpName.toString(), field.getValue());
}
parsedHeader(field);
}
@Override
public boolean headerComplete()
{
boolean result = super.headerComplete();
started = false;
return result;
return null;
}
protected void dispatch()

View File

@ -26,6 +26,7 @@ import org.eclipse.jetty.fcgi.generator.ServerGenerator;
import org.eclipse.jetty.http.HttpGenerator;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.server.HttpTransport;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
public class HttpTransportOverFCGI implements HttpTransport
@ -33,6 +34,7 @@ public class HttpTransportOverFCGI implements HttpTransport
private final ServerGenerator generator;
private final Flusher flusher;
private final int request;
private volatile boolean head;
public HttpTransportOverFCGI(ByteBufferPool byteBufferPool, Flusher flusher, int request)
{
@ -44,17 +46,53 @@ public class HttpTransportOverFCGI implements HttpTransport
@Override
public void send(HttpGenerator.ResponseInfo info, ByteBuffer content, boolean lastContent, Callback callback)
{
Generator.Result headersResult = generator.generateResponseHeaders(request, info.getStatus(), info.getReason(),
info.getHttpFields(), new Callback.Adapter());
Generator.Result contentResult = generator.generateResponseContent(request, content, lastContent, callback);
flusher.flush(headersResult, contentResult);
boolean head = this.head = info.isHead();
if (head)
{
if (lastContent)
{
Generator.Result headersResult = generator.generateResponseHeaders(request, info.getStatus(), info.getReason(),
info.getHttpFields(), new Callback.Adapter());
Generator.Result contentResult = generator.generateResponseContent(request, BufferUtil.EMPTY_BUFFER, lastContent, callback);
flusher.flush(headersResult, contentResult);
}
else
{
Generator.Result headersResult = generator.generateResponseHeaders(request, info.getStatus(), info.getReason(),
info.getHttpFields(), callback);
flusher.flush(headersResult);
}
}
else
{
Generator.Result headersResult = generator.generateResponseHeaders(request, info.getStatus(), info.getReason(),
info.getHttpFields(), new Callback.Adapter());
Generator.Result contentResult = generator.generateResponseContent(request, content, lastContent, callback);
flusher.flush(headersResult, contentResult);
}
}
@Override
public void send(ByteBuffer content, boolean lastContent, Callback callback)
{
Generator.Result result = generator.generateResponseContent(request, content, lastContent, callback);
flusher.flush(result);
if (head)
{
if (lastContent)
{
Generator.Result result = generator.generateResponseContent(request, BufferUtil.EMPTY_BUFFER, lastContent, callback);
flusher.flush(result);
}
else
{
// Skip content generation
callback.succeeded();
}
}
else
{
Generator.Result result = generator.generateResponseContent(request, content, lastContent, callback);
flusher.flush(result);
}
}
@Override