Skip to content

Commit 36c2fee

Browse files
committed
Add more examples, make Request Protocols a Vec
Tests all pass as well
1 parent 726ed0f commit 36c2fee

File tree

8 files changed

+64
-23
lines changed

8 files changed

+64
-23
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22

33
name = "websocket"
4-
version = "0.4.1"
4+
version = "0.5.0"
55
authors = ["cyderize <[email protected]>"]
66

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

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Rust-WebSocket attempts to provide a framework for WebSocket connections (both c
1010
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:
1111

1212
```INI
13-
websocket = "~0.4.0"
13+
websocket = "~0.5.0"
1414
```
1515

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

src/lib.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,10 @@
3535
//! let key = request.key().unwrap();
3636
//!
3737
//! // Form a response from the key
38-
//! // In this example, we don't deal with the requested protocol
39-
//! let response = WebSocketResponse::new(key.as_slice(), None);
38+
//! /* In this example, we don't deal with the requested protocol
39+
//! Because of this, however, we need to a type annotation,
40+
//! which would usually not be required. */
41+
//! let response = WebSocketResponse::new::<String>(key.as_slice(), None);
4042
//!
4143
//! // Send the response to the client
4244
//! let _ = client.send_handshake_response(response);
@@ -60,7 +62,8 @@ extern crate serialize;
6062

6163
pub use self::ws::client::WebSocketClient;
6264

63-
/// Structs for manipulation of HTTP headers
65+
/// Structs for manipulation of HTTP headers. Used in conjunction with
66+
/// WebSocketRequest and WebSocketResponse.
6467
pub mod headers {
6568
pub use util::header::{HeaderCollection, Headers};
6669
pub use url::ParseResult;

src/ws/client.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,12 @@ use std::clone::Clone;
1111
/// To use WebSocketClient, you must create one using either WebSocketClient::connect(),
1212
/// which is used for writing clients, or WebSocketClient::from_stream(), which creates
1313
/// a WebSocketClient from a TcpStream (typically used in a server).
14-
///
15-
/// An example client application:
1614
///
1715
/// ```no_run
1816
/// use websocket::WebSocketClient;
1917
/// use websocket::handshake::WebSocketRequest;
2018
///
21-
/// let request = WebSocketRequest::new("ws://127.0.0.1:1234", "myProtocol").unwrap();
19+
/// let request = WebSocketRequest::new("ws://127.0.0.1:1234", ["myProtocol"].as_slice()).unwrap();
2220
/// let key = request.key().unwrap();
2321
/// let mut client = WebSocketClient::connect(&request).unwrap();
2422
/// let response = client.receive_handshake_response().unwrap();
@@ -39,8 +37,8 @@ pub struct WebSocketClient {
3937
}
4038

4139
impl WebSocketClient {
42-
/// Connect to the WebSocket server using the given request. Use WebSocketRequest::new() to create a request for use
43-
/// with this function.
40+
/// Connect to the WebSocket server using the given request.
41+
/// Use WebSocketRequest::new() to create a request for use with this function.
4442
pub fn connect(request: &WebSocketRequest) -> IoResult<WebSocketClient> {
4543
let host = try!(request.headers.get("Host").ok_or(
4644
IoError {
@@ -64,6 +62,8 @@ impl WebSocketClient {
6462
/// The mask parameter determines whether or not messages send to the remote endpoint will be masked.
6563
/// If the client is connecting to a remote endpoint, set mask to true. If the client is the remote
6664
/// endpoint (and therefore, the server is the local endpoint), set mask to false.
65+
///
66+
/// Nothing is sent to or read from the stream during the conversion.
6767
pub fn from_stream(stream: TcpStream, mask: bool) -> WebSocketClient {
6868
WebSocketClient {
6969
stream: stream,
@@ -72,6 +72,7 @@ impl WebSocketClient {
7272
}
7373

7474
/// Returns a copy of the underlying TcpStream for this WebSocketClient.
75+
/// Note that writing to this stream will likely invalidate the WebSocket data stream.
7576
pub fn stream(&self) -> TcpStream {
7677
self.stream.clone()
7778
}

src/ws/handshake/request.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,26 @@ extern crate url;
66
use super::util::{ReadUntilStr, HeaderCollection, ReadHttpHeaders, WriteHttpHeaders};
77
use super::version::HttpVersion;
88
use url::{Url, ParseResult, ParseError};
9+
use std::fmt::Show;
910
use std::rand;
1011
use std::io::{Reader, Writer, IoResult, IoError, IoErrorKind};
1112
use serialize::base64::{ToBase64, STANDARD};
1213
use std::clone::Clone;
1314

1415
/// Represents a WebSocket handshake request, which is sent from the client to the server.
1516
/// Use the new() function to create a new request, and send it with the WebSocketClient::connect() function.
17+
/// Use the WebSocketClient.receive_handshake_request() method to read a WebSocketRequest from a remote client.
18+
///
19+
/// ```
20+
/// use websocket::handshake::WebSocketRequest;
21+
///
22+
/// let protocols = vec!["FirstPreference", "SecondPreference", "ThirdPreference"];
23+
/// let request = WebSocketRequest::new("ws://www.example.com:1234", protocols.as_slice()).unwrap();
24+
///
25+
/// assert_eq!(request.host().unwrap().as_slice(), "www.example.com:1234");
26+
/// assert_eq!(request.version().unwrap().as_slice(), "13");
27+
/// //...
28+
/// ```
1629
pub struct WebSocketRequest {
1730
/// The resource name of the request. E.g. /path/to/resource for the URI ws://www.example.com/path/to/resource
1831
pub resource_name: String,
@@ -26,7 +39,8 @@ pub struct WebSocketRequest {
2639

2740
impl WebSocketRequest {
2841
/// Creates a new WebSocket handshake request for use with WebSocketClient::connect().
29-
pub fn new(uri: &str, protocol: &str) -> ParseResult<WebSocketRequest> {
42+
/// The URI should use the ws:// scheme (wss:// not supported at this time).
43+
pub fn new<A: Show>(uri: &str, protocols: &[A]) -> ParseResult<WebSocketRequest> {
3044
let ws_uri = match Url::parse(uri) {
3145
Ok(uri) => { uri }
3246
Err(e) => { return Err(e); }
@@ -71,7 +85,10 @@ impl WebSocketRequest {
7185

7286
headers.insert("Sec-WebSocket-Key", key);
7387
headers.insert("Sec-WebSocket-Version", "13");
74-
headers.insert("Sec-WebSocket-Protocol", protocol);
88+
89+
for protocol in protocols.iter() {
90+
headers.insert("Sec-WebSocket-Protocol", protocol);
91+
}
7592

7693
Ok(WebSocketRequest {
7794
resource_name: resource_name,

src/ws/handshake/response.rs

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,25 @@ use super::util::{str_eq_ignore_case, ReadUntilStr, HeaderCollection, ReadHttpHe
66
use super::version::HttpVersion;
77
use sha1::Sha1;
88
use serialize::base64::{ToBase64, STANDARD};
9+
use std::fmt::Show;
910
use std::io::{Reader, Writer, IoResult, IoError, IoErrorKind};
1011
use std::string::ToString;
1112
use std::clone::Clone;
1213

1314
static MAGIC_GUID: &'static str = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
1415

15-
/// Represents a WebSocket response from a server
16+
/// Represents a WebSocket response which is sent from the server to the client.
17+
/// Use the new() function to create a new response, and send it with the WebSocketClient::send_handshake_response() function.
18+
///
19+
/// ```
20+
/// use websocket::handshake::WebSocketResponse;
21+
///
22+
/// let response = WebSocketResponse::new("dGhlIHNhbXBsZSBub25jZQ==", Some("myProtocol"));
23+
///
24+
/// assert_eq!(response.accept().unwrap().as_slice(), "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=");
25+
/// assert_eq!(response.upgrade().unwrap().as_slice(), "websocket");
26+
/// //...
27+
/// ```
1628
pub struct WebSocketResponse {
1729
/// The HTTP version of this request
1830
pub http_version: HttpVersion,
@@ -26,7 +38,7 @@ pub struct WebSocketResponse {
2638

2739
impl WebSocketResponse {
2840
/// Create a new WebSocket response based on the base-64 encoded key from a client.
29-
pub fn new(key: &str, protocol: Option<String>) -> WebSocketResponse {
41+
pub fn new<A: Show>(key: &str, protocol: Option<A>) -> WebSocketResponse {
3042
let accept = WebSocketResponse::gen_accept(key.to_string());
3143

3244
let status_code = 101;
@@ -71,8 +83,20 @@ impl WebSocketResponse {
7183
}
7284

7385
/// Short-cut to get the Sec-WebSocket-Version field value of this request
74-
pub fn version(&self) -> Option<String> {
75-
self.headers.get("Sec-WebSocket-Version")
86+
/// This may be present when the handshake fails (it should not appear on a successful
87+
/// handshake response.
88+
pub fn version(&self) -> Option<Vec<String>> {
89+
match self.headers.get("Sec-WebSocket-Version") {
90+
Some(version) => {
91+
let mut result: Vec<String> = Vec::new();
92+
let mut values = version.as_slice().split_str(",");
93+
for value in values {
94+
result.push(value.trim().to_string());
95+
}
96+
Some(result)
97+
}
98+
None => { None }
99+
}
76100
}
77101

78102
/// Short-cut to get the Sec-WebSocket-Extensions field value of this request
@@ -107,10 +131,6 @@ impl WebSocketResponse {
107131
/// the given key.
108132
pub fn is_successful<A: ToString>(&self, key: A) -> bool {
109133
self.status_code == 101 &&
110-
match self.version() {
111-
Some(version) => { version.as_slice() == "13" }
112-
None => { false }
113-
} &&
114134
match self.upgrade() {
115135
Some(upgrade) => { str_eq_ignore_case(upgrade.as_slice(), "websocket") }
116136
None => { false }

src/ws/message/receive.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use std::str::from_utf8;
1717
/// # use websocket::handshake::WebSocketRequest;
1818
/// # #[allow(unused_must_use)]
1919
/// # fn foo() {
20-
/// # let request = WebSocketRequest::new("ws://127.0.0.1:1234", "None").unwrap();
20+
/// # let request = WebSocketRequest::new("ws://127.0.0.1:1234", ["None"].as_slice()).unwrap();
2121
/// # let mut client = WebSocketClient::connect(&request).unwrap();
2222
///
2323
/// let receiver = client.receiver();

src/ws/message/send.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use std::rand;
1717
/// # use websocket::handshake::WebSocketRequest;
1818
/// # #[allow(unused_must_use)]
1919
/// # fn foo() {
20-
/// # let request = WebSocketRequest::new("ws://127.0.0.1:1234", "None").unwrap();
20+
/// # let request = WebSocketRequest::new("ws://127.0.0.1:1234", ["None"].as_slice()).unwrap();
2121
/// # let mut client = WebSocketClient::connect(&request).unwrap();
2222
///
2323
/// let mut sender = client.sender(); // Get a sender
@@ -104,7 +104,7 @@ impl WebSocketSender {
104104
/// # use websocket::handshake::WebSocketRequest;
105105
/// # #[allow(unused_must_use)]
106106
/// # fn foo() {
107-
/// # let request = WebSocketRequest::new("ws://127.0.0.1:1234", "None").unwrap();
107+
/// # let request = WebSocketRequest::new("ws://127.0.0.1:1234", ["None"].as_slice()).unwrap();
108108
/// # let mut client = WebSocketClient::connect(&request).unwrap();
109109
/// # let mut sender = client.sender();
110110
/// // Get a WebSocketFragmentSerializer

0 commit comments

Comments
 (0)