[#4754] Correctly detect websocket upgrade

Motivation:

If the Connection header contains multiple values (which is valid) we fail to detect a websocket upgrade

Modification:

- Add new method which allows to check if a header field contains a specific value (and also respect multiple header values)
- Use this method to detect handshake

Result:

Correct detect handshake if Connection header contains multiple values (seperated by ',').
This commit is contained in:
Norman Maurer 2016-01-27 14:26:33 +01:00
parent d0b0e028d0
commit d5a8b65700
6 changed files with 55 additions and 13 deletions

View File

@ -16,6 +16,7 @@
package io.netty.handler.codec.http;
import io.netty.buffer.ByteBuf;
import io.netty.util.internal.StringUtil;
import java.text.ParseException;
import java.util.Calendar;
@ -1671,6 +1672,48 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
return false;
}
/**
* Returns {@code true} if a header with the {@code name} and {@code value} exists, {@code false} otherwise.
* This also handles multiple values that are seperated with a {@code ,}.
* <p>
* If {@code ignoreCase} is {@code true} then a case insensitive compare is done on the value.
* @param name the name of the header to find
* @param value the value of the header to find
* @param ignoreCase {@code true} then a case insensitive compare is run to compare values.
* otherwise a case sensitive compare is run to compare values.
*/
public boolean containsValue(CharSequence name, CharSequence value, boolean ignoreCase) {
List<String> values = getAll(name);
if (values.isEmpty()) {
return false;
}
for (String v: values) {
if (contains(v, value, ignoreCase)) {
return true;
}
}
return false;
}
private static boolean contains(String value, CharSequence expected, boolean ignoreCase) {
String[] parts = StringUtil.split(value, ',');
if (ignoreCase) {
for (String s: parts) {
if (equalsIgnoreCase(expected, s.trim())) {
return true;
}
}
} else {
for (String s: parts) {
if (s.trim().contentEquals(expected)) {
return true;
}
}
}
return false;
}
/**
* Returns {@code true} if a header with the name and value exists.
*

View File

@ -196,10 +196,9 @@ public class WebSocketClientHandshaker00 extends WebSocketClientHandshaker {
+ upgrade);
}
String connection = headers.get(Names.CONNECTION);
if (!Values.UPGRADE.equalsIgnoreCase(connection)) {
if (!headers.containsValue(Names.CONNECTION, Values.UPGRADE, true)) {
throw new WebSocketHandshakeException("Invalid handshake response connection: "
+ connection);
+ headers.get(Names.CONNECTION));
}
ByteBuf challenge = response.content();

View File

@ -170,9 +170,9 @@ public class WebSocketClientHandshaker07 extends WebSocketClientHandshaker {
throw new WebSocketHandshakeException("Invalid handshake response upgrade: " + upgrade);
}
String connection = headers.get(Names.CONNECTION);
if (!Values.UPGRADE.equalsIgnoreCase(connection)) {
throw new WebSocketHandshakeException("Invalid handshake response connection: " + connection);
if (!headers.containsValue(Names.CONNECTION, Values.UPGRADE, true)) {
throw new WebSocketHandshakeException("Invalid handshake response connection: "
+ headers.get(Names.CONNECTION));
}
String accept = headers.get(Names.SEC_WEBSOCKET_ACCEPT);

View File

@ -170,9 +170,9 @@ public class WebSocketClientHandshaker08 extends WebSocketClientHandshaker {
throw new WebSocketHandshakeException("Invalid handshake response upgrade: " + upgrade);
}
String connection = headers.get(Names.CONNECTION);
if (!Values.UPGRADE.equalsIgnoreCase(connection)) {
throw new WebSocketHandshakeException("Invalid handshake response connection: " + connection);
if (!headers.containsValue(Names.CONNECTION, Values.UPGRADE, true)) {
throw new WebSocketHandshakeException("Invalid handshake response connection: "
+ headers.get(Names.CONNECTION));
}
String accept = headers.get(Names.SEC_WEBSOCKET_ACCEPT);

View File

@ -180,9 +180,9 @@ public class WebSocketClientHandshaker13 extends WebSocketClientHandshaker {
throw new WebSocketHandshakeException("Invalid handshake response upgrade: " + upgrade);
}
String connection = headers.get(Names.CONNECTION);
if (!Values.UPGRADE.equalsIgnoreCase(connection)) {
throw new WebSocketHandshakeException("Invalid handshake response connection: " + connection);
if (!headers.containsValue(Names.CONNECTION, Values.UPGRADE, true)) {
throw new WebSocketHandshakeException("Invalid handshake response connection: "
+ headers.get(Names.CONNECTION));
}
String accept = headers.get(Names.SEC_WEBSOCKET_ACCEPT);

View File

@ -109,7 +109,7 @@ public class WebSocketServerHandshaker00 extends WebSocketServerHandshaker {
protected FullHttpResponse newHandshakeResponse(FullHttpRequest req, HttpHeaders headers) {
// Serve the WebSocket handshake request.
if (!Values.UPGRADE.equalsIgnoreCase(req.headers().get(CONNECTION))
if (!req.headers().containsValue(CONNECTION, Values.UPGRADE, true)
|| !WEBSOCKET.equalsIgnoreCase(req.headers().get(Names.UPGRADE))) {
throw new WebSocketHandshakeException("not a WebSocket handshake request: missing upgrade");
}