Skip to content

Commit ab5d60a

Browse files
committed
fix issue Firefox websocket upgrade request robaho#12
1 parent fb69e42 commit ab5d60a

File tree

4 files changed

+59
-9
lines changed

4 files changed

+59
-9
lines changed

src/main/java/robaho/net/httpserver/Utils.java

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
* or visit www.oracle.com if you need additional information or have any
2323
* questions.
2424
*/
25-
2625
package robaho.net.httpserver;
2726

2827
/**
@@ -36,9 +35,9 @@ public class Utils {
3635
private static final boolean[] QUOTED_PAIR = new boolean[256];
3736

3837
static {
39-
char[] allowedTokenChars = ("!#$%&'*+-.^_`|~0123456789" +
40-
"abcdefghijklmnopqrstuvwxyz" +
41-
"ABCDEFGHIJKLMNOPQRSTUVWXYZ").toCharArray();
38+
char[] allowedTokenChars = ("!#$%&'*+-.^_`|~0123456789"
39+
+ "abcdefghijklmnopqrstuvwxyz"
40+
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ").toCharArray();
4241
for (char c : allowedTokenChars) {
4342
TCHAR[c] = true;
4443
}
@@ -87,4 +86,32 @@ public static boolean isQuotedStringContent(String token) {
8786
}
8887
return true;
8988
}
89+
90+
/**
91+
* efficient contains() ignoring case
92+
*/
93+
public static boolean containsIgnoreCase(String src, String what) {
94+
final int length = what.length();
95+
if (length == 0) {
96+
return true; // Empty string is contained
97+
}
98+
final char firstLo = Character.toLowerCase(what.charAt(0));
99+
final char firstUp = Character.toUpperCase(what.charAt(0));
100+
101+
final int srcLength = src.length();
102+
103+
for (int i = srcLength - length; i >= 0; i--) {
104+
// Quick check before calling the more expensive regionMatches() method:
105+
final char ch = src.charAt(i);
106+
if (ch != firstLo && ch != firstUp) {
107+
continue;
108+
}
109+
110+
if (src.regionMatches(true, i, what, 0, length)) {
111+
return true;
112+
}
113+
}
114+
115+
return false;
116+
}
90117
}

src/main/java/robaho/net/httpserver/websockets/WebSocketHandler.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.sun.net.httpserver.HttpHandler;
99

1010
import robaho.net.httpserver.Code;
11+
import robaho.net.httpserver.Utils;
1112

1213
public abstract class WebSocketHandler implements HttpHandler {
1314

@@ -58,11 +59,9 @@ public void handle(HttpExchange exchange) throws IOException {
5859

5960
public static boolean isWebsocketRequested(Headers headers) {
6061
// check if Upgrade connection
61-
String connection = headers.getFirst(Util.HEADER_CONNECTION);
62-
if (connection == null || !connection.equalsIgnoreCase(Util.HEADER_CONNECTION_VALUE)) {
63-
return false;
64-
}
65-
// check for proper upgrade tyoe
62+
var values = headers.get(Util.HEADER_CONNECTION);
63+
if(values==null || values.stream().filter(s -> Utils.containsIgnoreCase(s, Util.HEADER_CONNECTION_VALUE)).findAny().isEmpty()) return false;
64+
// check for proper upgrade type
6665
String upgrade = headers.getFirst(Util.HEADER_UPGRADE);
6766
return Util.HEADER_UPGRADE_VALUE.equalsIgnoreCase(upgrade);
6867
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package robaho.net.httpserver;
2+
3+
import java.io.ByteArrayInputStream;
4+
import java.io.ByteArrayOutputStream;
5+
import java.io.IOException;
6+
7+
import static org.testng.Assert.assertEquals;
8+
import static org.testng.Assert.assertFalse;
9+
import static org.testng.Assert.assertTrue;
10+
import org.testng.annotations.Test;
11+
12+
public class StringUtilsTest {
13+
@Test
14+
public void TestContainsIgnoreCase() throws IOException {
15+
assertTrue(Utils.containsIgnoreCase("Keep-alive","keep-alive"));
16+
assertTrue(Utils.containsIgnoreCase("Keep-alive, upgrade","Upgrade"));
17+
assertTrue(Utils.containsIgnoreCase("upgrade, keep-alive","Upgrade"));
18+
assertTrue(Utils.containsIgnoreCase("upgrade, keep-alive","upgrade"));
19+
assertFalse(Utils.containsIgnoreCase("Keep-alive, upgrde","Upgrade"));
20+
}
21+
22+
}

src/test/java/robaho/net/httpserver/websockets/WebSocketResponseHandlerTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ private void testResponseHeader(String key, String expected) {
155155
public void testConnectionHeaderHandlesKeepAlive_FixingFirefoxConnectIssue() throws IOException {
156156
this.headers.set("connection", "keep-alive, Upgrade");
157157
handler.handle(exchange);
158+
testResponseHeader(Util.HEADER_WEBSOCKET_ACCEPT, "HSmrc0sMlYUkAGmm5OPpG2HaGWk=");
159+
testResponseHeader(Util.HEADER_WEBSOCKET_PROTOCOL, "chat");
158160
}
159161

160162
@Test

0 commit comments

Comments
 (0)