* Added HttpVersion.isKeepAliveDefault() to handle the 'Connection' header in a more robust manner
* Added HttpVersion constructors with the default keep alive flag - old constructors were deprecated due to ambiguity * Moved HttpMessage.is/setKeepAlive() to HttpHeaders and deprecated the original method
This commit is contained in:
parent
aff9af5af2
commit
a85635f74c
@ -96,7 +96,7 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
|
||||
ChannelFuture writeFuture = ch.write(new ChunkedFile(raf, 0, fileLength, 8192));
|
||||
|
||||
// Decide whether to close the connection or not.
|
||||
if (!request.isKeepAlive()) {
|
||||
if (!isKeepAlive(request)) {
|
||||
// Close the connection when the whole content is written out.
|
||||
writeFuture.addListener(ChannelFutureListener.CLOSE);
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ public class HttpRequestHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
private void writeResponse(MessageEvent e) {
|
||||
// Decide whether to close the connection or not.
|
||||
boolean keepAlive = request.isKeepAlive();
|
||||
boolean keepAlive = isKeepAlive(request);
|
||||
|
||||
// Build the response object.
|
||||
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
|
||||
@ -154,7 +154,7 @@ public class HttpRequestHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
// Write the response.
|
||||
ChannelFuture future = e.getChannel().write(response);
|
||||
|
||||
System.out.println(response.toString());
|
||||
// Close the non-keep-alive connection after the write operation is done.
|
||||
if (!keepAlive) {
|
||||
future.addListener(ChannelFutureListener.CLOSE);
|
||||
|
@ -140,7 +140,7 @@ public class WebSocketServerHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
// Send the response and close the connection if necessary.
|
||||
ChannelFuture f = ctx.getChannel().write(res);
|
||||
if (!req.isKeepAlive() || res.getStatus().getCode() != 200) {
|
||||
if (!isKeepAlive(req) || res.getStatus().getCode() != 200) {
|
||||
f.addListener(ChannelFutureListener.CLOSE);
|
||||
}
|
||||
}
|
||||
|
@ -21,8 +21,6 @@ import java.util.Set;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.buffer.ChannelBuffers;
|
||||
import org.jboss.netty.handler.codec.http.HttpHeaders.Names;
|
||||
import org.jboss.netty.handler.codec.http.HttpHeaders.Values;
|
||||
import org.jboss.netty.util.internal.StringUtil;
|
||||
|
||||
/**
|
||||
@ -88,43 +86,9 @@ public class DefaultHttpMessage implements HttpMessage {
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public boolean isKeepAlive() {
|
||||
HttpVersion version = getProtocolVersion();
|
||||
if (!version.getProtocolName().equals("HTTP")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String connection = getHeader(Names.CONNECTION);
|
||||
if (HttpHeaders.Values.CLOSE.equalsIgnoreCase(connection)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (version.equals(HttpVersion.HTTP_1_0) &&
|
||||
!HttpHeaders.Values.KEEP_ALIVE.equalsIgnoreCase(connection)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setKeepAlive(boolean keepAlive) {
|
||||
HttpVersion version = getProtocolVersion();
|
||||
if (!version.getProtocolName().equals("HTTP")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (version.equals(HttpVersion.HTTP_1_0)) {
|
||||
if (keepAlive) {
|
||||
setHeader(Names.CONNECTION, Values.KEEP_ALIVE);
|
||||
} else {
|
||||
removeHeader(Names.CONNECTION);
|
||||
}
|
||||
} else {
|
||||
if (keepAlive) {
|
||||
removeHeader(Names.CONNECTION);
|
||||
} else {
|
||||
setHeader(Names.CONNECTION, Values.CLOSE);
|
||||
}
|
||||
}
|
||||
return HttpHeaders.isKeepAlive(this);
|
||||
}
|
||||
|
||||
public void clearHeaders() {
|
||||
|
@ -69,9 +69,7 @@ public class DefaultHttpRequest extends DefaultHttpMessage implements HttpReques
|
||||
public String toString() {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append(getClass().getSimpleName());
|
||||
buf.append("(keepAlive: ");
|
||||
buf.append(isKeepAlive());
|
||||
buf.append(", chunked: ");
|
||||
buf.append("(chunked: ");
|
||||
buf.append(isChunked());
|
||||
buf.append(')');
|
||||
buf.append(StringUtil.NEWLINE);
|
||||
|
@ -55,9 +55,7 @@ public class DefaultHttpResponse extends DefaultHttpMessage implements HttpRespo
|
||||
public String toString() {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append(getClass().getSimpleName());
|
||||
buf.append("(keepAlive: ");
|
||||
buf.append(isKeepAlive());
|
||||
buf.append(", chunked: ");
|
||||
buf.append("(chunked: ");
|
||||
buf.append(isChunked());
|
||||
buf.append(')');
|
||||
buf.append(StringUtil.NEWLINE);
|
||||
|
@ -441,6 +441,60 @@ public class HttpHeaders {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if and only if the connection can remain open and
|
||||
* thus 'kept alive'. This methods respects the value of the
|
||||
* {@code "Connection"} header first and then the return value of
|
||||
* {@link HttpVersion#isKeepAliveDefault()}.
|
||||
*/
|
||||
public static boolean isKeepAlive(HttpMessage message) {
|
||||
String connection = message.getHeader(Names.CONNECTION);
|
||||
if (Values.CLOSE.equalsIgnoreCase(connection)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (message.getProtocolVersion().isKeepAliveDefault()) {
|
||||
return !Values.CLOSE.equalsIgnoreCase(connection);
|
||||
} else {
|
||||
return Values.KEEP_ALIVE.equalsIgnoreCase(connection);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the {@code "Connection"} header depending on the
|
||||
* protocol version of the specified message. This method sets or removes
|
||||
* the {@code "Connection"} header depending on what the default keep alive
|
||||
* mode of the message's protocol version is, as specified by
|
||||
* {@link HttpVersion#isKeepAliveDefault()}.
|
||||
* <ul>
|
||||
* <li>If the connection is kept alive by default:
|
||||
* <ul>
|
||||
* <li>set to {@code "close"} if {@code keepAlive} is {@code false}.</li>
|
||||
* <li>remove otherwise.</li>
|
||||
* </ul></li>
|
||||
* <li>If the connection is closed by default:
|
||||
* <ul>
|
||||
* <li>set to {@code "keep-alive"} if {@code keepAlive} is {@code true}.</li>
|
||||
* <li>remove otherwise.</li>
|
||||
* </ul></li>
|
||||
* </ul>
|
||||
*/
|
||||
public static void setKeepAlive(HttpMessage message, boolean keepAlive) {
|
||||
if (message.getProtocolVersion().isKeepAliveDefault()) {
|
||||
if (keepAlive) {
|
||||
message.removeHeader(Names.CONNECTION);
|
||||
} else {
|
||||
message.setHeader(Names.CONNECTION, Values.CLOSE);
|
||||
}
|
||||
} else {
|
||||
if (keepAlive) {
|
||||
message.setHeader(Names.CONNECTION, Values.KEEP_ALIVE);
|
||||
} else {
|
||||
message.removeHeader(Names.CONNECTION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Document me
|
||||
|
||||
public static void setContentLength(HttpMessage message, long value) {
|
||||
|
@ -164,38 +164,8 @@ public interface HttpMessage {
|
||||
void setChunked(boolean chunked);
|
||||
|
||||
/**
|
||||
* Returns {@code true} if and only if the connection can remain open and
|
||||
* thus 'kept alive'. In HTTP, this property is determined by the value of the
|
||||
* {@code "Connection"} header and the protocol version of this message.
|
||||
* <p>
|
||||
* Please note that the default implementation of this method only
|
||||
* understands HTTP. If the protocol version of this message indicates
|
||||
* other derived protocols such as RTSP and ICAP, it will return false by
|
||||
* default.
|
||||
* @deprecated Use {@link HttpHeaders#isKeepAlive(HttpMessage)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
boolean isKeepAlive();
|
||||
|
||||
/**
|
||||
* Sets the value of the {@code "Connection"} header depending on the
|
||||
* protocol version of this message. The default implementation sets or
|
||||
* removes the {@code "Connection"} header with the following rules:
|
||||
* <ul>
|
||||
* <li>If protocol version is HTTP/1.1 or later:
|
||||
* <ul>
|
||||
* <li>set to {@code "close"} if {@code keepAlive} is {@code false}.</li>
|
||||
* <li>remove otherwise.</li>
|
||||
* </ul></li>
|
||||
* <li>If protocol version is HTTP/1.0:
|
||||
* <ul>
|
||||
* <li>set to {@code "keep-alive"} if {@code keepAlive} is {@code true}.</li>
|
||||
* <li>remove otherwise.</li>
|
||||
* </ul></li>
|
||||
* <li>do nothing if the protocol name is not {@code "HTTP"}.</li>
|
||||
* </ul>
|
||||
* Please note that the default implementation of this method only
|
||||
* understands HTTP. If the protocol version of this message indicates
|
||||
* other derived protocols such as RTSP and ICAP, it will do nothing by
|
||||
* default.
|
||||
*/
|
||||
void setKeepAlive(boolean keepAlive);
|
||||
}
|
||||
|
@ -38,12 +38,12 @@ public class HttpVersion implements Comparable<HttpVersion> {
|
||||
/**
|
||||
* HTTP/1.0
|
||||
*/
|
||||
public static final HttpVersion HTTP_1_0 = new HttpVersion("HTTP", 1, 0);
|
||||
public static final HttpVersion HTTP_1_0 = new HttpVersion("HTTP", 1, 0, false);
|
||||
|
||||
/**
|
||||
* HTTP/1.1
|
||||
*/
|
||||
public static final HttpVersion HTTP_1_1 = new HttpVersion("HTTP", 1, 1);
|
||||
public static final HttpVersion HTTP_1_1 = new HttpVersion("HTTP", 1, 1, true);
|
||||
|
||||
/**
|
||||
* Returns an existing or new {@link HttpVersion} instance which matches to
|
||||
@ -65,13 +65,22 @@ public class HttpVersion implements Comparable<HttpVersion> {
|
||||
if (text.equals("HTTP/1.0")) {
|
||||
return HTTP_1_0;
|
||||
}
|
||||
return new HttpVersion(text);
|
||||
return new HttpVersion(text, true);
|
||||
}
|
||||
|
||||
private final String protocolName;
|
||||
private final int majorVersion;
|
||||
private final int minorVersion;
|
||||
private final String text;
|
||||
private final boolean keepAliveDefault;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #HttpVersion(String, boolean)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public HttpVersion(String text) {
|
||||
this(text, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new HTTP version with the specified version string. You will
|
||||
@ -80,7 +89,7 @@ public class HttpVersion implements Comparable<HttpVersion> {
|
||||
* <a href="http://en.wikipedia.org/wiki/Real_Time_Streaming_Protocol">RTSP</a> and
|
||||
* <a href="http://en.wikipedia.org/wiki/Internet_Content_Adaptation_Protocol">ICAP</a>.
|
||||
*/
|
||||
public HttpVersion(String text) {
|
||||
public HttpVersion(String text, boolean keepAliveDefault) {
|
||||
if (text == null) {
|
||||
throw new NullPointerException("text");
|
||||
}
|
||||
@ -99,6 +108,16 @@ public class HttpVersion implements Comparable<HttpVersion> {
|
||||
majorVersion = Integer.parseInt(m.group(2));
|
||||
minorVersion = Integer.parseInt(m.group(3));
|
||||
this.text = protocolName + '/' + majorVersion + '.' + minorVersion;
|
||||
this.keepAliveDefault = keepAliveDefault;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #HttpVersion(String, int, int, boolean)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public HttpVersion(
|
||||
String protocolName, int majorVersion, int minorVersion) {
|
||||
this(protocolName, majorVersion, minorVersion, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -109,7 +128,8 @@ public class HttpVersion implements Comparable<HttpVersion> {
|
||||
* <a href="http://en.wikipedia.org/wiki/Internet_Content_Adaptation_Protocol">ICAP</a>
|
||||
*/
|
||||
public HttpVersion(
|
||||
String protocolName, int majorVersion, int minorVersion) {
|
||||
String protocolName, int majorVersion, int minorVersion,
|
||||
boolean keepAliveDefault) {
|
||||
if (protocolName == null) {
|
||||
throw new NullPointerException("protocolName");
|
||||
}
|
||||
@ -137,6 +157,7 @@ public class HttpVersion implements Comparable<HttpVersion> {
|
||||
this.majorVersion = majorVersion;
|
||||
this.minorVersion = minorVersion;
|
||||
text = protocolName + '/' + majorVersion + '.' + minorVersion;
|
||||
this.keepAliveDefault = keepAliveDefault;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -167,6 +188,14 @@ public class HttpVersion implements Comparable<HttpVersion> {
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if and only if the connection is kept alive unless
|
||||
* the {@code "Connection"} header is set to {@code "close"} explicitly.
|
||||
*/
|
||||
public boolean isKeepAliveDefault() {
|
||||
return keepAliveDefault;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full protocol version text such as {@code "HTTP/1.0"}.
|
||||
*/
|
||||
|
@ -30,7 +30,7 @@ public final class RtspVersions {
|
||||
/**
|
||||
* RTSP/1.0
|
||||
*/
|
||||
public static final HttpVersion RTSP_1_0 = new HttpVersion("RTSP", 1, 0);
|
||||
public static final HttpVersion RTSP_1_0 = new HttpVersion("RTSP", 1, 0, true);
|
||||
|
||||
/**
|
||||
* Returns an existing or new {@link HttpVersion} instance which matches to
|
||||
@ -48,7 +48,7 @@ public final class RtspVersions {
|
||||
return RTSP_1_0;
|
||||
}
|
||||
|
||||
return new HttpVersion(text);
|
||||
return new HttpVersion(text, true);
|
||||
}
|
||||
|
||||
private RtspVersions() {
|
||||
|
Loading…
Reference in New Issue
Block a user