Setting headers for a websocket upgrade request.
ibotva opened this issue · 2 comments
I have been working on a client-side library for WAMP, and one of the required headers of that specification is Sec-Websocket-Protocol
. I had a difficult time trying to figure out how to create headers using tungstenite-rs
because I could not find any examples.
Now I did actually end up figuring this out, and this is more of a "convenience" issue because when you implement your own headers, it takes out all of the default websocket ones.
Because the connect
method accepts the IntoClientRequest
variants, I built something like this for my use cases:
use std::str::FromStr;
use http::{Uri, Version};
use tungstenite::{client::IntoClientRequest, handshake::client::generate_key};
pub struct WampRequest<T: ToString> {
pub uri: T,
pub protocol: T
}
impl<T: ToString> IntoClientRequest for WampRequest<T> {
fn into_client_request(self) -> tungstenite::Result<tungstenite::handshake::client::Request> {
let uri = Uri::from_str(&self.uri.to_string())?;
let req = http::Request::builder()
.uri(self.uri.to_string())
.version(Version::HTTP_11)
.header("Sec-WebSocket-Protocol", self.protocol.to_string())
.header("Sec-WebSocket-Key", generate_key())
.header("Connection", "Upgrade")
.header("Upgrade", "websocket")
.header("Sec-WebSocket-Version", 13)
.header("Host", uri.host().unwrap());
Ok(tungstenite::handshake::client::Request::from(req.body(())?))
}
}
However, I would like to contribute towards tungstenite-rs
to create a request type (not the same as the above one, since that is a wamp specific) that implements these default required values and allows for easy setter methods within the type. Is tungstenite open to contributors? How do contributions work here?
Maybe something like this (still needs extra methods to do things like set headers, unless you call the inner builder):
pub struct TungyRequest {
pub uri: Uri,
pub builder: Builder
}
impl TungyRequest {
pub fn new(uri: Uri) -> Self {
Self {
uri,
builder: Builder::new()
}
}
}
impl IntoClientRequest for TungyRequest {
fn into_client_request(self) -> tungstenite::Result<tungstenite::handshake::client::Request> {
Ok(tungstenite::handshake::client::Request::from(
self.builder
.uri(&self.uri)
.version(Version::HTTP_11)
.header("Sec-Websocket-Key", generate_key())
.header("Connection", "Upgrade")
.header("Upgrade", "websocket")
.header("Sec-WebSocket-Version", 13)
.header("Host", self.uri.host().unwrap())
.body(())?
))
}
}
The direction you've taken is certainly not wrong, but there is a simpler way to achieve this. The IntoClientRequest
is implemented for a String
and related types, so you could in fact use it to generate a Request
and then simply amend it with the headers you need.