1 extern crate env_logger;
2 /// WebSocket server using trait objects to route
3 /// to an infinitely extensible number of handlers
4 extern crate ws;
5
6 // A WebSocket handler that routes connections to different boxed handlers by resource
7 struct Router {
8 sender: ws::Sender,
9 inner: Box<ws::Handler>,
10 }
11
12 impl ws::Handler for Router {
on_request(&mut self, req: &ws::Request) -> ws::Result<(ws::Response)>13 fn on_request(&mut self, req: &ws::Request) -> ws::Result<(ws::Response)> {
14 // Clone the sender so that we can move it into the child handler
15 let out = self.sender.clone();
16
17 match req.resource() {
18 "/echo" => self.inner = Box::new(Echo { ws: out }),
19
20 // Route to a data handler
21 "/data/one" => {
22 self.inner = Box::new(Data {
23 ws: out,
24 data: vec!["one", "two", "three", "four", "five"],
25 })
26 }
27
28 // Route to another data handler
29 "/data/two" => {
30 self.inner = Box::new(Data {
31 ws: out,
32 data: vec!["いち", "二", "さん", "四", "ご"],
33 })
34 }
35
36 // Use a closure as the child handler
37 "/closure" => {
38 self.inner = Box::new(move |msg: ws::Message| {
39 println!("Got a message on a closure handler: {}", msg);
40 out.close_with_reason(ws::CloseCode::Error, "Not Implemented.")
41 })
42 }
43
44 // Use the default child handler, NotFound
45 _ => (),
46 }
47
48 // Delegate to the child handler
49 self.inner.on_request(req)
50 }
51
52 // Pass through any other methods that should be delegated to the child.
53 //
54 // You could probably use a macro for this if you have many different
55 // routers or were building some sort of routing framework.
56
on_shutdown(&mut self)57 fn on_shutdown(&mut self) {
58 self.inner.on_shutdown()
59 }
60
on_open(&mut self, shake: ws::Handshake) -> ws::Result<()>61 fn on_open(&mut self, shake: ws::Handshake) -> ws::Result<()> {
62 self.inner.on_open(shake)
63 }
64
on_message(&mut self, msg: ws::Message) -> ws::Result<()>65 fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> {
66 self.inner.on_message(msg)
67 }
68
on_close(&mut self, code: ws::CloseCode, reason: &str)69 fn on_close(&mut self, code: ws::CloseCode, reason: &str) {
70 self.inner.on_close(code, reason)
71 }
72
on_error(&mut self, err: ws::Error)73 fn on_error(&mut self, err: ws::Error) {
74 self.inner.on_error(err);
75 }
76 }
77
78 // This handler returns a 404 response to all handshake requests
79 struct NotFound;
80
81 impl ws::Handler for NotFound {
on_request(&mut self, req: &ws::Request) -> ws::Result<(ws::Response)>82 fn on_request(&mut self, req: &ws::Request) -> ws::Result<(ws::Response)> {
83 // This handler responds to all requests with a 404
84 let mut res = ws::Response::from_request(req)?;
85 res.set_status(404);
86 res.set_reason("Not Found");
87 Ok(res)
88 }
89 }
90
91 // This handler simply echoes all messages back to the client
92 struct Echo {
93 ws: ws::Sender,
94 }
95
96 impl ws::Handler for Echo {
on_message(&mut self, msg: ws::Message) -> ws::Result<()>97 fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> {
98 println!("Echo handler received a message: {}", msg);
99 self.ws.send(msg)
100 }
101 }
102
103 // This handler sends some data to the client and then terminates the connection on the first
104 // message received, presumably confirming receipt of the data
105 struct Data {
106 ws: ws::Sender,
107 data: Vec<&'static str>,
108 }
109
110 impl ws::Handler for Data {
on_open(&mut self, _: ws::Handshake) -> ws::Result<()>111 fn on_open(&mut self, _: ws::Handshake) -> ws::Result<()> {
112 for msg in &self.data {
113 self.ws.send(*msg)?
114 }
115 Ok(())
116 }
117
on_message(&mut self, msg: ws::Message) -> ws::Result<()>118 fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> {
119 println!("Data handler received a message: {}", msg);
120 println!("Data handler going down.");
121 self.ws.close(ws::CloseCode::Normal)
122 }
123 }
124
main()125 fn main() {
126 env_logger::init();
127
128 // Listen on an address and call the closure for each connection
129 if let Err(error) = ws::listen("127.0.0.1:3012", |out| {
130 // Use our router as the handler to route the new connection
131 Router {
132 sender: out,
133 // Default to returning a 404 when the route doesn't match.
134 // You could default to any handler here.
135 inner: Box::new(NotFound),
136 }
137 }) {
138 // Inform the user of failure
139 println!("Failed to create WebSocket due to {:?}", error);
140 }
141 }
142