Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add invalid request handling callback for websocket server #444

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

PragmaTwice
Copy link

@PragmaTwice PragmaTwice commented Sep 7, 2024

It closes #443.

I found that currently the server side of tungstenite will directly drop the connection when encountering some handshake failures (the stream is moved into accept() so it will be dropped when an error occurs).

However I have a requirement to return a valid http response when some websocket related headers are missing (such as the connection upgrade header). Currently tungstenite seems unable to do this.

This patch provides a method to solve this problem.

A new method on_invalid_request() (with a default impl) is added into Callback. (It doesn't break the current API and also keeps the current default behavior so that no users code will be broken.)

By default the behavior has no change: the connection will just be dropped if the server get some invalid request (e.g. no connection upgrade header), but users can define their own on_invalid_request() to return a valid response for it.

It also makes the library more compliant to the standards, refer to RFC 6455:

If the server, while reading the handshake, finds that the client did
not send a handshake that matches the description below (note that as
per [RFC2616], the order of the header fields is not important),
including but not limited to any violations of the ABNF grammar
specified for the components of the handshake, the server MUST stop
processing the client's handshake and return an HTTP response with an
appropriate error code (such as 400 Bad Request).

A simple use case:

impl Callback for MyOwnHandshakeCallback {
  
    ...

    fn on_invalid_request(self, _request: &Request, error: Error) -> Result<ErrorResponse> {
        if let Error::Protocol(e) = &error {
            match e {
                ProtocolError::WrongHttpMethod | ProtocolError::WrongHttpVersion => return Err(error)
                _ => {
                    let err = Response::builder()
                        .status(StatusCode::BAD_REQUEST)
                        .body(None)
                        .unwrap();

                    return Ok(err);
                }
            }
        }

        Err(error)
    }
}

@agalakhov
Copy link
Member

An alternative solution would be returning HandshakeError::Failure(Error, Connection) so that the connection would be usable. But the callback is fine too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support custom behavior for some handshake error cases
2 participants