Backport the additional AsciiString/TextHeader changes from master
- Add useful static methods to AsciiString - Add more getters in TextHeaders - Remove unnecessary utility methods in SpdyHttpHeaders
This commit is contained in:
parent
681d460938
commit
c076c33901
@ -17,6 +17,7 @@ package io.netty.handler.codec.http;
|
|||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
|
import io.netty.handler.codec.AsciiString;
|
||||||
import io.netty.handler.codec.http.DefaultHttpHeaders.NonValidatingTextHeaders;
|
import io.netty.handler.codec.http.DefaultHttpHeaders.NonValidatingTextHeaders;
|
||||||
import io.netty.handler.codec.http.DefaultHttpHeaders.ValidatingTextHeaders;
|
import io.netty.handler.codec.http.DefaultHttpHeaders.ValidatingTextHeaders;
|
||||||
import io.netty.util.internal.StringUtil;
|
import io.netty.util.internal.StringUtil;
|
||||||
@ -113,9 +114,9 @@ public class DefaultLastHttpContent extends DefaultHttpContent implements LastHt
|
|||||||
@Override
|
@Override
|
||||||
protected CharSequence convertName(CharSequence name) {
|
protected CharSequence convertName(CharSequence name) {
|
||||||
name = super.convertName(name);
|
name = super.convertName(name);
|
||||||
if (HttpHeaders.equalsIgnoreCase(HttpHeaders.Names.CONTENT_LENGTH, name) ||
|
if (AsciiString.equalsIgnoreCase(HttpHeaders.Names.CONTENT_LENGTH, name) ||
|
||||||
HttpHeaders.equalsIgnoreCase(HttpHeaders.Names.TRANSFER_ENCODING, name) ||
|
AsciiString.equalsIgnoreCase(HttpHeaders.Names.TRANSFER_ENCODING, name) ||
|
||||||
HttpHeaders.equalsIgnoreCase(HttpHeaders.Names.TRAILER, name)) {
|
AsciiString.equalsIgnoreCase(HttpHeaders.Names.TRAILER, name)) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"prohibited trailing header: " + name);
|
"prohibited trailing header: " + name);
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package io.netty.handler.codec.http;
|
package io.netty.handler.codec.http;
|
||||||
|
|
||||||
import io.netty.channel.embedded.EmbeddedChannel;
|
import io.netty.channel.embedded.EmbeddedChannel;
|
||||||
|
import io.netty.handler.codec.AsciiString;
|
||||||
import io.netty.handler.codec.compression.ZlibCodecFactory;
|
import io.netty.handler.codec.compression.ZlibCodecFactory;
|
||||||
import io.netty.handler.codec.compression.ZlibWrapper;
|
import io.netty.handler.codec.compression.ZlibWrapper;
|
||||||
import io.netty.util.internal.StringUtil;
|
import io.netty.util.internal.StringUtil;
|
||||||
@ -96,7 +97,7 @@ public class HttpContentCompressor extends HttpContentEncoder {
|
|||||||
protected Result beginEncode(HttpResponse headers, String acceptEncoding) throws Exception {
|
protected Result beginEncode(HttpResponse headers, String acceptEncoding) throws Exception {
|
||||||
String contentEncoding = headers.headers().get(HttpHeaders.Names.CONTENT_ENCODING);
|
String contentEncoding = headers.headers().get(HttpHeaders.Names.CONTENT_ENCODING);
|
||||||
if (contentEncoding != null &&
|
if (contentEncoding != null &&
|
||||||
!HttpHeaders.equalsIgnoreCase(HttpHeaders.Values.IDENTITY, contentEncoding)) {
|
!AsciiString.equalsIgnoreCase(HttpHeaders.Values.IDENTITY, contentEncoding)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -567,14 +567,14 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
|
|||||||
*/
|
*/
|
||||||
public static boolean isKeepAlive(HttpMessage message) {
|
public static boolean isKeepAlive(HttpMessage message) {
|
||||||
String connection = message.headers().get(CONNECTION_ENTITY);
|
String connection = message.headers().get(CONNECTION_ENTITY);
|
||||||
if (connection != null && equalsIgnoreCase(CLOSE_ENTITY, connection)) {
|
if (connection != null && AsciiString.equalsIgnoreCase(CLOSE_ENTITY, connection)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.getProtocolVersion().isKeepAliveDefault()) {
|
if (message.getProtocolVersion().isKeepAliveDefault()) {
|
||||||
return !equalsIgnoreCase(CLOSE_ENTITY, connection);
|
return !AsciiString.equalsIgnoreCase(CLOSE_ENTITY, connection);
|
||||||
} else {
|
} else {
|
||||||
return equalsIgnoreCase(KEEP_ALIVE_ENTITY, connection);
|
return AsciiString.equalsIgnoreCase(KEEP_ALIVE_ENTITY, connection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1115,7 +1115,7 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
|
|||||||
if (value == null) {
|
if (value == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (equalsIgnoreCase(CONTINUE_ENTITY, value)) {
|
if (AsciiString.equalsIgnoreCase(CONTINUE_ENTITY, value)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1165,7 +1165,7 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
|
|||||||
Iterator<String> valuesIt = values.iterator();
|
Iterator<String> valuesIt = values.iterator();
|
||||||
while (valuesIt.hasNext()) {
|
while (valuesIt.hasNext()) {
|
||||||
String value = valuesIt.next();
|
String value = valuesIt.next();
|
||||||
if (equalsIgnoreCase(value, CHUNKED_ENTITY)) {
|
if (AsciiString.equalsIgnoreCase(value, CHUNKED_ENTITY)) {
|
||||||
valuesIt.remove();
|
valuesIt.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1186,39 +1186,11 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@code true} if both {@link CharSequence}'s are equals when ignore the case.
|
* @deprecated Use {@link AsciiString#equalsIgnoreCase(CharSequence, CharSequence)} instead.
|
||||||
* This only supports US_ASCII.
|
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static boolean equalsIgnoreCase(CharSequence name1, CharSequence name2) {
|
public static boolean equalsIgnoreCase(CharSequence name1, CharSequence name2) {
|
||||||
if (name1 == name2) {
|
return AsciiString.equalsIgnoreCase(name1, name2);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name1 == null || name2 == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int nameLen = name1.length();
|
|
||||||
if (nameLen != name2.length()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = nameLen - 1; i >= 0; i --) {
|
|
||||||
char c1 = name1.charAt(i);
|
|
||||||
char c2 = name2.charAt(i);
|
|
||||||
if (c1 != c2) {
|
|
||||||
if (c1 >= 'A' && c1 <= 'Z') {
|
|
||||||
c1 += 32;
|
|
||||||
}
|
|
||||||
if (c2 >= 'A' && c2 <= 'Z') {
|
|
||||||
c2 += 32;
|
|
||||||
}
|
|
||||||
if (c1 != c2) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void encode(HttpHeaders headers, ByteBuf buf) {
|
static void encode(HttpHeaders headers, ByteBuf buf) {
|
||||||
@ -1238,6 +1210,7 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
|
|||||||
buf.writeBytes(CRLF);
|
buf.writeBytes(CRLF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public static void encodeAscii(CharSequence seq, ByteBuf buf) {
|
public static void encodeAscii(CharSequence seq, ByteBuf buf) {
|
||||||
if (seq instanceof AsciiString) {
|
if (seq instanceof AsciiString) {
|
||||||
((AsciiString) seq).copy(0, buf, seq.length());
|
((AsciiString) seq).copy(0, buf, seq.length());
|
||||||
@ -1499,7 +1472,7 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
|
|||||||
|
|
||||||
for (String v: values) {
|
for (String v: values) {
|
||||||
if (ignoreCase) {
|
if (ignoreCase) {
|
||||||
if (equalsIgnoreCase(v, value)) {
|
if (AsciiString.equalsIgnoreCase(v, value)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -20,6 +20,7 @@ import io.netty.buffer.ByteBufProcessor;
|
|||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ChannelPipeline;
|
import io.netty.channel.ChannelPipeline;
|
||||||
|
import io.netty.handler.codec.AsciiString;
|
||||||
import io.netty.handler.codec.DecoderResult;
|
import io.netty.handler.codec.DecoderResult;
|
||||||
import io.netty.handler.codec.ReplayingDecoder;
|
import io.netty.handler.codec.ReplayingDecoder;
|
||||||
import io.netty.handler.codec.TooLongFrameException;
|
import io.netty.handler.codec.TooLongFrameException;
|
||||||
@ -559,9 +560,9 @@ public abstract class HttpObjectDecoder extends ReplayingDecoder<HttpObjectDecod
|
|||||||
} else {
|
} else {
|
||||||
String[] header = splitHeader(line);
|
String[] header = splitHeader(line);
|
||||||
String name = header[0];
|
String name = header[0];
|
||||||
if (!HttpHeaders.equalsIgnoreCase(name, HttpHeaders.Names.CONTENT_LENGTH) &&
|
if (!AsciiString.equalsIgnoreCase(name, HttpHeaders.Names.CONTENT_LENGTH) &&
|
||||||
!HttpHeaders.equalsIgnoreCase(name, HttpHeaders.Names.TRANSFER_ENCODING) &&
|
!AsciiString.equalsIgnoreCase(name, HttpHeaders.Names.TRANSFER_ENCODING) &&
|
||||||
!HttpHeaders.equalsIgnoreCase(name, HttpHeaders.Names.TRAILER)) {
|
!AsciiString.equalsIgnoreCase(name, HttpHeaders.Names.TRAILER)) {
|
||||||
trailer.trailingHeaders().add(name, header[1]);
|
trailer.trailingHeaders().add(name, header[1]);
|
||||||
}
|
}
|
||||||
lastHeader = name;
|
lastHeader = name;
|
||||||
|
@ -17,6 +17,7 @@ package io.netty.handler.codec.http.multipart;
|
|||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.handler.codec.AsciiString;
|
||||||
import io.netty.handler.codec.DecoderResult;
|
import io.netty.handler.codec.DecoderResult;
|
||||||
import io.netty.handler.codec.http.DefaultFullHttpRequest;
|
import io.netty.handler.codec.http.DefaultFullHttpRequest;
|
||||||
import io.netty.handler.codec.http.DefaultHttpContent;
|
import io.netty.handler.codec.http.DefaultHttpContent;
|
||||||
@ -741,7 +742,7 @@ public class HttpPostRequestEncoder implements ChunkedInput<HttpContent> {
|
|||||||
if (transferEncoding != null) {
|
if (transferEncoding != null) {
|
||||||
headers.remove(HttpHeaders.Names.TRANSFER_ENCODING);
|
headers.remove(HttpHeaders.Names.TRANSFER_ENCODING);
|
||||||
for (String v : transferEncoding) {
|
for (String v : transferEncoding) {
|
||||||
if (HttpHeaders.equalsIgnoreCase(v, HttpHeaders.Values.CHUNKED)) {
|
if (AsciiString.equalsIgnoreCase(v, HttpHeaders.Values.CHUNKED)) {
|
||||||
// ignore
|
// ignore
|
||||||
} else {
|
} else {
|
||||||
headers.add(HttpHeaders.Names.TRANSFER_ENCODING, v);
|
headers.add(HttpHeaders.Names.TRANSFER_ENCODING, v);
|
||||||
|
@ -17,6 +17,7 @@ package io.netty.handler.codec.http.websocketx;
|
|||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
|
import io.netty.handler.codec.AsciiString;
|
||||||
import io.netty.handler.codec.http.DefaultFullHttpRequest;
|
import io.netty.handler.codec.http.DefaultFullHttpRequest;
|
||||||
import io.netty.handler.codec.http.FullHttpRequest;
|
import io.netty.handler.codec.http.FullHttpRequest;
|
||||||
import io.netty.handler.codec.http.FullHttpResponse;
|
import io.netty.handler.codec.http.FullHttpResponse;
|
||||||
@ -198,13 +199,13 @@ public class WebSocketClientHandshaker00 extends WebSocketClientHandshaker {
|
|||||||
HttpHeaders headers = response.headers();
|
HttpHeaders headers = response.headers();
|
||||||
|
|
||||||
String upgrade = headers.get(Names.UPGRADE);
|
String upgrade = headers.get(Names.UPGRADE);
|
||||||
if (!HttpHeaders.equalsIgnoreCase(Values.WEBSOCKET, upgrade)) {
|
if (!AsciiString.equalsIgnoreCase(Values.WEBSOCKET, upgrade)) {
|
||||||
throw new WebSocketHandshakeException("Invalid handshake response upgrade: "
|
throw new WebSocketHandshakeException("Invalid handshake response upgrade: "
|
||||||
+ upgrade);
|
+ upgrade);
|
||||||
}
|
}
|
||||||
|
|
||||||
String connection = headers.get(Names.CONNECTION);
|
String connection = headers.get(Names.CONNECTION);
|
||||||
if (!HttpHeaders.equalsIgnoreCase(Values.UPGRADE, connection)) {
|
if (!AsciiString.equalsIgnoreCase(Values.UPGRADE, connection)) {
|
||||||
throw new WebSocketHandshakeException("Invalid handshake response connection: "
|
throw new WebSocketHandshakeException("Invalid handshake response connection: "
|
||||||
+ connection);
|
+ connection);
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.codec.http.websocketx;
|
package io.netty.handler.codec.http.websocketx;
|
||||||
|
|
||||||
|
import io.netty.handler.codec.AsciiString;
|
||||||
import io.netty.handler.codec.http.DefaultFullHttpRequest;
|
import io.netty.handler.codec.http.DefaultFullHttpRequest;
|
||||||
import io.netty.handler.codec.http.FullHttpRequest;
|
import io.netty.handler.codec.http.FullHttpRequest;
|
||||||
import io.netty.handler.codec.http.FullHttpResponse;
|
import io.netty.handler.codec.http.FullHttpResponse;
|
||||||
@ -173,12 +174,12 @@ public class WebSocketClientHandshaker07 extends WebSocketClientHandshaker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String upgrade = headers.get(Names.UPGRADE);
|
String upgrade = headers.get(Names.UPGRADE);
|
||||||
if (!HttpHeaders.equalsIgnoreCase(Values.WEBSOCKET, upgrade)) {
|
if (!AsciiString.equalsIgnoreCase(Values.WEBSOCKET, upgrade)) {
|
||||||
throw new WebSocketHandshakeException("Invalid handshake response upgrade: " + upgrade);
|
throw new WebSocketHandshakeException("Invalid handshake response upgrade: " + upgrade);
|
||||||
}
|
}
|
||||||
|
|
||||||
String connection = headers.get(Names.CONNECTION);
|
String connection = headers.get(Names.CONNECTION);
|
||||||
if (!HttpHeaders.equalsIgnoreCase(Values.UPGRADE, connection)) {
|
if (!AsciiString.equalsIgnoreCase(Values.UPGRADE, connection)) {
|
||||||
throw new WebSocketHandshakeException("Invalid handshake response connection: " + connection);
|
throw new WebSocketHandshakeException("Invalid handshake response connection: " + connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.codec.http.websocketx;
|
package io.netty.handler.codec.http.websocketx;
|
||||||
|
|
||||||
|
import io.netty.handler.codec.AsciiString;
|
||||||
import io.netty.handler.codec.http.DefaultFullHttpRequest;
|
import io.netty.handler.codec.http.DefaultFullHttpRequest;
|
||||||
import io.netty.handler.codec.http.FullHttpRequest;
|
import io.netty.handler.codec.http.FullHttpRequest;
|
||||||
import io.netty.handler.codec.http.FullHttpResponse;
|
import io.netty.handler.codec.http.FullHttpResponse;
|
||||||
@ -174,12 +175,12 @@ public class WebSocketClientHandshaker08 extends WebSocketClientHandshaker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String upgrade = headers.get(Names.UPGRADE);
|
String upgrade = headers.get(Names.UPGRADE);
|
||||||
if (!HttpHeaders.equalsIgnoreCase(Values.WEBSOCKET, upgrade)) {
|
if (!AsciiString.equalsIgnoreCase(Values.WEBSOCKET, upgrade)) {
|
||||||
throw new WebSocketHandshakeException("Invalid handshake response upgrade: " + upgrade);
|
throw new WebSocketHandshakeException("Invalid handshake response upgrade: " + upgrade);
|
||||||
}
|
}
|
||||||
|
|
||||||
String connection = headers.get(Names.CONNECTION);
|
String connection = headers.get(Names.CONNECTION);
|
||||||
if (!HttpHeaders.equalsIgnoreCase(Values.UPGRADE, connection)) {
|
if (!AsciiString.equalsIgnoreCase(Values.UPGRADE, connection)) {
|
||||||
throw new WebSocketHandshakeException("Invalid handshake response connection: " + connection);
|
throw new WebSocketHandshakeException("Invalid handshake response connection: " + connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.codec.http.websocketx;
|
package io.netty.handler.codec.http.websocketx;
|
||||||
|
|
||||||
|
import io.netty.handler.codec.AsciiString;
|
||||||
import io.netty.handler.codec.http.DefaultFullHttpRequest;
|
import io.netty.handler.codec.http.DefaultFullHttpRequest;
|
||||||
import io.netty.handler.codec.http.FullHttpRequest;
|
import io.netty.handler.codec.http.FullHttpRequest;
|
||||||
import io.netty.handler.codec.http.FullHttpResponse;
|
import io.netty.handler.codec.http.FullHttpResponse;
|
||||||
@ -184,12 +185,12 @@ public class WebSocketClientHandshaker13 extends WebSocketClientHandshaker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String upgrade = headers.get(Names.UPGRADE);
|
String upgrade = headers.get(Names.UPGRADE);
|
||||||
if (!HttpHeaders.equalsIgnoreCase(Values.WEBSOCKET, upgrade)) {
|
if (!AsciiString.equalsIgnoreCase(Values.WEBSOCKET, upgrade)) {
|
||||||
throw new WebSocketHandshakeException("Invalid handshake response upgrade: " + upgrade);
|
throw new WebSocketHandshakeException("Invalid handshake response upgrade: " + upgrade);
|
||||||
}
|
}
|
||||||
|
|
||||||
String connection = headers.get(Names.CONNECTION);
|
String connection = headers.get(Names.CONNECTION);
|
||||||
if (!HttpHeaders.equalsIgnoreCase(Values.UPGRADE, connection)) {
|
if (!AsciiString.equalsIgnoreCase(Values.UPGRADE, connection)) {
|
||||||
throw new WebSocketHandshakeException("Invalid handshake response connection: " + connection);
|
throw new WebSocketHandshakeException("Invalid handshake response connection: " + connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ import io.netty.buffer.Unpooled;
|
|||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.ChannelPromise;
|
import io.netty.channel.ChannelPromise;
|
||||||
|
import io.netty.handler.codec.AsciiString;
|
||||||
import io.netty.handler.codec.http.DefaultFullHttpResponse;
|
import io.netty.handler.codec.http.DefaultFullHttpResponse;
|
||||||
import io.netty.handler.codec.http.FullHttpRequest;
|
import io.netty.handler.codec.http.FullHttpRequest;
|
||||||
import io.netty.handler.codec.http.FullHttpResponse;
|
import io.netty.handler.codec.http.FullHttpResponse;
|
||||||
@ -109,8 +110,8 @@ public class WebSocketServerHandshaker00 extends WebSocketServerHandshaker {
|
|||||||
protected FullHttpResponse newHandshakeResponse(FullHttpRequest req, HttpHeaders headers) {
|
protected FullHttpResponse newHandshakeResponse(FullHttpRequest req, HttpHeaders headers) {
|
||||||
|
|
||||||
// Serve the WebSocket handshake request.
|
// Serve the WebSocket handshake request.
|
||||||
if (!HttpHeaders.equalsIgnoreCase(Values.UPGRADE, req.headers().get(CONNECTION))
|
if (!AsciiString.equalsIgnoreCase(Values.UPGRADE, req.headers().get(CONNECTION))
|
||||||
|| !HttpHeaders.equalsIgnoreCase(WEBSOCKET, req.headers().get(Names.UPGRADE))) {
|
|| !AsciiString.equalsIgnoreCase(WEBSOCKET, req.headers().get(Names.UPGRADE))) {
|
||||||
throw new WebSocketHandshakeException("not a WebSocket handshake request: missing upgrade");
|
throw new WebSocketHandshakeException("not a WebSocket handshake request: missing upgrade");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ import io.netty.handler.codec.http.HttpHeaders;
|
|||||||
import io.netty.handler.codec.http.HttpMethod;
|
import io.netty.handler.codec.http.HttpMethod;
|
||||||
import io.netty.handler.codec.http.HttpResponseStatus;
|
import io.netty.handler.codec.http.HttpResponseStatus;
|
||||||
import io.netty.handler.codec.http.HttpVersion;
|
import io.netty.handler.codec.http.HttpVersion;
|
||||||
|
import io.netty.handler.codec.spdy.SpdyHttpHeaders.Names;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -138,10 +139,11 @@ public class SpdyHttpDecoder extends MessageToMessageDecoder<SpdyFrame> {
|
|||||||
createHttpResponse(spdyVersion, spdySynStreamFrame);
|
createHttpResponse(spdyVersion, spdySynStreamFrame);
|
||||||
|
|
||||||
// Set the Stream-ID, Associated-To-Stream-ID, Priority, and URL as headers
|
// Set the Stream-ID, Associated-To-Stream-ID, Priority, and URL as headers
|
||||||
SpdyHttpHeaders.setStreamId(httpResponseWithEntity, streamId);
|
HttpHeaders.setIntHeader(httpResponseWithEntity, Names.STREAM_ID, streamId);
|
||||||
SpdyHttpHeaders.setAssociatedToStreamId(httpResponseWithEntity, associatedToStreamId);
|
HttpHeaders.setIntHeader(
|
||||||
SpdyHttpHeaders.setPriority(httpResponseWithEntity, spdySynStreamFrame.getPriority());
|
httpResponseWithEntity, Names.ASSOCIATED_TO_STREAM_ID, associatedToStreamId);
|
||||||
SpdyHttpHeaders.setUrl(httpResponseWithEntity, URL);
|
HttpHeaders.setIntHeader(httpResponseWithEntity, Names.PRIORITY, spdySynStreamFrame.getPriority());
|
||||||
|
httpResponseWithEntity.headers().set(Names.URL, URL);
|
||||||
|
|
||||||
if (spdySynStreamFrame.isLast()) {
|
if (spdySynStreamFrame.isLast()) {
|
||||||
HttpHeaders.setContentLength(httpResponseWithEntity, 0);
|
HttpHeaders.setContentLength(httpResponseWithEntity, 0);
|
||||||
@ -174,7 +176,7 @@ public class SpdyHttpDecoder extends MessageToMessageDecoder<SpdyFrame> {
|
|||||||
FullHttpRequest httpRequestWithEntity = createHttpRequest(spdyVersion, spdySynStreamFrame);
|
FullHttpRequest httpRequestWithEntity = createHttpRequest(spdyVersion, spdySynStreamFrame);
|
||||||
|
|
||||||
// Set the Stream-ID as a header
|
// Set the Stream-ID as a header
|
||||||
SpdyHttpHeaders.setStreamId(httpRequestWithEntity, streamId);
|
HttpHeaders.setIntHeader(httpRequestWithEntity, Names.STREAM_ID, streamId);
|
||||||
|
|
||||||
if (spdySynStreamFrame.isLast()) {
|
if (spdySynStreamFrame.isLast()) {
|
||||||
out.add(httpRequestWithEntity);
|
out.add(httpRequestWithEntity);
|
||||||
@ -213,7 +215,7 @@ public class SpdyHttpDecoder extends MessageToMessageDecoder<SpdyFrame> {
|
|||||||
FullHttpResponse httpResponseWithEntity = createHttpResponse(spdyVersion, spdySynReplyFrame);
|
FullHttpResponse httpResponseWithEntity = createHttpResponse(spdyVersion, spdySynReplyFrame);
|
||||||
|
|
||||||
// Set the Stream-ID as a header
|
// Set the Stream-ID as a header
|
||||||
SpdyHttpHeaders.setStreamId(httpResponseWithEntity, streamId);
|
HttpHeaders.setIntHeader(httpResponseWithEntity, Names.STREAM_ID, streamId);
|
||||||
|
|
||||||
if (spdySynReplyFrame.isLast()) {
|
if (spdySynReplyFrame.isLast()) {
|
||||||
HttpHeaders.setContentLength(httpResponseWithEntity, 0);
|
HttpHeaders.setContentLength(httpResponseWithEntity, 0);
|
||||||
|
@ -27,6 +27,7 @@ import io.netty.handler.codec.http.HttpObject;
|
|||||||
import io.netty.handler.codec.http.HttpRequest;
|
import io.netty.handler.codec.http.HttpRequest;
|
||||||
import io.netty.handler.codec.http.HttpResponse;
|
import io.netty.handler.codec.http.HttpResponse;
|
||||||
import io.netty.handler.codec.http.LastHttpContent;
|
import io.netty.handler.codec.http.LastHttpContent;
|
||||||
|
import io.netty.handler.codec.spdy.SpdyHttpHeaders.Names;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -207,23 +208,24 @@ public class SpdyHttpEncoder extends MessageToMessageEncoder<HttpObject> {
|
|||||||
private SpdySynStreamFrame createSynStreamFrame(HttpMessage httpMessage)
|
private SpdySynStreamFrame createSynStreamFrame(HttpMessage httpMessage)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
// Get the Stream-ID, Associated-To-Stream-ID, Priority, URL, and scheme from the headers
|
// Get the Stream-ID, Associated-To-Stream-ID, Priority, URL, and scheme from the headers
|
||||||
int streamID = SpdyHttpHeaders.getStreamId(httpMessage);
|
final HttpHeaders httpHeaders = httpMessage.headers();
|
||||||
int associatedToStreamId = SpdyHttpHeaders.getAssociatedToStreamId(httpMessage);
|
int streamID = HttpHeaders.getIntHeader(httpMessage, Names.STREAM_ID);
|
||||||
byte priority = SpdyHttpHeaders.getPriority(httpMessage);
|
int associatedToStreamId = HttpHeaders.getIntHeader(httpMessage, Names.ASSOCIATED_TO_STREAM_ID, 0);
|
||||||
String URL = SpdyHttpHeaders.getUrl(httpMessage);
|
byte priority = (byte) HttpHeaders.getIntHeader(httpMessage, Names.PRIORITY, 0);
|
||||||
String scheme = SpdyHttpHeaders.getScheme(httpMessage);
|
String URL = httpHeaders.get(Names.URL);
|
||||||
SpdyHttpHeaders.removeStreamId(httpMessage);
|
String scheme = httpHeaders.get(Names.SCHEME);
|
||||||
SpdyHttpHeaders.removeAssociatedToStreamId(httpMessage);
|
httpHeaders.remove(Names.STREAM_ID);
|
||||||
SpdyHttpHeaders.removePriority(httpMessage);
|
httpHeaders.remove(Names.ASSOCIATED_TO_STREAM_ID);
|
||||||
SpdyHttpHeaders.removeUrl(httpMessage);
|
httpHeaders.remove(Names.PRIORITY);
|
||||||
SpdyHttpHeaders.removeScheme(httpMessage);
|
httpHeaders.remove(Names.URL);
|
||||||
|
httpHeaders.remove(Names.SCHEME);
|
||||||
|
|
||||||
// The Connection, Keep-Alive, Proxy-Connection, and Transfer-Encoding
|
// The Connection, Keep-Alive, Proxy-Connection, and Transfer-Encoding
|
||||||
// headers are not valid and MUST not be sent.
|
// headers are not valid and MUST not be sent.
|
||||||
httpMessage.headers().remove(HttpHeaders.Names.CONNECTION);
|
httpHeaders.remove(HttpHeaders.Names.CONNECTION);
|
||||||
httpMessage.headers().remove("Keep-Alive");
|
httpHeaders.remove("Keep-Alive");
|
||||||
httpMessage.headers().remove("Proxy-Connection");
|
httpHeaders.remove("Proxy-Connection");
|
||||||
httpMessage.headers().remove(HttpHeaders.Names.TRANSFER_ENCODING);
|
httpHeaders.remove(HttpHeaders.Names.TRANSFER_ENCODING);
|
||||||
|
|
||||||
SpdySynStreamFrame spdySynStreamFrame =
|
SpdySynStreamFrame spdySynStreamFrame =
|
||||||
new DefaultSpdySynStreamFrame(streamID, associatedToStreamId, priority);
|
new DefaultSpdySynStreamFrame(streamID, associatedToStreamId, priority);
|
||||||
@ -247,7 +249,7 @@ public class SpdyHttpEncoder extends MessageToMessageEncoder<HttpObject> {
|
|||||||
// Replace the HTTP host header with the SPDY host header
|
// Replace the HTTP host header with the SPDY host header
|
||||||
if (spdyVersion >= 3) {
|
if (spdyVersion >= 3) {
|
||||||
String host = HttpHeaders.getHost(httpMessage);
|
String host = HttpHeaders.getHost(httpMessage);
|
||||||
httpMessage.headers().remove(HttpHeaders.Names.HOST);
|
httpHeaders.remove(HttpHeaders.Names.HOST);
|
||||||
frameHeaders.set(HOST, host);
|
frameHeaders.set(HOST, host);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,7 +260,7 @@ public class SpdyHttpEncoder extends MessageToMessageEncoder<HttpObject> {
|
|||||||
frameHeaders.set(SCHEME, scheme);
|
frameHeaders.set(SCHEME, scheme);
|
||||||
|
|
||||||
// Transfer the remaining HTTP headers
|
// Transfer the remaining HTTP headers
|
||||||
for (Map.Entry<String, String> entry: httpMessage.headers()) {
|
for (Map.Entry<String, String> entry: httpHeaders) {
|
||||||
frameHeaders.add(entry.getKey(), entry.getValue());
|
frameHeaders.add(entry.getKey(), entry.getValue());
|
||||||
}
|
}
|
||||||
currentStreamId = spdySynStreamFrame.getStreamId();
|
currentStreamId = spdySynStreamFrame.getStreamId();
|
||||||
@ -270,15 +272,16 @@ public class SpdyHttpEncoder extends MessageToMessageEncoder<HttpObject> {
|
|||||||
private SpdySynReplyFrame createSynReplyFrame(HttpResponse httpResponse)
|
private SpdySynReplyFrame createSynReplyFrame(HttpResponse httpResponse)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
// Get the Stream-ID from the headers
|
// Get the Stream-ID from the headers
|
||||||
int streamID = SpdyHttpHeaders.getStreamId(httpResponse);
|
final HttpHeaders httpHeaders = httpResponse.headers();
|
||||||
SpdyHttpHeaders.removeStreamId(httpResponse);
|
int streamID = HttpHeaders.getIntHeader(httpResponse, Names.STREAM_ID);
|
||||||
|
httpHeaders.remove(Names.STREAM_ID);
|
||||||
|
|
||||||
// The Connection, Keep-Alive, Proxy-Connection, and Transfer-Encoding
|
// The Connection, Keep-Alive, Proxy-Connection, and Transfer-Encoding
|
||||||
// headers are not valid and MUST not be sent.
|
// headers are not valid and MUST not be sent.
|
||||||
httpResponse.headers().remove(HttpHeaders.Names.CONNECTION);
|
httpHeaders.remove(HttpHeaders.Names.CONNECTION);
|
||||||
httpResponse.headers().remove("Keep-Alive");
|
httpHeaders.remove("Keep-Alive");
|
||||||
httpResponse.headers().remove("Proxy-Connection");
|
httpHeaders.remove("Proxy-Connection");
|
||||||
httpResponse.headers().remove(HttpHeaders.Names.TRANSFER_ENCODING);
|
httpHeaders.remove(HttpHeaders.Names.TRANSFER_ENCODING);
|
||||||
|
|
||||||
SpdySynReplyFrame spdySynReplyFrame = new DefaultSpdySynReplyFrame(streamID);
|
SpdySynReplyFrame spdySynReplyFrame = new DefaultSpdySynReplyFrame(streamID);
|
||||||
SpdyHeaders frameHeaders = spdySynReplyFrame.headers();
|
SpdyHeaders frameHeaders = spdySynReplyFrame.headers();
|
||||||
@ -287,7 +290,7 @@ public class SpdyHttpEncoder extends MessageToMessageEncoder<HttpObject> {
|
|||||||
frameHeaders.set(VERSION, httpResponse.getProtocolVersion());
|
frameHeaders.set(VERSION, httpResponse.getProtocolVersion());
|
||||||
|
|
||||||
// Transfer the remaining HTTP headers
|
// Transfer the remaining HTTP headers
|
||||||
for (Map.Entry<String, String> entry: httpResponse.headers()) {
|
for (Map.Entry<String, String> entry: httpHeaders) {
|
||||||
spdySynReplyFrame.headers().add(entry.getKey(), entry.getValue());
|
spdySynReplyFrame.headers().add(entry.getKey(), entry.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,8 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.codec.spdy;
|
package io.netty.handler.codec.spdy;
|
||||||
|
|
||||||
import io.netty.handler.codec.http.HttpHeaders;
|
import io.netty.handler.codec.AsciiString;
|
||||||
import io.netty.handler.codec.http.HttpMessage;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the constants for the header names and the utility methods
|
* Provides the constants for the header names and the utility methods
|
||||||
@ -31,138 +30,26 @@ public final class SpdyHttpHeaders {
|
|||||||
/**
|
/**
|
||||||
* {@code "X-SPDY-Stream-ID"}
|
* {@code "X-SPDY-Stream-ID"}
|
||||||
*/
|
*/
|
||||||
public static final String STREAM_ID = "X-SPDY-Stream-ID";
|
public static final AsciiString STREAM_ID = new AsciiString("X-SPDY-Stream-ID");
|
||||||
/**
|
/**
|
||||||
* {@code "X-SPDY-Associated-To-Stream-ID"}
|
* {@code "X-SPDY-Associated-To-Stream-ID"}
|
||||||
*/
|
*/
|
||||||
public static final String ASSOCIATED_TO_STREAM_ID = "X-SPDY-Associated-To-Stream-ID";
|
public static final AsciiString ASSOCIATED_TO_STREAM_ID = new AsciiString("X-SPDY-Associated-To-Stream-ID");
|
||||||
/**
|
/**
|
||||||
* {@code "X-SPDY-Priority"}
|
* {@code "X-SPDY-Priority"}
|
||||||
*/
|
*/
|
||||||
public static final String PRIORITY = "X-SPDY-Priority";
|
public static final AsciiString PRIORITY = new AsciiString("X-SPDY-Priority");
|
||||||
/**
|
/**
|
||||||
* {@code "X-SPDY-URL"}
|
* {@code "X-SPDY-URL"}
|
||||||
*/
|
*/
|
||||||
public static final String URL = "X-SPDY-URL";
|
public static final AsciiString URL = new AsciiString("X-SPDY-URL");
|
||||||
/**
|
/**
|
||||||
* {@code "X-SPDY-Scheme"}
|
* {@code "X-SPDY-Scheme"}
|
||||||
*/
|
*/
|
||||||
public static final String SCHEME = "X-SPDY-Scheme";
|
public static final AsciiString SCHEME = new AsciiString("X-SPDY-Scheme");
|
||||||
|
|
||||||
private Names() { }
|
private Names() { }
|
||||||
}
|
}
|
||||||
|
|
||||||
private SpdyHttpHeaders() {
|
private SpdyHttpHeaders() { }
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the {@code "X-SPDY-Stream-ID"} header.
|
|
||||||
*/
|
|
||||||
public static void removeStreamId(HttpMessage message) {
|
|
||||||
message.headers().remove(Names.STREAM_ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the value of the {@code "X-SPDY-Stream-ID"} header.
|
|
||||||
*/
|
|
||||||
public static int getStreamId(HttpMessage message) {
|
|
||||||
return HttpHeaders.getIntHeader(message, Names.STREAM_ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the {@code "X-SPDY-Stream-ID"} header.
|
|
||||||
*/
|
|
||||||
public static void setStreamId(HttpMessage message, int streamId) {
|
|
||||||
HttpHeaders.setIntHeader(message, Names.STREAM_ID, streamId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the {@code "X-SPDY-Associated-To-Stream-ID"} header.
|
|
||||||
*/
|
|
||||||
public static void removeAssociatedToStreamId(HttpMessage message) {
|
|
||||||
message.headers().remove(Names.ASSOCIATED_TO_STREAM_ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the value of the {@code "X-SPDY-Associated-To-Stream-ID"} header.
|
|
||||||
*
|
|
||||||
* @return the header value or {@code 0} if there is no such header or
|
|
||||||
* if the header value is not a number
|
|
||||||
*/
|
|
||||||
public static int getAssociatedToStreamId(HttpMessage message) {
|
|
||||||
return HttpHeaders.getIntHeader(message, Names.ASSOCIATED_TO_STREAM_ID, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the {@code "X-SPDY-Associated-To-Stream-ID"} header.
|
|
||||||
*/
|
|
||||||
public static void setAssociatedToStreamId(HttpMessage message, int associatedToStreamId) {
|
|
||||||
HttpHeaders.setIntHeader(message, Names.ASSOCIATED_TO_STREAM_ID, associatedToStreamId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the {@code "X-SPDY-Priority"} header.
|
|
||||||
*/
|
|
||||||
public static void removePriority(HttpMessage message) {
|
|
||||||
message.headers().remove(Names.PRIORITY);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the value of the {@code "X-SPDY-Priority"} header.
|
|
||||||
*
|
|
||||||
* @return the header value or {@code 0} if there is no such header or
|
|
||||||
* if the header value is not a number
|
|
||||||
*/
|
|
||||||
public static byte getPriority(HttpMessage message) {
|
|
||||||
return (byte) HttpHeaders.getIntHeader(message, Names.PRIORITY, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the {@code "X-SPDY-Priority"} header.
|
|
||||||
*/
|
|
||||||
public static void setPriority(HttpMessage message, byte priority) {
|
|
||||||
HttpHeaders.setIntHeader(message, Names.PRIORITY, priority);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the {@code "X-SPDY-URL"} header.
|
|
||||||
*/
|
|
||||||
public static void removeUrl(HttpMessage message) {
|
|
||||||
message.headers().remove(Names.URL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the value of the {@code "X-SPDY-URL"} header.
|
|
||||||
*/
|
|
||||||
public static String getUrl(HttpMessage message) {
|
|
||||||
return message.headers().get(Names.URL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the {@code "X-SPDY-URL"} header.
|
|
||||||
*/
|
|
||||||
public static void setUrl(HttpMessage message, String url) {
|
|
||||||
message.headers().set(Names.URL, url);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the {@code "X-SPDY-Scheme"} header.
|
|
||||||
*/
|
|
||||||
public static void removeScheme(HttpMessage message) {
|
|
||||||
message.headers().remove(Names.SCHEME);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the value of the {@code "X-SPDY-Scheme"} header.
|
|
||||||
*/
|
|
||||||
public static String getScheme(HttpMessage message) {
|
|
||||||
return message.headers().get(Names.SCHEME);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the {@code "X-SPDY-Scheme"} header.
|
|
||||||
*/
|
|
||||||
public static void setScheme(HttpMessage message, String scheme) {
|
|
||||||
message.headers().set(Names.SCHEME, scheme);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,9 @@ package io.netty.handler.codec.spdy;
|
|||||||
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.handler.codec.MessageToMessageCodec;
|
import io.netty.handler.codec.MessageToMessageCodec;
|
||||||
|
import io.netty.handler.codec.http.HttpHeaders;
|
||||||
import io.netty.handler.codec.http.HttpMessage;
|
import io.netty.handler.codec.http.HttpMessage;
|
||||||
|
import io.netty.handler.codec.spdy.SpdyHttpHeaders.Names;
|
||||||
import io.netty.util.ReferenceCountUtil;
|
import io.netty.util.ReferenceCountUtil;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@ -43,7 +45,7 @@ public class SpdyHttpResponseStreamIdHandler extends
|
|||||||
protected void encode(ChannelHandlerContext ctx, HttpMessage msg, List<Object> out) throws Exception {
|
protected void encode(ChannelHandlerContext ctx, HttpMessage msg, List<Object> out) throws Exception {
|
||||||
Integer id = ids.poll();
|
Integer id = ids.poll();
|
||||||
if (id != null && id.intValue() != NO_ID && !msg.headers().contains(SpdyHttpHeaders.Names.STREAM_ID)) {
|
if (id != null && id.intValue() != NO_ID && !msg.headers().contains(SpdyHttpHeaders.Names.STREAM_ID)) {
|
||||||
SpdyHttpHeaders.setStreamId(msg, id);
|
HttpHeaders.setIntHeader(msg, Names.STREAM_ID, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
out.add(ReferenceCountUtil.retain(msg));
|
out.add(ReferenceCountUtil.retain(msg));
|
||||||
@ -56,7 +58,7 @@ public class SpdyHttpResponseStreamIdHandler extends
|
|||||||
if (!contains) {
|
if (!contains) {
|
||||||
ids.add(NO_ID);
|
ids.add(NO_ID);
|
||||||
} else {
|
} else {
|
||||||
ids.add(SpdyHttpHeaders.getStreamId((HttpMessage) msg));
|
ids.add(HttpHeaders.getIntHeader((HttpMessage) msg, Names.STREAM_ID));
|
||||||
}
|
}
|
||||||
} else if (msg instanceof SpdyRstStreamFrame) {
|
} else if (msg instanceof SpdyRstStreamFrame) {
|
||||||
ids.remove(((SpdyRstStreamFrame) msg).getStreamId());
|
ids.remove(((SpdyRstStreamFrame) msg).getStreamId());
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.codec.http;
|
package io.netty.handler.codec.http;
|
||||||
|
|
||||||
|
import io.netty.handler.codec.AsciiString;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -50,9 +51,9 @@ public class HttpHeadersTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEquansIgnoreCase() {
|
public void testEquansIgnoreCase() {
|
||||||
assertThat(HttpHeaders.equalsIgnoreCase(null, null), is(true));
|
assertThat(AsciiString.equalsIgnoreCase(null, null), is(true));
|
||||||
assertThat(HttpHeaders.equalsIgnoreCase(null, "foo"), is(false));
|
assertThat(AsciiString.equalsIgnoreCase(null, "foo"), is(false));
|
||||||
assertThat(HttpHeaders.equalsIgnoreCase("bar", null), is(false));
|
assertThat(AsciiString.equalsIgnoreCase("bar", null), is(false));
|
||||||
assertThat(HttpHeaders.equalsIgnoreCase("FoO", "fOo"), is(true));
|
assertThat(AsciiString.equalsIgnoreCase("FoO", "fOo"), is(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,8 +35,12 @@ public final class AsciiString implements CharSequence, Comparable<CharSequence>
|
|||||||
|
|
||||||
public static final AsciiString EMPTY_STRING = new AsciiString("");
|
public static final AsciiString EMPTY_STRING = new AsciiString("");
|
||||||
|
|
||||||
/** XXX: Make sure that this method and {@link #hashCode()} uses the same hashing algorithm */
|
/**
|
||||||
static int hashCode(CharSequence value) {
|
* Returns the case-insensitive hash code of the specified string. Note that this method uses the same hashing
|
||||||
|
* algorithm with {@link #hashCode()} so that you can put both {@link AsciiString}s and arbitrary
|
||||||
|
* {@link CharSequence}s into the same {@link TextHeaders}.
|
||||||
|
*/
|
||||||
|
public static int caseInsensitiveHashCode(CharSequence value) {
|
||||||
if (value instanceof AsciiString) {
|
if (value instanceof AsciiString) {
|
||||||
return value.hashCode();
|
return value.hashCode();
|
||||||
}
|
}
|
||||||
@ -50,6 +54,57 @@ public final class AsciiString implements CharSequence, Comparable<CharSequence>
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@code true} if both {@link CharSequence}'s are equals when ignore the case.
|
||||||
|
* This only supports 8-bit ASCII.
|
||||||
|
*/
|
||||||
|
public static boolean equalsIgnoreCase(CharSequence a, CharSequence b) {
|
||||||
|
if (a == b) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a instanceof AsciiString) {
|
||||||
|
AsciiString aa = (AsciiString) a;
|
||||||
|
return aa.equalsIgnoreCase(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b instanceof AsciiString) {
|
||||||
|
AsciiString ab = (AsciiString) b;
|
||||||
|
return ab.equalsIgnoreCase(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a == null || b == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.toString().equalsIgnoreCase(b.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@code true} if both {@link CharSequence}'s are equals. This only supports 8-bit ASCII.
|
||||||
|
*/
|
||||||
|
public static boolean equals(CharSequence a, CharSequence b) {
|
||||||
|
if (a == b) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a instanceof AsciiString) {
|
||||||
|
AsciiString aa = (AsciiString) a;
|
||||||
|
return aa.equals(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b instanceof AsciiString) {
|
||||||
|
AsciiString ab = (AsciiString) b;
|
||||||
|
return ab.equals(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a == null || b == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.equals(b);
|
||||||
|
}
|
||||||
|
|
||||||
private final byte[] value;
|
private final byte[] value;
|
||||||
private String string;
|
private String string;
|
||||||
private int hash;
|
private int hash;
|
||||||
|
@ -19,6 +19,7 @@ package io.netty.handler.codec;
|
|||||||
import io.netty.util.internal.PlatformDependent;
|
import io.netty.util.internal.PlatformDependent;
|
||||||
|
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
|
import java.text.ParseException;
|
||||||
import java.text.ParsePosition;
|
import java.text.ParsePosition;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -59,7 +60,7 @@ public class DefaultTextHeaders implements TextHeaders {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected int hashCode(CharSequence name) {
|
protected int hashCode(CharSequence name) {
|
||||||
return AsciiString.hashCode(name);
|
return AsciiString.caseInsensitiveHashCode(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected CharSequence convertName(CharSequence name) {
|
protected CharSequence convertName(CharSequence name) {
|
||||||
@ -376,6 +377,20 @@ public class DefaultTextHeaders implements TextHeaders {
|
|||||||
return v.toString();
|
return v.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getInt(CharSequence name) {
|
||||||
|
CharSequence v = getUnconverted(name);
|
||||||
|
if (v == null) {
|
||||||
|
throw new NoSuchElementException(String.valueOf(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v instanceof AsciiString) {
|
||||||
|
return ((AsciiString) v).parseInt();
|
||||||
|
} else {
|
||||||
|
return Integer.parseInt(v.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getInt(CharSequence name, int defaultValue) {
|
public int getInt(CharSequence name, int defaultValue) {
|
||||||
CharSequence v = getUnconverted(name);
|
CharSequence v = getUnconverted(name);
|
||||||
@ -394,6 +409,20 @@ public class DefaultTextHeaders implements TextHeaders {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getLong(CharSequence name) {
|
||||||
|
CharSequence v = getUnconverted(name);
|
||||||
|
if (v == null) {
|
||||||
|
throw new NoSuchElementException(String.valueOf(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v instanceof AsciiString) {
|
||||||
|
return ((AsciiString) v).parseLong();
|
||||||
|
} else {
|
||||||
|
return Long.parseLong(v.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getLong(CharSequence name, long defaultValue) {
|
public long getLong(CharSequence name, long defaultValue) {
|
||||||
CharSequence v = getUnconverted(name);
|
CharSequence v = getUnconverted(name);
|
||||||
@ -412,6 +441,16 @@ public class DefaultTextHeaders implements TextHeaders {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getTimeMillis(CharSequence name) {
|
||||||
|
CharSequence v = getUnconverted(name);
|
||||||
|
if (v == null) {
|
||||||
|
throw new NoSuchElementException(String.valueOf(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
return HttpHeaderDateFormat.get().parse(v.toString());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getTimeMillis(CharSequence name, long defaultValue) {
|
public long getTimeMillis(CharSequence name, long defaultValue) {
|
||||||
CharSequence v = getUnconverted(name);
|
CharSequence v = getUnconverted(name);
|
||||||
@ -786,6 +825,20 @@ public class DefaultTextHeaders implements TextHeaders {
|
|||||||
dateFormat3.setTimeZone(tz);
|
dateFormat3.setTimeZone(tz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long parse(String text) {
|
||||||
|
Date date = dateFormat1.parse(text, parsePos);
|
||||||
|
if (date == null) {
|
||||||
|
date = dateFormat2.parse(text, parsePos);
|
||||||
|
}
|
||||||
|
if (date == null) {
|
||||||
|
date = dateFormat3.parse(text, parsePos);
|
||||||
|
}
|
||||||
|
if (date == null) {
|
||||||
|
PlatformDependent.throwException(new ParseException(text, 0));
|
||||||
|
}
|
||||||
|
return date.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
long parse(String text, long defaultValue) {
|
long parse(String text, long defaultValue) {
|
||||||
Date date = dateFormat1.parse(text, parsePos);
|
Date date = dateFormat1.parse(text, parsePos);
|
||||||
if (date == null) {
|
if (date == null) {
|
||||||
|
@ -20,6 +20,7 @@ import java.util.Collections;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class EmptyTextHeaders implements TextHeaders {
|
public class EmptyTextHeaders implements TextHeaders {
|
||||||
@ -36,16 +37,31 @@ public class EmptyTextHeaders implements TextHeaders {
|
|||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getInt(CharSequence name) {
|
||||||
|
throw new NoSuchElementException(String.valueOf(name));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getInt(CharSequence name, int defaultValue) {
|
public int getInt(CharSequence name, int defaultValue) {
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getLong(CharSequence name) {
|
||||||
|
throw new NoSuchElementException(String.valueOf(name));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getLong(CharSequence name, long defaultValue) {
|
public long getLong(CharSequence name, long defaultValue) {
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getTimeMillis(CharSequence name) {
|
||||||
|
throw new NoSuchElementException(String.valueOf(name));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getTimeMillis(CharSequence name, long defaultValue) {
|
public long getTimeMillis(CharSequence name, long defaultValue) {
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
|
@ -41,8 +41,11 @@ public interface TextHeaders extends Iterable<Map.Entry<String, String>> {
|
|||||||
String get(CharSequence name);
|
String get(CharSequence name);
|
||||||
|
|
||||||
String get(CharSequence name, String defaultValue);
|
String get(CharSequence name, String defaultValue);
|
||||||
|
int getInt(CharSequence name);
|
||||||
int getInt(CharSequence name, int defaultValue);
|
int getInt(CharSequence name, int defaultValue);
|
||||||
|
long getLong(CharSequence name);
|
||||||
long getLong(CharSequence name, long defaultValue);
|
long getLong(CharSequence name, long defaultValue);
|
||||||
|
long getTimeMillis(CharSequence name);
|
||||||
long getTimeMillis(CharSequence name, long defaultValue);
|
long getTimeMillis(CharSequence name, long defaultValue);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,8 +18,10 @@ package io.netty.example.spdy.client;
|
|||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ChannelOutboundHandlerAdapter;
|
import io.netty.channel.ChannelOutboundHandlerAdapter;
|
||||||
import io.netty.channel.ChannelPromise;
|
import io.netty.channel.ChannelPromise;
|
||||||
|
import io.netty.handler.codec.http.HttpHeaders;
|
||||||
import io.netty.handler.codec.http.HttpMessage;
|
import io.netty.handler.codec.http.HttpMessage;
|
||||||
import io.netty.handler.codec.spdy.SpdyHttpHeaders;
|
import io.netty.handler.codec.spdy.SpdyHttpHeaders;
|
||||||
|
import io.netty.handler.codec.spdy.SpdyHttpHeaders.Names;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a unique client stream ID to the SPDY header. Client stream IDs MUST be odd.
|
* Adds a unique client stream ID to the SPDY header. Client stream IDs MUST be odd.
|
||||||
@ -37,7 +39,7 @@ public class SpdyClientStreamIdHandler extends ChannelOutboundHandlerAdapter {
|
|||||||
if (acceptOutboundMessage(msg)) {
|
if (acceptOutboundMessage(msg)) {
|
||||||
HttpMessage httpMsg = (HttpMessage) msg;
|
HttpMessage httpMsg = (HttpMessage) msg;
|
||||||
if (!httpMsg.headers().contains(SpdyHttpHeaders.Names.STREAM_ID)) {
|
if (!httpMsg.headers().contains(SpdyHttpHeaders.Names.STREAM_ID)) {
|
||||||
SpdyHttpHeaders.setStreamId(httpMsg, currentStreamId);
|
HttpHeaders.setIntHeader(httpMsg, Names.STREAM_ID, currentStreamId);
|
||||||
// Client stream IDs are always odd
|
// Client stream IDs are always odd
|
||||||
currentStreamId += 2;
|
currentStreamId += 2;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user