websockets-rs / rust-websocket

A WebSocket (RFC6455) library written in Rust
http://websockets-rs.github.io/rust-websocket/
MIT License
1.55k stars 223 forks source link

Add body to request struct #79

Closed Paxa closed 7 years ago

Paxa commented 8 years ago

I need it to process normal HTTP and WebSocket on same port

Not sure if that's a correct way to implement it

dns2utf8 commented 8 years ago

How did you use it? is your webserver OSS?

It looks promising :+1:

dns2utf8 commented 8 years ago

This is the other way around as in #53

Paxa commented 8 years ago

You may detect if it's websocket request or normal HTTP

I use it here https://github.com/Paxa/waithook/blob/master/src/websocket_s.rs#L89 then in https://github.com/Paxa/waithook/blob/master/src/webserver.rs

I didn't find way to convert it hyper request or to iron request. In my case I create my own Request struct and check headers.has::<header::Upgrade>(). When it's normal http I server it immediately and close connection.

Real example: https://waithook.herokuapp.com/

Code example (didn't try to run, but idea is like this)


pub struct RequestWrap {
    pub method: String,
    pub url: String,
    pub headers: Headers,
    pub body: String,
}

for connection in ws_server {
    thread::spawn(move || {
        let request = connection.unwrap().read_request().unwrap();
        let headers = request.headers.clone();
        let path = request.url.to_string();

        if !headers.has::<header::Upgrade>() {

            let web_request = RequestWrap {
                method: request.method.as_ref().to_string(),
                url: request.url.to_string(),
                headers: request.headers.clone(),
                body: request.body.clone()
            };

            let response = WsResponse::bad_request(request);
            let (_, writer) = response.into_inner();

            let body = "OK\n";

            let raw_response = format!("{}\r\n{}: {}\r\n\r\n{}",
                "HTTP/1.1 200 OK",
                "Content-Length", body.len(),
                body
            )

            match writter.write(raw_response.as_bytes()) {
                Ok(_) => {},
                Err(e) => { println!("HTTP Socket write error: {}", e); }
            }

            writter.flush().unwrap();
            writter.shutdown(Shutdown::Both).unwrap();
            return;
        } else {
            // handle web socket connection
        }
    }
}
illegalprime commented 7 years ago

@Paxa currently I added a way to upgrade from a hyper request:

use hyper::server::{Server, Request, Response};
use websocket::Message;
use websocket::server::upgrade::IntoWs;
use websocket::server::upgrade::from_hyper::HyperRequest;

Server::http("0.0.0.0:80").unwrap().handle(move |req: Request, res: Response| {
    match HyperRequest(req).into_ws() {
        Ok(upgrade) => {
            // `accept` sends a successful handshake, no need to worry about res
            let mut client = match upgrade.accept() {
                Ok(c) => c,
                Err(_) => panic!(),
            };

            client.send_message(&Message::text("its free real estate"));
        },

        Err((request, err)) => {
            // continue using the request as normal, "echo uri"
            res.send(b"Try connecting over ws instead.").unwrap();
        },
    };
})
.unwrap();

If you still want the body to be added I'd be happy to merge the changes after they've been updated to the new way of doing things.

illegalprime commented 7 years ago

@Paxa closing for now, if you still want this feature let me know here.