solicit/server/mod.rs
1//! The module contains a simple HTTP/2 server implementation.
2
3use http::{Response, HttpResult, HttpError, HttpScheme, Header, StreamId};
4use http::transport::TransportStream;
5use http::connection::{HttpConnection, EndStream, SendStatus};
6use http::session::{DefaultSessionState, SessionState, Stream};
7use http::server::ServerConnection;
8
9/// The struct represents a fully received request.
10pub struct ServerRequest<'a> {
11 pub stream_id: StreamId,
12 pub headers: &'a [Header],
13 pub body: &'a [u8],
14}
15
16/// The struct implements a simple HTTP/2 server that allows users to register a request handler (a
17/// callback taking a `ServerRequest` and returning a `Response`) which is run on all received
18/// requests.
19///
20/// The `handle_next` method needs to be called regularly in order to have the server process
21/// received frames, as well as send out the responses.
22///
23/// This is an exceedingly simple implementation of an HTTP/2 server and is mostly an example of
24/// how the `solicit::http` API can be used to make one.
25///
26/// # Examples
27///
28/// ```no_run
29/// extern crate solicit;
30/// use std::str;
31/// use std::net::{TcpListener, TcpStream};
32/// use std::thread;
33///
34/// use solicit::server::SimpleServer;
35///
36/// use solicit::http::Response;
37///
38/// fn main() {
39/// fn handle_client(stream: TcpStream) {
40/// let mut server = SimpleServer::new(stream, |req| {
41/// println!("Received request:");
42/// for header in req.headers.iter() {
43/// println!(" {}: {}",
44/// str::from_utf8(&header.0).unwrap(),
45/// str::from_utf8(&header.1).unwrap());
46/// }
47/// println!("Body:\n{}", str::from_utf8(&req.body).unwrap());
48///
49/// // Return a dummy response for every request
50/// Response {
51/// headers: vec![
52/// (b":status".to_vec(), b"200".to_vec()),
53/// (b"x-solicit".to_vec(), b"Hello, World!".to_vec()),
54/// ],
55/// body: vec![65],
56/// stream_id: req.stream_id,
57/// }
58/// }).unwrap();
59/// while let Ok(_) = server.handle_next() {}
60/// println!("Server done (client disconnected)");
61/// }
62///
63/// let listener = TcpListener::bind("127.0.0.1:8080").unwrap();
64/// for stream in listener.incoming() {
65/// let stream = stream.unwrap();
66/// thread::spawn(move || {
67/// handle_client(stream)
68/// });
69/// }
70/// }
71/// ```
72pub struct SimpleServer<TS, H> where TS: TransportStream, H: FnMut(ServerRequest) -> Response {
73 conn: ServerConnection<TS, TS>,
74 handler: H,
75}
76
77impl<TS, H> SimpleServer<TS, H>
78 where TS: TransportStream, H: FnMut(ServerRequest) -> Response {
79 /// Creates a new `SimpleServer` that will use the given `TransportStream` to communicate to
80 /// the client. Assumes that the stream is fully uninitialized -- no preface sent or read yet.
81 pub fn new(mut stream: TS, handler: H) -> HttpResult<SimpleServer<TS, H>> {
82 // First assert that the preface is received
83 let mut preface = [0; 24];
84 TransportStream::read_exact(&mut stream, &mut preface).unwrap();
85 if &preface != b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" {
86 return Err(HttpError::UnableToConnect);
87 }
88
89 let conn = HttpConnection::<TS, TS>::with_stream(stream, HttpScheme::Http);
90 let mut server = SimpleServer {
91 conn: ServerConnection::with_connection(conn, DefaultSessionState::new()),
92 handler: handler,
93 };
94
95 // Initialize the connection -- send own settings and process the peer's
96 try!(server.conn.init());
97
98 // Set up done
99 Ok(server)
100 }
101
102 /// Handles the next incoming frame, blocking to receive it if nothing is available on the
103 /// underlying stream.
104 ///
105 /// Handling the frame can trigger the handler callback. Any responses returned by the handler
106 /// are immediately flushed out to the client (blocking the call until it's done).
107 pub fn handle_next(&mut self) -> HttpResult<()> {
108 try!(self.conn.handle_next_frame());
109 let responses = try!(self.handle_requests());
110 try!(self.prepare_responses(responses));
111 try!(self.flush_streams());
112 try!(self.reap_streams());
113
114 Ok(())
115 }
116
117 /// Invokes the request handler for each fully received request. Collects all the responses
118 /// into the returned `Vec`.
119 fn handle_requests(&mut self) -> HttpResult<Vec<Response>> {
120 let handler = &mut self.handler;
121 Ok(self.conn.state.iter().filter(|s| s.is_closed_remote()).map(|stream| {
122 let req = ServerRequest {
123 stream_id: stream.stream_id,
124 headers: stream.headers.as_ref().unwrap(),
125 body: &stream.body,
126 };
127 handler(req)
128 }).collect())
129 }
130
131 /// Prepares the streams for each of the given responses. Headers for each response are
132 /// immediately sent and the data staged into the streams' outgoing buffer.
133 fn prepare_responses(&mut self, responses: Vec<Response>) -> HttpResult<()> {
134 for response in responses.into_iter() {
135 try!(self.conn.start_response(
136 response.headers,
137 response.stream_id,
138 EndStream::No));
139 let mut stream = self.conn.state.get_stream_mut(response.stream_id).unwrap();
140 stream.set_full_data(response.body);
141 }
142
143 Ok(())
144 }
145
146 /// Flushes the outgoing buffers of all streams.
147 #[inline]
148 fn flush_streams(&mut self) -> HttpResult<()> {
149 while let SendStatus::Sent = try!(self.conn.send_next_data()) {}
150
151 Ok(())
152 }
153
154 /// Removes closed streams from the connection state.
155 #[inline]
156 fn reap_streams(&mut self) -> HttpResult<()> {
157 // Moves the streams out of the state and then drops them
158 let _ = self.conn.state.get_closed();
159 Ok(())
160 }
161}