sled_web/
server.rs

1use hyper::{self, Server};
2use hyper::rt::Future;
3use hyper::service::service_fn;
4use response::{or_404, response};
5use sled;
6use std::net::SocketAddr;
7use std::sync::Arc;
8
9// Request strings.
10
11/// Configuration for the server.
12#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
13pub struct Config {
14    /// The socket address to which the server will bind and listen for HTTP requests.
15    ///
16    /// Defaults to localhost:3000. E.g. `([127, 0, 0, 1], 3000)`.
17    pub addr: SocketAddr,
18}
19
20/// A type used for building a `Config`.
21#[derive(Clone, Default, Eq, Hash, PartialEq, Serialize, Deserialize)]
22pub struct ConfigBuilder {
23    pub addr: Option<SocketAddr>,
24}
25
26/// Begin building the configuration for the server.
27pub fn config() -> ConfigBuilder {
28    Default::default()
29}
30
31// Implementations.
32
33impl Config {
34    /// The default IP address used if a socket address is not specified.
35    pub const DEFAULT_IP: [u8; 4] = [127, 0, 0, 1];
36    /// The default port used if a socket address is not specified.
37    pub const DEFAULT_PORT: u16 = 3000;
38    /// The default socket address used if one is not specified.
39    pub const DEFAULT_ADDR: ([u8; 4], u16) = (Self::DEFAULT_IP, Self::DEFAULT_PORT);
40}
41
42impl ConfigBuilder {
43    /// The socket address to which the server will bind and listen for HTTP requests.
44    ///
45    /// Defaults to localhost:3000. E.g. `([127, 0, 0, 1], 3000)`.
46    pub fn addr<T>(&mut self, addr: T) -> &mut Self
47    where
48        T: Into<SocketAddr>,
49    {
50        self.addr = Some(addr.into());
51        self
52    }
53
54    /// Build the `Config` type, replacing `None` values with defaults where necessary.
55    pub fn build(&mut self) -> Config {
56        let addr = self.addr.take().unwrap_or_else(|| Config::DEFAULT_ADDR.into());
57        Config { addr }
58    }
59}
60
61// Pure functions.
62
63/// Build the hyper `Server` with the given configuration and `sled::Tree`.
64///
65/// Returns a `Future` representing the `Server`'s computation.
66///
67/// To create and run your own server you can use the `response` function which simply translates
68/// requests to response futures.
69pub fn new(config: Config, tree: Arc<sled::Tree>) -> impl Future<Item = (), Error = hyper::Error> {
70    Server::bind(&config.addr)
71        .serve(move || {
72            let tree = tree.clone();
73            service_fn(move |req| {
74                or_404(response(req, tree.clone()))
75            })
76        })
77}
78
79/// Build and run a hyper `Server` using the default runtime with the given configuration and
80/// `sled::Tree`.
81pub fn run(config: Config, tree: Arc<sled::Tree>) {
82    let server = new(config, tree)
83        .map_err(|e| eprintln!("error occurred: {}", e));
84    hyper::rt::run(server);
85}