Skip to content

Commit 47d9701

Browse files
committed
Merge remote-tracking branch 'origin/master' into split_in_two
Conflicts: src/client/builder.rs src/result.rs
2 parents b3e3970 + 9e98df3 commit 47d9701

File tree

5 files changed

+53
-13
lines changed

5 files changed

+53
-13
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "websocket"
3-
version = "0.22.4"
3+
version = "0.23.0"
44
authors = ["cyderize <[email protected]>", "Michael Eden <[email protected]>"]
55

66
description = "A WebSocket (RFC6455) library for Rust."

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
Rust-WebSocket [![Build Status](https://travis-ci.com/websockets-rs/rust-websocket.svg?branch=master)](https://travis-ci.com/websockets-rs/rust-websocket) [![docs.rs](https://docs.rs/websocket/badge.svg)](https://docs.rs/websocket)
22
==============
33

4+
5+
|**Note: Maintainership of this project is slugglish. You may want to use [tungstenite](https://crates.io/crates/tungstenite) or [tokio-tungstenite](https://crates.io/crates/tokio-tungstenite) instead.**|
6+
|----|
7+
8+
49
Rust-WebSocket is a WebSocket ([RFC6455](https://datatracker.ietf.org/doc/rfc6455/)) library written in Rust.
510

611
Rust-WebSocket provides a framework for dealing with WebSocket connections (both clients and servers). The library is currently in an experimental state, but provides functionality for both normal and secure WebSockets, a message level API supporting fragmentation, a data frame level API, and the ability to extend and customize behaviour.
@@ -10,7 +15,7 @@ Rust-WebSocket provides a framework for dealing with WebSocket connections (both
1015
To add a library release version from [crates.io](https://crates.io/crates/websocket) to a Cargo project, add this to the 'dependencies' section of your Cargo.toml:
1116

1217
```INI
13-
websocket = "0.22.4"
18+
websocket = "0.23.0"
1419
```
1520

1621
To add the library's Git repository to a Cargo project, add this to your Cargo.toml:

examples/async-client.rs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,56 +13,69 @@ use websocket::{ClientBuilder, OwnedMessage};
1313

1414
const CONNECTION: &'static str = "ws://127.0.0.1:2794";
1515

16+
// Async websocket chat client
1617
fn main() {
1718
println!("Connecting to {}", CONNECTION);
19+
20+
// Construct new Tokio runtime environment
1821
let mut runtime = tokio::runtime::current_thread::Builder::new()
1922
.build()
2023
.unwrap();
2124

22-
// standard in isn't supported in mio yet, so we use a thread
23-
// see https://github.com/carllerche/mio/issues/321
2425
let (usr_msg, stdin_ch) = mpsc::channel(0);
26+
27+
// Spawn new thread to read user input
28+
// stdin isn't supported in mio yet, so we use a thread
29+
// see https://github.com/carllerche/mio/issues/321
2530
thread::spawn(|| {
2631
let mut input = String::new();
2732
let mut stdin_sink = usr_msg.wait();
2833
loop {
34+
// Read user input from stdin
2935
input.clear();
3036
stdin().read_line(&mut input).unwrap();
37+
38+
// Trim whitespace and match input to known chat commands
39+
// If input is unknown, send trimmed input as a chat message
3140
let trimmed = input.trim();
32-
3341
let (close, msg) = match trimmed {
3442
"/close" => (true, OwnedMessage::Close(None)),
3543
"/ping" => (false, OwnedMessage::Ping(b"PING".to_vec())),
3644
_ => (false, OwnedMessage::Text(trimmed.to_string())),
3745
};
38-
46+
// Send message to websocket server
3947
stdin_sink
4048
.send(msg)
4149
.expect("Sending message across stdin channel.");
42-
50+
// If user entered the "/close" command, break the loop
4351
if close {
4452
break;
4553
}
4654
}
4755
});
4856

57+
// Construct a new connection to the websocket server
4958
let runner = ClientBuilder::new(CONNECTION)
5059
.unwrap()
5160
.add_protocol("rust-websocket")
5261
.async_connect_insecure()
5362
.and_then(|(duplex, _)| {
5463
let (sink, stream) = duplex.split();
5564
stream
65+
// Iterate over message as they arrive in stream
5666
.filter_map(|message| {
5767
println!("Received Message: {:?}", message);
68+
// Respond to close or ping commands from the server
5869
match message {
59-
OwnedMessage::Close(e) => Some(OwnedMessage::Close(e)),
6070
OwnedMessage::Ping(d) => Some(OwnedMessage::Pong(d)),
6171
_ => None,
6272
}
6373
})
74+
// Takes in messages from both sinks
6475
.select(stdin_ch.map_err(|_| WebSocketError::NoDataAvailable))
76+
// Return a future that completes once all incoming data from the above streams has been processed into the sink
6577
.forward(sink)
6678
});
79+
// Start our websocket client runner in the Tokio environment
6780
runtime.block_on(runner).unwrap();
6881
}

src/client/builder.rs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use header::extensions::Extension;
44
use header::{Origin, WebSocketExtensions, WebSocketKey, WebSocketProtocol, WebSocketVersion};
5-
use hyper::header::{Header, HeaderFormat, Headers};
5+
use hyper::header::{Authorization, Basic, Header, HeaderFormat, Headers};
66
use hyper::version::HttpVersion;
77
use std::borrow::Cow;
88
use std::convert::Into;
@@ -820,6 +820,17 @@ impl<'u> ClientBuilder<'u> {
820820
});
821821
}
822822

823+
// handle username/password from URL
824+
if !self.url.username().is_empty() {
825+
self.headers.set(Authorization(Basic {
826+
username: self.url.username().to_owned(),
827+
password: match self.url.password() {
828+
Some(password) => Some(password.to_owned()),
829+
None => None,
830+
},
831+
}));
832+
}
833+
823834
self.headers
824835
.set(Connection(vec![ConnectionOption::ConnectionHeader(
825836
UniCase("Upgrade".to_string()),
@@ -847,10 +858,7 @@ impl<'u> ClientBuilder<'u> {
847858
let status = StatusCode::from_u16(response.subject.0);
848859

849860
if status != StatusCode::SwitchingProtocols {
850-
return Err(WebSocketOtherError::ResponseError(
851-
"Status code must be Switching Protocols",
852-
))
853-
.map_err(towse);
861+
return Err(WebSocketOtherError::StatusCodeError(status));
854862
}
855863

856864
let key = self
@@ -989,4 +997,14 @@ mod tests {
989997
assert!(protos.contains(&"electric".to_string()));
990998
assert!(!protos.contains(&"rust-websocket".to_string()));
991999
}
1000+
1001+
#[test]
1002+
fn build_client_with_username_password() {
1003+
use super::*;
1004+
let mut builder = ClientBuilder::new("ws://john:[email protected]:8080/hello").unwrap();
1005+
let _request = builder.build_request();
1006+
let auth = builder.headers.get::<Authorization<Basic>>().unwrap();
1007+
assert!(auth.username == "john");
1008+
assert_eq!(auth.password, Some("pswd".to_owned()));
1009+
}
9921010
}

src/result.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! The result type used within Rust-WebSocket
22
3+
pub use hyper::status::StatusCode;
34
use hyper::Error as HttpError;
45
use server::upgrade::HyperIntoWsError;
56
use std::convert::From;
@@ -40,6 +41,8 @@ pub enum WebSocketOtherError {
4041
RequestError(&'static str),
4142
/// Invalid WebSocket response error
4243
ResponseError(&'static str),
44+
/// Received unexpected status code
45+
StatusCodeError(StatusCode),
4346
/// An HTTP parsing error
4447
HttpError(HttpError),
4548
/// A URL parsing error
@@ -83,6 +86,7 @@ impl Error for WebSocketOtherError {
8386
WebSocketOtherError::WebSocketUrlError(_) => "WebSocket URL failure",
8487
WebSocketOtherError::IoError(ref e) => e.description(),
8588
WebSocketOtherError::ProtocolError(e) => e,
89+
WebSocketOtherError::StatusCodeError(_) => "Received unexpected status code",
8690
}
8791
}
8892

0 commit comments

Comments
 (0)