Closed nox closed 7 years ago
I guess one can access them by implementing HandshakeRole
themselves, but that doesn't seem like the most straightforward thing to do.
It's also planned and the way to do it is known. Most likely it will be done together with permessage-deflate as permessage-deflate depends on the request headers. There is TODO comment in the code.
@agalakhov hyper's author @seanmonstar expects the Headers
type from hyper to one day live in its own crate. Would you be willing to use that to represent headers in requests and answers in tungstenite? It would help Servo, and I think it would be nice in any case given it's the exact same concept as in hyper.
Why not? everything that is properly designed would fit. Tungstenite is flexible enough to use that. BUt I would prefer single-pass zero-copy approach if possible.
Most likely it will be done together with permessage-deflate as permessage-deflate depends on the request headers.
My use case is access to the Set-Cookie
headers in the response.
I think this request may be more general. We need to be able to control each connection over their entire lifetime. Some examples for my use case (server side):
access to the full client request handshake and returning my own answer. use case: retrieving payload for checking jsonwebtoken and allowing or not this connection (forging my handshake answer)
react to a pong frame. use case: i set 2 timers/timeouts for each connection, one is an expire timeout, other one is a ping timeout.. When ping timeout occur, server send a ping frame and wait for a pong frame who reset my 2 timers. If expire timeout occur, server close the connection.
ws-rs provides a nice solution with Traits Handler a Factory allowing library users to implement their own logic.
PS: i am looking for building a mio-tungstenite for replacing my modified ws-rs
I have some opinions on this :)
I think this library (the pure websocket Read/Write
library) should not deal with HTTP at all. It should just deal with abstract ClientHandshake
and ServerHandshake
structs, which contain the relevant fields corresponding to the headers described in the RFC (key
, extensions
, protocol
, origin
, accept
, version
etc.).
Dealing with HTTP is better done by an HTTP library (client or server). This library should provide helpers and guidance for dealing with the handshake (checking version, choosing subprotocol, choosing extensions, checking origin, etc.), but only on an abstract level, not actually parsing the HTTP headers or writing 101 Switching Protocols
to the socket and so on. Once the handshake is done, the user hijacks the socket from the HTTP library and passes it to us.
I am only saying this because the WebSocket
type is already nicely isolated from stuff like mio
, tokio
, etc. It'd be nice to apply the same principles to the handshake part as well (let the user control the library, not the other way around).
@bluetech This is more or less what I intend to do in Servo, especially because WebSocket as used on the Web is a more restricted version of what the RFC is capable of.
@ffablia Reaction to pong could be done in a more elegant way than making a callback. We can add more items to the enum Message. Such an approach does not add artificial restrictions on the message handler. Should I add these enum variants?
In order to get the handshake information, one could just return it together
@bluetech Correct. Point me at the matching handshake library I could use and I'll use it. My definition of "matching" is: the library must be capable of parsing the information as it comes without making any assumption about the underlying stream. The stream is just Read + Write and may return WouldBlock. The ideal API here is somthing like the one of native_tls. I'm very picky about the performance here since on the server it's the place that may be DDoS-ed and thus it should be able to handle higher loads that the rest of the code.
Please note that, for the client, the RFC 6455 specifies URI format as well. Thus Tungstenite is in charge to parse them.
Alternatively, we can split the handshake portion of Tungstenite into a separate crate and transform it into a generic handshake engine. It is theoretically capable of that.
I don't know of any library which already does that; it would be great if this library would do it :)
Here is a very rough draft of my general idea of an API for this: https://gist.github.com/bluetech/466415d496d261614a6f47dcfa91d6dc (not valid Rust)
The idea is to help as much as possible with the handshake stuff, but not take over completely, so that the library user still has full control to do whatever they want. In particular, they can add headers, remove headers, validate headers, modify headers, reject requests/responses, and so on.
Thank you. It's quite similar to my idea and also similar to Tungstenite internals. Tungstenite just does not expose the public API now since I haven't found an elegant way to do that. For a client, just sending extra data together with the URL will do:
fn connect(url, extra: Option<ExtraHeaders>) -> ...;
For a server, there's a need for a callback or even to split handshake in two stages to allow the caller for inserting own code between them:
fn accept(stream) -> Result<Request, ...>;
impl Request {
fn response(self, extra: Option<ExtraHeaders>) -> Result<WebSocket, ...>;
}
For the Web, we need to be able to access the headers of the response to the initial HTTP request.