Fixed handling of "url" header (now ignored since Chromium does not send it as absolute URL),

and added handling of "host" header (sent by Chromium).

Also fixed handling of "bypass" content, that is content that is directly sent to clients without
being buffered (such as images, CSS, and others).
This commit is contained in:
Simone Bordet 2012-02-14 23:03:10 +01:00
parent c8dcaacdff
commit f33a0deee2
2 changed files with 76 additions and 69 deletions

View File

@ -18,8 +18,6 @@ package org.eclipse.jetty.spdy.http;
import java.io.EOFException;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.util.concurrent.TimeUnit;
@ -109,7 +107,7 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
String m = method.value();
String u = uri.value();
String v = version.value();
logger.debug("HTTP {} {} {}", new Object[]{m, u, v});
logger.debug("HTTP > {} {} {}", new Object[]{m, u, v});
startRequest(new ByteArrayBuffer(m), new ByteArrayBuffer(u), new ByteArrayBuffer(v));
state = State.HEADERS;
@ -125,28 +123,15 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
{
case "method":
case "version":
case "url":
{
// Skip request line headers
continue;
}
case "url":
{
// Mangle the URL if the host header is missing
String host = parseHost(header.value());
// Jetty needs the host header, although HTTP 1.1 does not
// require it if it can be parsed from an absolute URI
if (host != null)
{
logger.debug("HTTP {}: {}", "host", host);
parsedHeader(new ByteArrayBuffer("host"), new ByteArrayBuffer(host));
}
break;
}
case "connection":
case "keep-alive":
case "proxy-connection":
case "transfer-encoding":
case "host":
{
// Spec says to ignore these headers
continue;
@ -155,7 +140,7 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
{
// Spec says headers must be single valued
String value = header.value();
logger.debug("HTTP {}: {}", name, value);
logger.debug("HTTP > {}: {}", name, value);
parsedHeader(new ByteArrayBuffer(name), new ByteArrayBuffer(value));
break;
}
@ -221,7 +206,7 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
{
buffer = byteBuffer.isDirect() ? new DirectNIOBuffer(byteBuffer, false) : new IndirectNIOBuffer(byteBuffer, false);
complete = endRequest;
logger.debug("HTTP {} bytes of content", buffer.length());
logger.debug("HTTP > {} bytes of content", buffer.length());
if (state == State.HEADERS)
{
state = State.HEADERS_COMPLETE;
@ -310,19 +295,6 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
super.completeResponse();
}
private String parseHost(String url)
{
try
{
URI uri = new URI(url);
return uri.getHost() + (uri.getPort() > 0 ? ":" + uri.getPort() : "");
}
catch (URISyntaxException x)
{
return null;
}
}
private enum State
{
INITIAL, REQUEST, HEADERS, HEADERS_COMPLETE, CONTENT, FINAL
@ -414,41 +386,56 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
public void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException
{
Headers headers = new Headers();
String version = "HTTP/1.1";
headers.put("version", version);
StringBuilder status = new StringBuilder().append(_status);
if (_reason != null)
status.append(" ").append(_reason.toString("UTF-8"));
headers.put("status", status.toString());
headers.put("version", "HTTP/1.1");
logger.debug("HTTP < {} {}", version, status);
if (fields != null)
{
for (int i = 0; i < fields.size(); ++i)
{
HttpFields.Field field = fields.getField(i);
headers.put(field.getName(), field.getValue());
String name = field.getName().toLowerCase();
String value = field.getValue();
headers.put(name, value);
logger.debug("HTTP < {}: {}", name, value);
}
}
// We have to query the HttpGenerator and its _buffer to know
// We have to query the HttpGenerator and its buffers to know
// whether there is content buffered; if so, send the data frame
boolean close = _buffer == null || _buffer.length() == 0;
stream.reply(new ReplyInfo(headers, close));
if (close)
Buffer content = getContentBuffer();
stream.reply(new ReplyInfo(headers, content == null));
if (content != null)
{
closed = allContentAdded || isAllContentWritten();
ByteBuffer buffer = ByteBuffer.wrap(content.asArray());
logger.debug("HTTP < {} bytes of content", buffer.remaining());
// Send the data frame
stream.data(new ByteBufferDataInfo(buffer, closed));
// Update HttpGenerator fields so that they remain consistent
content.clear();
_state = closed ? HttpGenerator.STATE_END : HttpGenerator.STATE_CONTENT;
}
else
{
closed = true;
// Update HttpGenerator fields so that they remain consistent
_state = HttpGenerator.STATE_END;
}
else
{
closed = allContentAdded || isAllContentWritten();
ByteBuffer buffer = ByteBuffer.wrap(_buffer.asArray());
// Send the data frame
stream.data(new ByteBufferDataInfo(buffer, closed));
// Update HttpGenerator fields so that they remain consistent
_buffer.clear();
_state = closed ? HttpGenerator.STATE_END : HttpGenerator.STATE_CONTENT;
}
}
private Buffer getContentBuffer()
{
if (_buffer != null && _buffer.length() > 0)
return _buffer;
if (_bypass && _content != null && _content.length() > 0)
return _content;
return null;
}
@Override
@ -475,6 +462,7 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
{
_content.skip(_buffer.put(_content));
ByteBuffer buffer = ByteBuffer.wrap(_buffer.asArray());
logger.debug("HTTP < {} bytes of content", buffer.remaining());
_buffer.clear();
closed = _content.length() == 0 && _last;
stream.data(new ByteBufferDataInfo(buffer, closed));
@ -509,11 +497,13 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
@Override
public void complete() throws IOException
{
if (_buffer != null && _buffer.length() > 0)
Buffer content = getContentBuffer();
if (content != null)
{
ByteBuffer buffer = ByteBuffer.wrap(_buffer.asArray());
ByteBuffer buffer = ByteBuffer.wrap(content.asArray());
logger.debug("HTTP < {} bytes of content", buffer.remaining());
// Update HttpGenerator fields so that they remain consistent
_buffer.clear();
content.clear();
_state = STATE_END;
// Send the data frame
stream.data(new ByteBufferDataInfo(buffer, true));

View File

@ -142,8 +142,9 @@ public class ServerHTTPSPDYTest
Headers headers = new Headers();
headers.put("method", "GET");
headers.put("url", "http://localhost:" + connector.getLocalPort() + path);
headers.put("url", path);
headers.put("version", "HTTP/1.1");
headers.put("host", "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
session.syn(SPDY.V2, new SynInfo(headers, true), new Stream.FrameListener.Adapter()
{
@ -184,8 +185,9 @@ public class ServerHTTPSPDYTest
Headers headers = new Headers();
headers.put("method", "GET");
headers.put("url", "http://localhost:" + connector.getLocalPort() + uri);
headers.put("url", uri);
headers.put("version", "HTTP/1.1");
headers.put("host", "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
session.syn(SPDY.V2, new SynInfo(headers, true), new Stream.FrameListener.Adapter()
{
@ -223,8 +225,9 @@ public class ServerHTTPSPDYTest
Headers headers = new Headers();
headers.put("method", "HEAD");
headers.put("url", "http://localhost:" + connector.getLocalPort() + path);
headers.put("url", path);
headers.put("version", "HTTP/1.1");
headers.put("host", "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
session.syn(SPDY.V2, new SynInfo(headers, true), new Stream.FrameListener.Adapter()
{
@ -263,8 +266,9 @@ public class ServerHTTPSPDYTest
Headers headers = new Headers();
headers.put("method", "POST");
headers.put("url", "http://localhost:" + connector.getLocalPort() + path);
headers.put("url", path);
headers.put("version", "HTTP/1.1");
headers.put("host", "localhost:" + connector.getLocalPort());
headers.put("content-type", "application/x-www-form-urlencoded");
final CountDownLatch replyLatch = new CountDownLatch(1);
Stream stream = session.syn(SPDY.V2, new SynInfo(headers, false), new Stream.FrameListener.Adapter()
@ -307,8 +311,9 @@ public class ServerHTTPSPDYTest
Headers headers = new Headers();
headers.put("method", "POST");
headers.put("url", "http://localhost:" + connector.getLocalPort() + path);
headers.put("url", path);
headers.put("version", "HTTP/1.1");
headers.put("host", "localhost:" + connector.getLocalPort());
headers.put("content-type", "application/x-www-form-urlencoded");
final CountDownLatch replyLatch = new CountDownLatch(1);
Stream stream = session.syn(SPDY.V2, new SynInfo(headers, false), new Stream.FrameListener.Adapter()
@ -354,8 +359,9 @@ public class ServerHTTPSPDYTest
Headers headers = new Headers();
headers.put("method", "POST");
headers.put("url", "http://localhost:" + connector.getLocalPort() + path);
headers.put("url", path);
headers.put("version", "HTTP/1.1");
headers.put("host", "localhost:" + connector.getLocalPort());
headers.put("content-type", "application/x-www-form-urlencoded");
final CountDownLatch replyLatch = new CountDownLatch(1);
Stream stream = session.syn(SPDY.V2, new SynInfo(headers, false), new Stream.FrameListener.Adapter()
@ -398,8 +404,9 @@ public class ServerHTTPSPDYTest
Headers headers = new Headers();
headers.put("method", "GET");
headers.put("url", "http://localhost:" + connector.getLocalPort() + "/foo");
headers.put("url", "/foo");
headers.put("version", "HTTP/1.1");
headers.put("host", "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(SPDY.V2, new SynInfo(headers, true), new Stream.FrameListener.Adapter()
@ -447,8 +454,9 @@ public class ServerHTTPSPDYTest
Headers headers = new Headers();
headers.put("method", "GET");
headers.put("url", "http://localhost:" + connector.getLocalPort() + "/foo");
headers.put("url", "/foo");
headers.put("version", "HTTP/1.1");
headers.put("host", "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(SPDY.V2, new SynInfo(headers, true), new Stream.FrameListener.Adapter()
@ -503,8 +511,9 @@ public class ServerHTTPSPDYTest
Headers headers = new Headers();
headers.put("method", "GET");
headers.put("url", "http://localhost:" + connector.getLocalPort() + "/foo");
headers.put("url", "/foo");
headers.put("version", "HTTP/1.1");
headers.put("host", "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(2);
session.syn(SPDY.V2, new SynInfo(headers, true), new Stream.FrameListener.Adapter()
@ -561,8 +570,9 @@ public class ServerHTTPSPDYTest
Headers headers = new Headers();
headers.put("method", "GET");
headers.put("url", "http://localhost:" + connector.getLocalPort() + "/foo");
headers.put("url", "/foo");
headers.put("version", "HTTP/1.1");
headers.put("host", "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(SPDY.V2, new SynInfo(headers, true), new Stream.FrameListener.Adapter()
@ -617,8 +627,9 @@ public class ServerHTTPSPDYTest
Headers headers = new Headers();
headers.put("method", "GET");
headers.put("url", "http://localhost:" + connector.getLocalPort() + "/foo");
headers.put("url", "/foo");
headers.put("version", "HTTP/1.1");
headers.put("host", "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(SPDY.V2, new SynInfo(headers, true), new Stream.FrameListener.Adapter()
@ -673,8 +684,9 @@ public class ServerHTTPSPDYTest
Headers headers = new Headers();
headers.put("method", "GET");
headers.put("url", "http://localhost:" + connector.getLocalPort() + "/foo");
headers.put("url", "/foo");
headers.put("version", "HTTP/1.1");
headers.put("host", "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(SPDY.V2, new SynInfo(headers, true), new Stream.FrameListener.Adapter()
@ -736,8 +748,9 @@ public class ServerHTTPSPDYTest
Headers headers = new Headers();
headers.put("method", "GET");
headers.put("url", "http://localhost:" + connector.getLocalPort() + "/foo");
headers.put("url", "/foo");
headers.put("version", "HTTP/1.1");
headers.put("host", "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(SPDY.V2, new SynInfo(headers, true), new Stream.FrameListener.Adapter()
@ -794,8 +807,9 @@ public class ServerHTTPSPDYTest
Headers headers = new Headers();
headers.put("method", "GET");
headers.put("url", "http://localhost:" + connector.getLocalPort() + "/foo");
headers.put("url", "/foo");
headers.put("version", "HTTP/1.1");
headers.put("host", "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
session.syn(SPDY.V2, new SynInfo(headers, true), new Stream.FrameListener.Adapter()
{
@ -834,8 +848,9 @@ public class ServerHTTPSPDYTest
Headers headers = new Headers();
headers.put("method", "GET");
headers.put("url", "http://localhost:" + connector.getLocalPort() + "/foo");
headers.put("url", "/foo");
headers.put("version", "HTTP/1.1");
headers.put("host", "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(SPDY.V2, new SynInfo(headers, true), new Stream.FrameListener.Adapter()
@ -879,8 +894,9 @@ public class ServerHTTPSPDYTest
Headers headers = new Headers();
headers.put("method", "GET");
headers.put("url", "http://localhost:" + connector.getLocalPort() + "/foo");
headers.put("url", "/foo");
headers.put("version", "HTTP/1.1");
headers.put("host", "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
session.syn(SPDY.V2, new SynInfo(headers, true), new Stream.FrameListener.Adapter()
{
@ -924,8 +940,9 @@ public class ServerHTTPSPDYTest
Headers headers = new Headers();
headers.put("method", "GET");
headers.put("url", "http://localhost:" + connector.getLocalPort() + "/foo");
headers.put("url", "/foo");
headers.put("version", "HTTP/1.1");
headers.put("host", "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(2);
session.syn(SPDY.V2, new SynInfo(headers, true), new Stream.FrameListener.Adapter()