I'm using Jetty 8.1.1 Websocket client api.
I need to update the headers with ("Sec-WebSocket-Protocol", "xsCrossfire")
and ("Authorization", "Basic TLVWQMZqRr2hasYnZoI=")
WebSocketClientFactory factory = new WebSocketClientFactory();
factory.start();
client = factory.newWebSocketClient();
client.getCookies().put("Sec-WebSocket-Protocol", "xsCrossfire");
client.getCookies().put("Authorization", "Basic TLVWQMZqRr2hasYnZoI=");
Future<Connection> conn = client.open(uri, (WebSocket) this);
System.out.printf("Connecting to : %s%n", uri);
request looks:
Host: iltlvl262:8000\r\n
Upgrade: websocket\r\n
Connection: Upgrade\r\n
Sec-WebSocket-Version: 13\r\n
Sec-WebSocket-Key: FHKTsICO2vqGCxXVwLkH4Q==\r\n
Cookie: Sec-WebSocket-Protocol=xsCrossfire\r\n
Cookie: Authorization="Basic TLVWQMZqRr2hasYnZoI="\r\n
expected request:
Host: iltlvl262:8000\r\n
Upgrade: websocket\r\n
Connection: Upgrade\r\n
Sec-WebSocket-Version: 13\r\n
Sec-WebSocket-Key: FHKTsICO2vqGCxXVwLkH4Q==\r\n
Sec-WebSocket-Protocol: xsCrossfire\r\n
Authorization: "Basic TLVWQMZqRr2hasYnZoI="\r\n
how do I implement handshake in version 8.1.1 correctly?
Some good news and some bad news.
First, the Good news:
To set the Sec-WebSocket-Protocol
header use the following.
client.setProtocol("xsCrossfire");
before you use client.open()
Next, the Bad news:
With Jetty 8.x you cannot set arbitrary non-websocket headers. This was due to how early experimental drafts of WebSocket were written. You simply were not allowed to set arbitrary headers per the early draft specs, so the implementation back in the Jetty 8.x days just didn't allow it.
However, with the finalization of RFC6455 (the official WebSocket spec) things changed, all of those changes were rolled into the Jetty 9.x codebase. Which is 100% RFC6455 compliant. (Note: Jetty 8 is 100% compliant to RFC6455 on the server side. Jetty 8 is also 100% compatible on the RFC6455 protocol use for both server and client. However, Jetty 8 is only partially compliant on the client side, from a features and API point of view.)
The decision with Jetty 7 and Jetty 8 was made to keep the old experimental drafts around for those early adopters and old browsers (Safari 5.x) that still used them. This decision prevented us from allowing behaviors that are specifically prevented in the old experimental drafts.
Starting with Jetty 9.x all old experimental drafts of websocket were dropped, leaving only RFC6455 to support, which allowed Jetty to open up more features that were previously disallowed. This includes arbitrary headers on the WebSocketClient.
Example of Jetty 9.1 WebSocket Client
import java.io.IOException;
import java.net.URI;
import java.util.concurrent.Future;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.WebSocketAdapter;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient;
public class ExampleClient
{
public static class ExampleSocket extends WebSocketAdapter
{
@Override
public void onWebSocketText(String message)
{
try
{
// echo the message
getRemote().sendString(message);
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
public static void main(String[] args)
{
try
{
new ExampleClient().demo();
}
catch (Throwable t)
{
t.printStackTrace(System.err);
}
}
public void demo() throws Exception
{
WebSocketClient client = new WebSocketClient();
try
{
client.start();
ClientUpgradeRequest request = new ClientUpgradeRequest();
request.setSubProtocols("xsCrossfire");
request.setHeader("Authorization","Basic TLVWQMZqRr2hasYnZoI=");
URI wsUri = URI.create("ws://iltlvl262:8000/echo");
ExampleSocket socket = new ExampleSocket();
Future<Session> future = client.connect(socket,wsUri,request);
future.get(); // wait for connect
socket.getRemote().sendString("hello"); // send message
}
finally
{
client.stop();
}
}
}
Also note, that starting with Jetty 9.1, even the javax.websocket
(JSR-356) API is fully supported.
Same example using javax.websocket on Jetty 9.1
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.websocket.ClientEndpoint;
import javax.websocket.ContainerProvider;
import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;
public class ExampleClient
{
@ClientEndpoint(subprotocols = { "xsCrossfire" },
configurator = ExampleClient.Configurator.class)
public static class ExampleSocket
{
@OnMessage
public String onMessage(String msg)
{
return msg; // echo
}
}
public static class Configurator
extends javax.websocket.ClientEndpointConfig.Configurator
{
@Override
public void beforeRequest(Map<String, List<String>> headers)
{
List<String> authvalues = new ArrayList<>();
authvalues.add("Basic TLVWQMZqRr2hasYnZoI=");
headers.put("Authorization", authvalues);
super.beforeRequest(headers);
}
}
public static void main(String[] args)
{
try
{
new ExampleClient().demo();
}
catch (Throwable t)
{
t.printStackTrace(System.err);
}
}
public void demo() throws Exception
{
WebSocketContainer client = ContainerProvider.getWebSocketContainer();
ExampleSocket socket = new ExampleSocket();
URI wsUri = URI.create("ws://iltlvl262:8000/echo");
Session session = client.connectToServer(socket,wsUri);
session.getAsyncRemote().sendText("Hello");
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With