Skip to content

Commit

Permalink
Fix HttpUtils#isConnectOrUpgrade for FF WebSockets
Browse files Browse the repository at this point in the history
See #5141

An exception was thrown when upgrading manually a Firefox WebSocket using io.vertx.core.http.HttpServerRequest#toNetSocket.

This happened because FF doesn't send a normal 'Connection: Upgrade' header for WebSockets.
Instead, it sends: 'Connection: keep-alive, Upgrade'.

Signed-off-by: Thomas Segismont <tsegismont@gmail.com>
  • Loading branch information
tsegismont committed Mar 7, 2024
1 parent 3f3ff78 commit e888bde
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 10 deletions.
18 changes: 15 additions & 3 deletions src/main/java/io/vertx/core/http/impl/HttpUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -1008,7 +1008,19 @@ static void resolveFile(VertxInternal vertx, String filename, long offset, long
}

static boolean isConnectOrUpgrade(io.vertx.core.http.HttpMethod method, MultiMap headers) {
return method == io.vertx.core.http.HttpMethod.CONNECT || (method == io.vertx.core.http.HttpMethod.GET && headers.contains(io.vertx.core.http.HttpHeaders.CONNECTION, io.vertx.core.http.HttpHeaders.UPGRADE, true));
if (method == io.vertx.core.http.HttpMethod.CONNECT) {
return true;
}
if (method == io.vertx.core.http.HttpMethod.GET) {
for (String connection : headers.getAll(io.vertx.core.http.HttpHeaders.CONNECTION)) {
// Firefox doesn't send a normal 'Connection: Upgrade' header for WebSockets.
// Instead, it sends: 'Connection: keep-alive, Upgrade'.
if (AsciiString.containsIgnoreCase(connection, io.vertx.core.http.HttpHeaders.UPGRADE)) {
return true;
}
}
}
return false;
}

static boolean isKeepAlive(HttpRequest request) {
Expand All @@ -1031,9 +1043,9 @@ public static boolean canUpgradeToWebSocket(HttpServerRequest req) {
}
MultiMap headers = req.headers();
for (String connection : headers.getAll(io.vertx.core.http.HttpHeaders.CONNECTION)) {
if (connection.toLowerCase().contains(io.vertx.core.http.HttpHeaders.UPGRADE)) {
if (AsciiString.containsIgnoreCase(connection, io.vertx.core.http.HttpHeaders.UPGRADE)) {
for (String upgrade : headers.getAll(io.vertx.core.http.HttpHeaders.UPGRADE)) {
if (upgrade.toLowerCase().contains(io.vertx.core.http.HttpHeaders.WEBSOCKET)) {
if (AsciiString.containsIgnoreCase(upgrade, io.vertx.core.http.HttpHeaders.WEBSOCKET)) {
return true;
}
}
Expand Down
28 changes: 21 additions & 7 deletions src/test/java/io/vertx/core/http/Http1xTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import io.vertx.core.impl.ContextInternal;
import io.vertx.core.impl.Utils;
import io.vertx.core.impl.VertxInternal;
import io.vertx.core.impl.transports.JDKTransport;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.core.net.*;
Expand Down Expand Up @@ -5351,16 +5350,31 @@ public void testCannotUpgradeToWebSocketIfUpgradeDoesNotContainWebsocket() throw

private void doTestCanUpgradeToWebSocket(UnaryOperator<RequestOptions> config, boolean shouldSucceed) throws Exception {
server.requestHandler(req -> {
HttpServerResponse serverResponse = req.response();
int statusCode = HttpUtils.canUpgradeToWebSocket(req) ? 200 : 500;
serverResponse.setStatusCode(statusCode);
serverResponse.end();
HttpServerResponse resp = req.response();
if (HttpUtils.canUpgradeToWebSocket(req)) {
resp.headers()
.set(HttpHeaders.CONNECTION, HttpHeaders.UPGRADE)
.set(HttpHeaders.UPGRADE, HttpHeaders.WEBSOCKET);
req.toNetSocket().onComplete(onSuccess(sock -> {
sock.write(Buffer.buffer("foo"));
}));
} else {
resp.setStatusCode(500).end();
}
});
startServer(testAddress);
client.request(config.apply(new RequestOptions(requestOptions))).onComplete(onSuccess(req -> {
req.response().onComplete(onSuccess(resp -> {
assertEquals(shouldSucceed ? 200 : 500, resp.statusCode());
testComplete();
if (shouldSucceed) {
assertEquals(101, resp.statusCode());
resp.netSocket().handler(buffer -> {
assertEquals("foo", buffer.toString());
testComplete();
});
} else {
assertEquals(500, resp.statusCode());
testComplete();
}
}));
req.send();
}));
Expand Down

0 comments on commit e888bde

Please sign in to comment.