-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add note to draft a GitHub release too ocne the release is tagged * consistify newlines * First pass to create a working hyper+soketto example * rustfmt * make trimming a little nicer * Tidy up some hyper_server example a little * cargo fmt * Add comment on how to try hyper_server example * print local_addr (no real difference but more correct) * Fix typo Co-authored-by: Andrew Plaza <[email protected]> * Wee grammar tweak in comment * Empty slice is more readable; no need to preserve lifetime * allow setting custom headers * Add a feature and update hyper_example to make it easier to use Soketto with http types * Note about headers, re-export httparse::Header * rethink 1 (but it turns out this won't work..) * Make a new Server interface instead so that we have an API we can use * remove the default_feature * dedupe code in handshake and undo changes in handshake::server to minimise diff * Add link to RFC explaining Sec-Websocket-Key * add basic logger to example so we can get log output for debugging things * Fix up a couple of comments * use log since we added a logger, and comment tweaks * use WebSocketKey alias * return 28 byte base64 encoding instead of passing buffer in * Tweak the docs a little * fix a typo * Release v0.7.0 Co-authored-by: Andrew Plaza <[email protected]> Co-authored-by: Tomas Langsetmo <[email protected]> Co-authored-by: David <[email protected]>
- Loading branch information
1 parent
73748e4
commit feb2204
Showing
10 changed files
with
366 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,7 @@ name: Rust | |
|
||
on: | ||
push: | ||
# Run jobs when commits are pushed to | ||
# Run jobs when commits are pushed to | ||
# develop or release-like branches: | ||
branches: | ||
- develop | ||
|
@@ -40,7 +40,7 @@ jobs: | |
uses: actions-rs/[email protected] | ||
with: | ||
command: check | ||
args: --all-targets | ||
args: --all-targets --all-features | ||
|
||
fmt: | ||
name: Run rustfmt | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
[package] | ||
name = "soketto" | ||
version = "0.6.0" | ||
version = "0.7.0" | ||
authors = ["Parity Technologies <[email protected]>", "Jason Ozias <[email protected]>"] | ||
description = "A websocket protocol implementation." | ||
keywords = ["websocket", "codec", "async", "futures"] | ||
|
@@ -26,9 +26,17 @@ httparse = { default-features = false, features = ["std"], version = "1.3.4" } | |
log = { default-features = false, version = "0.4.8" } | ||
rand = { default-features = false, features = ["std", "std_rng"], version = "0.8" } | ||
sha-1 = { default-features = false, version = "0.9" } | ||
http = { default-features = false, version = "0.2", optional = true } | ||
|
||
[dev-dependencies] | ||
quickcheck = "0.9" | ||
tokio = { version = "1", features = ["full"] } | ||
tokio-util = { version = "0.6", features = ["compat"] } | ||
tokio-stream = { version = "0.1", features = ["net"] } | ||
hyper = { version = "0.14.10", features = ["full"] } | ||
env_logger = "0.9.0" | ||
|
||
[[example]] | ||
name = "hyper_server" | ||
required-features = ["http"] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
// Copyright (c) 2021 Parity Technologies (UK) Ltd. | ||
// | ||
// Licensed under the Apache License, Version 2.0 | ||
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT | ||
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. All files in the project carrying such notice may not be copied, | ||
// modified, or distributed except according to those terms. | ||
|
||
// An example of how to use of Soketto alongside Hyper, so that we can handle | ||
// standard HTTP traffic with Hyper, and WebSocket connections with Soketto, on | ||
// the same port. | ||
// | ||
// To try this, start up the example (`cargo run --example hyper_server`) and then | ||
// navigate to localhost:3000 and, in the browser JS console, run: | ||
// | ||
// ``` | ||
// var socket = new WebSocket("ws://localhost:3000"); | ||
// socket.onmessage = function(msg) { console.log(msg) }; | ||
// socket.send("Hello!"); | ||
// ``` | ||
// | ||
// You'll see any messages you send echoed back. | ||
|
||
use futures::io::{BufReader, BufWriter}; | ||
use hyper::{Body, Request, Response}; | ||
use soketto::{ | ||
handshake::http::{is_upgrade_request, Server}, | ||
BoxedError, | ||
}; | ||
use tokio_util::compat::TokioAsyncReadCompatExt; | ||
|
||
/// Start up a hyper server. | ||
#[tokio::main] | ||
async fn main() -> Result<(), BoxedError> { | ||
env_logger::init(); | ||
|
||
let addr = ([127, 0, 0, 1], 3000).into(); | ||
|
||
let service = | ||
hyper::service::make_service_fn(|_| async { Ok::<_, hyper::Error>(hyper::service::service_fn(handler)) }); | ||
let server = hyper::Server::bind(&addr).serve(service); | ||
|
||
println!("Listening on http://{} — connect and I'll echo back anything you send!", server.local_addr()); | ||
server.await?; | ||
|
||
Ok(()) | ||
} | ||
|
||
/// Handle incoming HTTP Requests. | ||
async fn handler(req: Request<Body>) -> Result<hyper::Response<Body>, BoxedError> { | ||
if is_upgrade_request(&req) { | ||
// Create a new handshake server. | ||
let mut server = Server::new(); | ||
|
||
// Add any extensions that we want to use. | ||
#[cfg(feature = "deflate")] | ||
{ | ||
let deflate = soketto::extension::deflate::Deflate::new(soketto::Mode::Server); | ||
server.add_extension(Box::new(deflate)); | ||
} | ||
|
||
// Attempt the handshake. | ||
match server.receive_request(&req) { | ||
// The handshake has been successful so far; return the response we're given back | ||
// and spawn a task to handle the long-running WebSocket server: | ||
Ok(response) => { | ||
tokio::spawn(async move { | ||
if let Err(e) = websocket_echo_messages(server, req).await { | ||
log::error!("Error upgrading to websocket connection: {}", e); | ||
} | ||
}); | ||
Ok(response.map(|()| Body::empty())) | ||
} | ||
// We tried to upgrade and failed early on; tell the client about the failure however we like: | ||
Err(e) => { | ||
log::error!("Could not upgrade connection: {}", e); | ||
Ok(Response::new(Body::from("Something went wrong upgrading!"))) | ||
} | ||
} | ||
} else { | ||
// The request wasn't an upgrade request; let's treat it as a standard HTTP request: | ||
Ok(Response::new(Body::from("Hello HTTP!"))) | ||
} | ||
} | ||
|
||
/// Echo any messages we get from the client back to them | ||
async fn websocket_echo_messages(server: Server, req: Request<Body>) -> Result<(), BoxedError> { | ||
// The negotiation to upgrade to a WebSocket connection has been successful so far. Next, we get back the underlying | ||
// stream using `hyper::upgrade::on`, and hand this to a Soketto server to use to handle the WebSocket communication | ||
// on this socket. | ||
// | ||
// Note: awaiting this won't succeed until the handshake response has been returned to the client, so this must be | ||
// spawned on a separate task so as not to block that response being handed back. | ||
let stream = hyper::upgrade::on(req).await?; | ||
let stream = BufReader::new(BufWriter::new(stream.compat())); | ||
|
||
// Get back a reader and writer that we can use to send and receive websocket messages. | ||
let (mut sender, mut receiver) = server.into_builder(stream).finish(); | ||
|
||
// Echo any received messages back to the client: | ||
let mut message = Vec::new(); | ||
loop { | ||
message.clear(); | ||
match receiver.receive_data(&mut message).await { | ||
Ok(soketto::Data::Binary(n)) => { | ||
assert_eq!(n, message.len()); | ||
sender.send_binary_mut(&mut message).await?; | ||
sender.flush().await? | ||
} | ||
Ok(soketto::Data::Text(n)) => { | ||
assert_eq!(n, message.len()); | ||
if let Ok(txt) = std::str::from_utf8(&message) { | ||
sender.send_text(txt).await?; | ||
sender.flush().await? | ||
} else { | ||
break; | ||
} | ||
} | ||
Err(soketto::connection::Error::Closed) => break, | ||
Err(e) => { | ||
eprintln!("Websocket connection error: {}", e); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.