Struct Server

Source
pub struct Server<State: 'static + Send + Sync = ()> {
    pub port: u16,
    pub ip: IpAddr,
    pub routes: Vec<Route<State>>,
    pub middleware: Vec<Box<dyn Middleware + Send + Sync>>,
    pub state: Option<Arc<State>>,
    pub error_handler: Box<dyn Fn(Option<Arc<State>>, &Box<Result<Rc<Request>>>, String) -> Response + Send + Sync>,
    pub default_headers: Headers,
    pub keep_alive: bool,
    pub socket_timeout: Option<Duration>,
}
Expand description

Defines a server.

Fieldsยง

ยงport: u16

Port to listen on.

ยงip: IpAddr

Ip address to listen on.

ยงroutes: Vec<Route<State>>

Routes to handle.

ยงmiddleware: Vec<Box<dyn Middleware + Send + Sync>>

Middleware

ยงstate: Option<Arc<State>>

Server wide App State

ยงerror_handler: Box<dyn Fn(Option<Arc<State>>, &Box<Result<Rc<Request>>>, String) -> Response + Send + Sync>

Default response for internal server errors

ยงdefault_headers: Headers

Headers automatically added to every response.

ยงkeep_alive: bool

Weather to allow keep-alive connections. If this is set to false, the server will close the connection after every request. This is enabled by default.

ยงsocket_timeout: Option<Duration>

Socket Timeout

Implementationsยง

Sourceยง

impl<State: Send + Sync> Server<State>

Implementations for Server

Source

pub fn new(raw_ip: impl ToHostAddress, port: u16) -> Self

Creates a new server on the specified address and port. raw_ip can be either an IP address or โ€˜localhostโ€™, which expands to 127.0.0.1.

ยงExample
// Create a server for localhost on port 8080
// Note: The server has not been started yet
let mut server = Server::<()>::new("localhost", 8080);
Examples found in repository?
examples/middle_bench.rs (line 25)
23fn main() {
24    set_log_level(Level::Debug);
25    let mut server = Server::<()>::new([127, 0, 0, 1], 8080);
26    server.route(Method::ANY, "**", |_req| Response::new());
27
28    Middleware1.attach(&mut server);
29    Middleware2.attach(&mut server);
30    Middleware3.attach(&mut server);
31    Middleware4.attach(&mut server);
32    Middleware5.attach(&mut server);
33
34    server.start().unwrap();
35}
More examples
Hide additional examples
examples/basic/trace.rs (line 49)
41    fn exec(&self) {
42        // Set the log level to Trace (shows some helpful information during startup)
43        // The default is Level::Error
44        set_log_level(Level::Trace);
45        trace!(Level::Trace, "Setting log level to Trace");
46        trace!(Level::Error, "Example error message");
47
48        // Create a new Server instance on localhost port 8080
49        let mut server = Server::<()>::new("localhost", 8080);
50
51        server.route(Method::GET, "/", |req| {
52            // The default log level is Level::Trace so this will be logged
53            trace!("Request from {}", req.address.ip());
54            Response::new()
55        });
56
57        server.start().unwrap();
58    }
examples/basic/middleware.rs (line 56)
54    fn exec(&self) {
55        // Create a new Server instance on localhost port 8080
56        let mut server = Server::<()>::new("localhost", 8080);
57
58        // Define a basic route
59        server.route(Method::GET, "/", |_req| {
60            Response::new().text("Hello World!").content(Content::TXT)
61        });
62
63        // Here is where we will attach our Middleware to the Server
64        // This is super easy
65        Log.attach(&mut server);
66
67        // You can now goto http://localhost:8080 you should see that the request is printed to the console
68        // It should look something like this: `[127.0.0.1] GET `
69
70        // Start the server
71        // This will block the current thread
72        server.start().unwrap();
73    }
examples/basic/state.rs (line 26)
24    fn exec(&self) {
25        // Create a server on localhost port 8080 with a state of App
26        let mut server = Server::<App>::new("localhost", 8080).state(App::default());
27
28        // Add catch all route that takes in state and the request
29        server.stateful_route(Method::ANY, "**", |sta, _req| {
30            // Respond with and increment request count
31            Response::new().text(sta.count.fetch_add(1, Ordering::Relaxed))
32        });
33
34        // Start the server
35        // This will block the current thread
36        // Because there is a stateful route, this will panic if no state is set
37        server.start().unwrap();
38
39        // Now go to http://localhost:8080
40        // You should see the request count increment each time you refresh
41    }
examples/basic/threading.rs (line 26)
24    fn exec(&self) {
25        // Create a new Server instance on localhost port 8080
26        let mut server = Server::<()>::new("localhost", 8080);
27
28        // Define a handler for GET "/"
29        server.route(Method::GET, "/", |_req| {
30            Response::new()
31                // hopefully the ThreadId.as_u64 method will become stable
32                // until then im stuck with this mess for the example
33                // It just gets the thread ID to show the user what thread is handling the request
34                .text(format!(
35                    "Hello from thread number {:#?}!",
36                    unsafe { std::mem::transmute::<_, NonZeroU64>(thread::current().id()) }.get()
37                        - 1
38                ))
39                .content(Content::TXT)
40        });
41
42        // Start the server with 8 threads
43        // This will block the current thread
44        server.start_threaded(8).unwrap();
45
46        // If you go to http://localhost:8080 you should see the thread ID change with each refresh
47    }
examples/basic/path_prams.rs (line 18)
16    fn exec(&self) {
17        // Create a new Server instance on localhost port 8080
18        let mut server: Server = Server::<()>::new("localhost", 8081);
19
20        // Define a handler for GET "/greet/{name}"
21        // This will handel requests with anything where the {name} is
22        // This includes "/greet/bob", "/greet/fin"
23        server.route(Method::GET, "/greet/{name}", |req| {
24            // Get name path param
25            let name = req.param("name").unwrap();
26
27            // Make a nice Message to send
28            let message = format!("Hello, {}", name);
29
30            // Send Response
31            Response::new().text(message).content(Content::TXT)
32        });
33
34        // Define a greet route for Darren because he is very cool
35        // This will take priority over the other route as it is defined after
36        server.route(Method::GET, "/greet/Darren/", |_req| {
37            Response::new().text("Hello, Darren. You are very cool")
38        });
39
40        // Start the server
41        // This will block the current thread
42        server.start().unwrap();
43    }
Source

pub fn start(&self) -> Result<()>

Starts the server without a threadpool. This is blocking. Will return an error if the server cant bind to the specified address, or of you are using stateful routes and have not set the state. (See Server::state)

ยงExample
// Creates a server on localhost (127.0.0.1) port 8080
let mut server = Server::<()>::new("localhost", 8080);

/* Define Routes, Attach Middleware, etc. */

// Starts the server
// This is blocking
server.start().unwrap();
Examples found in repository?
examples/middle_bench.rs (line 34)
23fn main() {
24    set_log_level(Level::Debug);
25    let mut server = Server::<()>::new([127, 0, 0, 1], 8080);
26    server.route(Method::ANY, "**", |_req| Response::new());
27
28    Middleware1.attach(&mut server);
29    Middleware2.attach(&mut server);
30    Middleware3.attach(&mut server);
31    Middleware4.attach(&mut server);
32    Middleware5.attach(&mut server);
33
34    server.start().unwrap();
35}
More examples
Hide additional examples
examples/basic/trace.rs (line 57)
41    fn exec(&self) {
42        // Set the log level to Trace (shows some helpful information during startup)
43        // The default is Level::Error
44        set_log_level(Level::Trace);
45        trace!(Level::Trace, "Setting log level to Trace");
46        trace!(Level::Error, "Example error message");
47
48        // Create a new Server instance on localhost port 8080
49        let mut server = Server::<()>::new("localhost", 8080);
50
51        server.route(Method::GET, "/", |req| {
52            // The default log level is Level::Trace so this will be logged
53            trace!("Request from {}", req.address.ip());
54            Response::new()
55        });
56
57        server.start().unwrap();
58    }
examples/basic/middleware.rs (line 72)
54    fn exec(&self) {
55        // Create a new Server instance on localhost port 8080
56        let mut server = Server::<()>::new("localhost", 8080);
57
58        // Define a basic route
59        server.route(Method::GET, "/", |_req| {
60            Response::new().text("Hello World!").content(Content::TXT)
61        });
62
63        // Here is where we will attach our Middleware to the Server
64        // This is super easy
65        Log.attach(&mut server);
66
67        // You can now goto http://localhost:8080 you should see that the request is printed to the console
68        // It should look something like this: `[127.0.0.1] GET `
69
70        // Start the server
71        // This will block the current thread
72        server.start().unwrap();
73    }
examples/basic/state.rs (line 37)
24    fn exec(&self) {
25        // Create a server on localhost port 8080 with a state of App
26        let mut server = Server::<App>::new("localhost", 8080).state(App::default());
27
28        // Add catch all route that takes in state and the request
29        server.stateful_route(Method::ANY, "**", |sta, _req| {
30            // Respond with and increment request count
31            Response::new().text(sta.count.fetch_add(1, Ordering::Relaxed))
32        });
33
34        // Start the server
35        // This will block the current thread
36        // Because there is a stateful route, this will panic if no state is set
37        server.start().unwrap();
38
39        // Now go to http://localhost:8080
40        // You should see the request count increment each time you refresh
41    }
examples/basic/path_prams.rs (line 42)
16    fn exec(&self) {
17        // Create a new Server instance on localhost port 8080
18        let mut server: Server = Server::<()>::new("localhost", 8081);
19
20        // Define a handler for GET "/greet/{name}"
21        // This will handel requests with anything where the {name} is
22        // This includes "/greet/bob", "/greet/fin"
23        server.route(Method::GET, "/greet/{name}", |req| {
24            // Get name path param
25            let name = req.param("name").unwrap();
26
27            // Make a nice Message to send
28            let message = format!("Hello, {}", name);
29
30            // Send Response
31            Response::new().text(message).content(Content::TXT)
32        });
33
34        // Define a greet route for Darren because he is very cool
35        // This will take priority over the other route as it is defined after
36        server.route(Method::GET, "/greet/Darren/", |_req| {
37            Response::new().text("Hello, Darren. You are very cool")
38        });
39
40        // Start the server
41        // This will block the current thread
42        server.start().unwrap();
43    }
examples/basic/serve_file.rs (line 44)
19    fn exec(&self) {
20        // Create a new Server instance on localhost port 8080
21        let mut server = Server::<()>::new("localhost", 8080);
22
23        // Define a handler for GET "/"
24        server.route(Method::GET, "/", |_req| {
25            // Try to open a file
26            match File::open("examples/basic/data/index.html") {
27                // If its found send it as response
28                // Because we used File::open and not fs::read, we can use the stream method to send the file in chunks
29                // This is more efficient than reading the whole file into memory and then sending it
30                Ok(content) => Response::new().stream(content).content(Content::HTML),
31
32                // If the file is not found, send a 404 response
33                Err(_) => Response::new()
34                    .status(Status::NotFound)
35                    .text("Not Found :/")
36                    .content(Content::TXT),
37            }
38        });
39
40        // View the file at http://localhost:8080
41
42        // Start the server
43        // This will block the current thread
44        server.start().unwrap();
45    }
Source

pub fn start_threaded(self, threads: usize) -> Result<()>

Start the server with a threadpool of threads threads. Just like Server::start, this is blocking. Will return an error if the server cant bind to the specified address, or of you are using stateful routes and have not set the state. (See Server::state)

ยงExample
// Import Library
use afire::{Server, Response, Header, Method};

// Creates a server on localhost (127.0.0.1) port 8080
let mut server = Server::<()>::new("localhost", 8080);

/* Define Routes, Attach Middleware, etc. */

// Starts the server with 4 threads
// This is blocking
server.start_threaded(4).unwrap();
Examples found in repository?
examples/basic/threading.rs (line 44)
24    fn exec(&self) {
25        // Create a new Server instance on localhost port 8080
26        let mut server = Server::<()>::new("localhost", 8080);
27
28        // Define a handler for GET "/"
29        server.route(Method::GET, "/", |_req| {
30            Response::new()
31                // hopefully the ThreadId.as_u64 method will become stable
32                // until then im stuck with this mess for the example
33                // It just gets the thread ID to show the user what thread is handling the request
34                .text(format!(
35                    "Hello from thread number {:#?}!",
36                    unsafe { std::mem::transmute::<_, NonZeroU64>(thread::current().id()) }.get()
37                        - 1
38                ))
39                .content(Content::TXT)
40        });
41
42        // Start the server with 8 threads
43        // This will block the current thread
44        server.start_threaded(8).unwrap();
45
46        // If you go to http://localhost:8080 you should see the thread ID change with each refresh
47    }
Source

pub fn default_header( self, key: impl Into<HeaderType>, value: impl AsRef<str>, ) -> Self

Add a new default header to the server. This will be added to every response if it is not already present.

This will be added to every response

ยงExample
// Create a server for localhost on port 8080
let mut server = Server::<()>::new("localhost", 8080)
    // Add a default header to the response
    .default_header("X-Server", "afire");
Examples found in repository?
examples/basic/header.rs (line 22)
14    fn exec(&self) {
15        // Create a new Server instance on localhost port 8080
16        let mut server = Server::<()>::new("localhost", 8080)
17            // Define server wide default headers
18            // These will be send with every response
19            // If the same header is defined in the route it will be put before the default header
20            // Although it is not guaranteed to be the one picked by the client it usually is
21            // At the bottom of this file is a representation of the order of the headers
22            .default_header("X-Server-Header", "This is a server wide header")
23            // You can also use the HeaderType enum to define a header type
24            // This is also true with the .header method on the Response struct
25            .default_header(HeaderType::Server, "afire");
26
27        // Define a route to redirect to another website
28        server.route(Method::GET, "/", |_req| {
29            // Because this is all bout headers I have put the header vector here
30            let headers = vec![
31                // Tell the client what type of data we are sending
32                afire::Header::new(HeaderType::ContentType, "text/html"),
33                // Tell the client to redirect to another website
34                afire::Header::new(HeaderType::Location, "https://connorcode.com"),
35                // Custom header
36                afire::Header::new("X-Custom-Header", "This is a custom header"),
37            ];
38
39            // Define response body
40            // In this case this should only be seen if the client doesn't support redirects for some reason
41            let text = "<a href=\"https://connorcode.com\">connorcode</a>";
42
43            // The response code of 308 tells the client to redirect to the location specified in the header
44            // There are other response codes you can use too
45            // 301 -> Moved Permanently
46            // 302 -> Found
47            // 303 -> See Other
48            // 307 -> Temporary Redirect
49            // 308 -> Permanent Redirect
50            Response::new()
51                .status(Status::PermanentRedirect)
52                .text(text)
53                .headers(&headers)
54        });
55
56        // Now to define a route to handle client headers
57        // This will just echo the headers back to the client
58        server.route(Method::GET, "/headers", |req| {
59            // Get the headers from the request and make a html string
60            let body = req
61                .headers
62                .iter()
63                .fold(String::new(), |old, new| old + &format!("{:?}<br />", new));
64
65            // Create a response with the headers
66            Response::new().text(body).content(Content::HTML)
67        });
68
69        // You can now goto http://localhost:8080 you should see a redirect to https://connorcode.com
70        // And you can goto http://localhost:8080/headers to see the headers your client sent to the server
71
72        // Start the server
73        // This will block the current thread
74        server.start().unwrap();
75    }
Source

pub fn socket_timeout(self, socket_timeout: Duration) -> Self

Set the timeout for the socket. This will ensure that the server will not hang on a request for too long. By default there is no timeout.

ยงExample
// Create a server for localhost on port 8080
let mut server = Server::<()>::new("localhost", 8080)
    // Set socket timeout
    .socket_timeout(Duration::from_secs(5));
Source

pub fn keep_alive(self, keep_alive: bool) -> Self

Set the keep alive state of the server. This will determine if the server will keep the connection alive after a request. By default this is true. If you arenโ€™t using a threadpool, you may want to set this to false.

ยงExample
// Create a server for localhost on port 8080
let mut server = Server::<()>::new("localhost", 8080)
    // Disable Keep Alive
    .keep_alive(false);
Source

pub fn state(self, state: State) -> Self

Set the state of a server. The state will be available to stateful routes (Server::stateful_route) and middleware. It is not mutable, so you will need to use an atomic or sync type to mutate it.

ยงExample
// Create a server for localhost on port 8080
// Note: We can omit the type parameter here because we are setting the state
let mut server = Server::new("localhost", 8080)
    // Set server wide state
    .state(AtomicU32::new(0));

// Add a stateful route to increment the state
server.stateful_route(Method::GET, "/", |state, _req| {
    Response::new().text(state.fetch_add(1, Ordering::Relaxed))
});
Examples found in repository?
examples/basic/state.rs (line 26)
24    fn exec(&self) {
25        // Create a server on localhost port 8080 with a state of App
26        let mut server = Server::<App>::new("localhost", 8080).state(App::default());
27
28        // Add catch all route that takes in state and the request
29        server.stateful_route(Method::ANY, "**", |sta, _req| {
30            // Respond with and increment request count
31            Response::new().text(sta.count.fetch_add(1, Ordering::Relaxed))
32        });
33
34        // Start the server
35        // This will block the current thread
36        // Because there is a stateful route, this will panic if no state is set
37        server.start().unwrap();
38
39        // Now go to http://localhost:8080
40        // You should see the request count increment each time you refresh
41    }
More examples
Hide additional examples
examples/application_quote_book.rs (line 39)
34fn main() {
35    set_log_level(Level::Trace);
36    let app = App::new(PathBuf::from("quotes.txt"));
37    app.load();
38
39    let mut server = Server::new(Ipv4Addr::LOCALHOST, 8080).state(app);
40
41    // Route to serve the homepage (page that has add quote form)
42    server.route(Method::GET, "/", |_| {
43        Response::new()
44            .text(String::new() + HEADER + HOME)
45            .content(Content::HTML)
46    });
47
48    // Route to handle creating new quotes.
49    // After successful creation the user will be redirected to the new quotes page.
50    server.stateful_route(Method::POST, "/api/new", |app, req| {
51        let form = Query::from_body(&String::from_utf8_lossy(&req.body));
52        let name =
53            url::decode(form.get("author").expect("No author supplied")).expect("Invalid author");
54        let body =
55            url::decode(form.get("quote").expect("No quote supplied")).expect("Invalid quote");
56
57        let quote = Quote {
58            name,
59            value: body,
60            date: now(),
61        };
62        let mut quotes = app.quotes.write().unwrap();
63        let id = quotes.len();
64        quotes.insert(id.to_string(), quote);
65        drop(quotes);
66        trace!(Level::Trace, "Added new quote #{id}");
67
68        app.save();
69        Response::new()
70            .status(Status::SeeOther)
71            .header(HeaderType::Location, format!("/quote/{id}"))
72            .text("Redirecting to quote page.")
73    });
74
75    server.stateful_route(Method::GET, "/quote/{id}", |app, req| {
76        let id = req.param("id").unwrap();
77        if id == "undefined" {
78            return Response::new();
79        }
80
81        let id = id.parse::<usize>().expect("ID is not a valid integer");
82        let quotes = app.quotes.read().unwrap();
83        if id >= quotes.len() {
84            return Response::new()
85                .status(Status::NotFound)
86                .text(format!("No quote with the id {id} was found."));
87        }
88
89        let quote = quotes.get(&id.to_string()).unwrap();
90        Response::new().content(Content::HTML).text(
91            String::new()
92                + HEADER
93                + &QUOTE
94                    .replace("{QUOTE}", &quote.value)
95                    .replace("{AUTHOR}", &quote.name)
96                    .replace("{TIME}", &imp_date(quote.date)),
97        )
98    });
99
100    server.stateful_route(Method::GET, "/quotes", |app, _req| {
101        let mut out = String::from(HEADER);
102        out.push_str("<ul>");
103        for i in app.quotes.read().unwrap().iter() {
104            out.push_str(&format!(
105                "<li><a href=\"/quote/{}\">\"{}\" - {}</a></li>\n",
106                i.0, i.1.name, i.1.value
107            ));
108        }
109
110        Response::new().text(out + "</ul>").content(Content::HTML)
111    });
112
113    // Note: In a production application you may want to multithread the server with the Server::start_threaded method.
114    server.start().unwrap();
115}
examples/application_paste_bin.rs (line 23)
21fn main() {
22    // Create Server
23    let mut server = Server::new("localhost", 8080).state(RwLock::new(Vec::new()));
24
25    // New paste interface
26    server.route(Method::GET, "/", |_req| {
27        Response::new().content(Content::HTML).text(
28            r#"
29        <form action="/new-form" method="post">
30        <input type="text" name="name" id="name" placeholder="Title">
31        
32        <br />
33        <textarea id="body" name="body" rows="5" cols="33"></textarea>
34        <input type="submit" value="Submit" />
35    </form>
36    "#,
37        )
38    });
39
40    // New paste API handler
41    server.stateful_route(Method::POST, "/new", move |app, req| {
42        // Make sure paste data isn't too long
43        if req.body.len() > DATA_LIMIT {
44            return Response::new()
45                .status(Status::NotFound)
46                .text("Data too big!");
47        }
48
49        // Get the data as string
50        let body_str = String::from_utf8_lossy(&req.body).to_string();
51
52        // Get the name from the Name header
53        let name = req.headers.get("Name").unwrap_or("Untitled");
54
55        let paste = Paste {
56            name: name.to_owned(),
57            body: body_str,
58            time: Instant::now(),
59        };
60
61        // Push this paste to the pastes vector
62        let mut pastes = app.write().unwrap();
63        let id = pastes.len();
64        pastes.push(paste);
65
66        // Send Redirect response
67        Response::new()
68            .status(Status::MovedPermanently)
69            .header(HeaderType::Location, format!("/p/{id}"))
70            .text(format!("Redirecting to /p/{id}."))
71    });
72
73    // New paste form handler
74    server.stateful_route(Method::POST, "/new-form", |app, req| {
75        // Get data from response
76        let query = Query::from_body(String::from_utf8_lossy(&req.body).borrow());
77        let name = url::decode(query.get("name").unwrap_or("Untitled")).expect("Invalid name");
78        let body = url::decode(query.get("body").expect("No body supplied")).expect("Invalid body");
79
80        // Make sure paste data isn't too long
81        if body.len() > DATA_LIMIT {
82            return Response::new()
83                .status(Status::NotFound)
84                .text("Data too big!");
85        }
86
87        let paste = Paste {
88            name,
89            body,
90            time: Instant::now(),
91        };
92
93        // Push this paste to the pastes vector
94        let mut pastes = app.write().unwrap();
95        let id = pastes.len();
96        pastes.push(paste);
97
98        // Send Redirect response
99        Response::new()
100            .status(Status::MovedPermanently)
101            .text("Ok")
102            .header(HeaderType::Location, format!("/p/{}", id))
103    });
104
105    // Get pate handler
106    server.stateful_route(Method::GET, "/p/{id}", move |app, req| {
107        // Get is from path param
108        let id = req.param("id").unwrap().parse::<usize>().unwrap();
109
110        // Get the paste by id
111        let paste = &app.read().unwrap()[id];
112
113        // Send paste
114        Response::new().text(&paste.body)
115    });
116
117    // View all pastes
118    server.stateful_route(Method::GET, "/pastes", move |app, _req| {
119        // Starter HTML
120        let mut out = String::from(
121            r#"<a href="/">New Paste</a><meta charset="UTF-8"><table><tr><th>Name</th><th>Date</th><th>Link</th></tr>"#,
122        );
123
124        // Add a table row for each paste
125        for (i, e) in app.read().unwrap().iter().enumerate() {
126            out.push_str(&format!(
127                "<tr><td>{}</td><td>{}</td><td><a href=\"/p/{}\">๐Ÿ”—</a></td></tr>",
128                e.name,
129                fmt_relative_time(e.time.elapsed().as_secs()),
130                i
131            ));
132        }
133
134        // Send HTML
135        Response::new()
136            .text(format!("{}</table>", out))
137            .content(Content::HTML)
138    });
139
140    server.start().unwrap();
141}
Source

pub fn error_handler( &mut self, res: impl Fn(Option<Arc<State>>, &Box<Result<Rc<Request>>>, String) -> Response + Send + Sync + 'static, )

Set the panic handler, which is called if a route or middleware panics. This is only available if the panic_handler feature is enabled. If you donโ€™t set it, the default response is 500 โ€œInternal Server Error :/โ€. Be sure that your panic handler wont panic, because that will just panic the whole application.

ยงExample
// Set the panic handler response
server.error_handler(|_state, _req, err| {
    Response::new()
        .status(Status::InternalServerError)
        .text(format!("Internal Server Error: {}", err))
});
Examples found in repository?
examples/basic/error_handling.rs (lines 38-47)
20    fn exec(&self) {
21        // Create a new Server instance on localhost port 8080
22        let mut server = Server::<()>::new("localhost", 8080);
23
24        // Define a route that will panic
25        server.route(Method::GET, "/panic", |_req| panic!("This is a panic!"));
26
27        // Give the server a main page
28        server.route(Method::GET, "/", |_req| {
29            Response::new()
30                .text(r#"<a href="/panic">PANIC</a>"#)
31                .content(Content::HTML)
32        });
33
34        // You can optionally define a custom error handler
35        // This can be defined anywhere in the server and will take affect for all routes
36        // Its like a normal route, but it will only be called if the route panics
37        let errors = AtomicUsize::new(1);
38        server.error_handler(move |_state, _req, err| {
39            Response::new()
40                .status(Status::InternalServerError)
41                .text(format!(
42                    "<h1>Internal Server Error #{}</h1><br>Panicked at '{}'",
43                    errors.fetch_add(1, Ordering::Relaxed),
44                    err
45                ))
46                .content(Content::HTML)
47        });
48
49        // You can now goto http://localhost:8080/panic
50        // This will cause the route to panic and return a 500 error
51
52        // Start the server
53        // This will block the current thread
54        server.start().unwrap();
55    }
Source

pub fn route( &mut self, method: Method, path: impl AsRef<str>, handler: impl Fn(&Request) -> Response + Send + Sync + 'static, ) -> &mut Self

Create a new route. The path can contain parameters, which are defined with {...}, as well as wildcards, which are defined with *. (** lets you math anything after the wildcard, including /)

ยงExample
// Define a route
server.route(Method::GET, "/greet/{name}", |req| {
    let name = req.param("name").unwrap();

    Response::new()
        .text(format!("Hello, {}!", name))
        .content(Content::TXT)
});
Examples found in repository?
examples/middle_bench.rs (line 26)
23fn main() {
24    set_log_level(Level::Debug);
25    let mut server = Server::<()>::new([127, 0, 0, 1], 8080);
26    server.route(Method::ANY, "**", |_req| Response::new());
27
28    Middleware1.attach(&mut server);
29    Middleware2.attach(&mut server);
30    Middleware3.attach(&mut server);
31    Middleware4.attach(&mut server);
32    Middleware5.attach(&mut server);
33
34    server.start().unwrap();
35}
More examples
Hide additional examples
examples/basic/trace.rs (lines 51-55)
41    fn exec(&self) {
42        // Set the log level to Trace (shows some helpful information during startup)
43        // The default is Level::Error
44        set_log_level(Level::Trace);
45        trace!(Level::Trace, "Setting log level to Trace");
46        trace!(Level::Error, "Example error message");
47
48        // Create a new Server instance on localhost port 8080
49        let mut server = Server::<()>::new("localhost", 8080);
50
51        server.route(Method::GET, "/", |req| {
52            // The default log level is Level::Trace so this will be logged
53            trace!("Request from {}", req.address.ip());
54            Response::new()
55        });
56
57        server.start().unwrap();
58    }
examples/basic/middleware.rs (lines 59-61)
54    fn exec(&self) {
55        // Create a new Server instance on localhost port 8080
56        let mut server = Server::<()>::new("localhost", 8080);
57
58        // Define a basic route
59        server.route(Method::GET, "/", |_req| {
60            Response::new().text("Hello World!").content(Content::TXT)
61        });
62
63        // Here is where we will attach our Middleware to the Server
64        // This is super easy
65        Log.attach(&mut server);
66
67        // You can now goto http://localhost:8080 you should see that the request is printed to the console
68        // It should look something like this: `[127.0.0.1] GET `
69
70        // Start the server
71        // This will block the current thread
72        server.start().unwrap();
73    }
examples/basic/threading.rs (lines 29-40)
24    fn exec(&self) {
25        // Create a new Server instance on localhost port 8080
26        let mut server = Server::<()>::new("localhost", 8080);
27
28        // Define a handler for GET "/"
29        server.route(Method::GET, "/", |_req| {
30            Response::new()
31                // hopefully the ThreadId.as_u64 method will become stable
32                // until then im stuck with this mess for the example
33                // It just gets the thread ID to show the user what thread is handling the request
34                .text(format!(
35                    "Hello from thread number {:#?}!",
36                    unsafe { std::mem::transmute::<_, NonZeroU64>(thread::current().id()) }.get()
37                        - 1
38                ))
39                .content(Content::TXT)
40        });
41
42        // Start the server with 8 threads
43        // This will block the current thread
44        server.start_threaded(8).unwrap();
45
46        // If you go to http://localhost:8080 you should see the thread ID change with each refresh
47    }
examples/basic/path_prams.rs (lines 23-32)
16    fn exec(&self) {
17        // Create a new Server instance on localhost port 8080
18        let mut server: Server = Server::<()>::new("localhost", 8081);
19
20        // Define a handler for GET "/greet/{name}"
21        // This will handel requests with anything where the {name} is
22        // This includes "/greet/bob", "/greet/fin"
23        server.route(Method::GET, "/greet/{name}", |req| {
24            // Get name path param
25            let name = req.param("name").unwrap();
26
27            // Make a nice Message to send
28            let message = format!("Hello, {}", name);
29
30            // Send Response
31            Response::new().text(message).content(Content::TXT)
32        });
33
34        // Define a greet route for Darren because he is very cool
35        // This will take priority over the other route as it is defined after
36        server.route(Method::GET, "/greet/Darren/", |_req| {
37            Response::new().text("Hello, Darren. You are very cool")
38        });
39
40        // Start the server
41        // This will block the current thread
42        server.start().unwrap();
43    }
examples/basic/serve_file.rs (lines 24-38)
19    fn exec(&self) {
20        // Create a new Server instance on localhost port 8080
21        let mut server = Server::<()>::new("localhost", 8080);
22
23        // Define a handler for GET "/"
24        server.route(Method::GET, "/", |_req| {
25            // Try to open a file
26            match File::open("examples/basic/data/index.html") {
27                // If its found send it as response
28                // Because we used File::open and not fs::read, we can use the stream method to send the file in chunks
29                // This is more efficient than reading the whole file into memory and then sending it
30                Ok(content) => Response::new().stream(content).content(Content::HTML),
31
32                // If the file is not found, send a 404 response
33                Err(_) => Response::new()
34                    .status(Status::NotFound)
35                    .text("Not Found :/")
36                    .content(Content::TXT),
37            }
38        });
39
40        // View the file at http://localhost:8080
41
42        // Start the server
43        // This will block the current thread
44        server.start().unwrap();
45    }
Source

pub fn stateful_route( &mut self, method: Method, path: impl AsRef<str>, handler: impl Fn(Arc<State>, &Request) -> Response + Send + Sync + 'static, ) -> &mut Self

Create a new stateful route. Is the same as Server::route, but the state is passed as the first parameter. (See Server::state)

Note: If you add a stateful route, you must also set the state or starting the sever will return an error.

ยงExample
// Create a server for localhost on port 8080
let mut server = Server::<u32>::new("localhost", 8080)
   .state(101);

// Define a route
server.stateful_route(Method::GET, "/nose", |sta, req| {
    Response::new().text(sta.to_string())
});
Examples found in repository?
examples/basic/state.rs (lines 29-32)
24    fn exec(&self) {
25        // Create a server on localhost port 8080 with a state of App
26        let mut server = Server::<App>::new("localhost", 8080).state(App::default());
27
28        // Add catch all route that takes in state and the request
29        server.stateful_route(Method::ANY, "**", |sta, _req| {
30            // Respond with and increment request count
31            Response::new().text(sta.count.fetch_add(1, Ordering::Relaxed))
32        });
33
34        // Start the server
35        // This will block the current thread
36        // Because there is a stateful route, this will panic if no state is set
37        server.start().unwrap();
38
39        // Now go to http://localhost:8080
40        // You should see the request count increment each time you refresh
41    }
More examples
Hide additional examples
examples/application_quote_book.rs (lines 50-73)
34fn main() {
35    set_log_level(Level::Trace);
36    let app = App::new(PathBuf::from("quotes.txt"));
37    app.load();
38
39    let mut server = Server::new(Ipv4Addr::LOCALHOST, 8080).state(app);
40
41    // Route to serve the homepage (page that has add quote form)
42    server.route(Method::GET, "/", |_| {
43        Response::new()
44            .text(String::new() + HEADER + HOME)
45            .content(Content::HTML)
46    });
47
48    // Route to handle creating new quotes.
49    // After successful creation the user will be redirected to the new quotes page.
50    server.stateful_route(Method::POST, "/api/new", |app, req| {
51        let form = Query::from_body(&String::from_utf8_lossy(&req.body));
52        let name =
53            url::decode(form.get("author").expect("No author supplied")).expect("Invalid author");
54        let body =
55            url::decode(form.get("quote").expect("No quote supplied")).expect("Invalid quote");
56
57        let quote = Quote {
58            name,
59            value: body,
60            date: now(),
61        };
62        let mut quotes = app.quotes.write().unwrap();
63        let id = quotes.len();
64        quotes.insert(id.to_string(), quote);
65        drop(quotes);
66        trace!(Level::Trace, "Added new quote #{id}");
67
68        app.save();
69        Response::new()
70            .status(Status::SeeOther)
71            .header(HeaderType::Location, format!("/quote/{id}"))
72            .text("Redirecting to quote page.")
73    });
74
75    server.stateful_route(Method::GET, "/quote/{id}", |app, req| {
76        let id = req.param("id").unwrap();
77        if id == "undefined" {
78            return Response::new();
79        }
80
81        let id = id.parse::<usize>().expect("ID is not a valid integer");
82        let quotes = app.quotes.read().unwrap();
83        if id >= quotes.len() {
84            return Response::new()
85                .status(Status::NotFound)
86                .text(format!("No quote with the id {id} was found."));
87        }
88
89        let quote = quotes.get(&id.to_string()).unwrap();
90        Response::new().content(Content::HTML).text(
91            String::new()
92                + HEADER
93                + &QUOTE
94                    .replace("{QUOTE}", &quote.value)
95                    .replace("{AUTHOR}", &quote.name)
96                    .replace("{TIME}", &imp_date(quote.date)),
97        )
98    });
99
100    server.stateful_route(Method::GET, "/quotes", |app, _req| {
101        let mut out = String::from(HEADER);
102        out.push_str("<ul>");
103        for i in app.quotes.read().unwrap().iter() {
104            out.push_str(&format!(
105                "<li><a href=\"/quote/{}\">\"{}\" - {}</a></li>\n",
106                i.0, i.1.name, i.1.value
107            ));
108        }
109
110        Response::new().text(out + "</ul>").content(Content::HTML)
111    });
112
113    // Note: In a production application you may want to multithread the server with the Server::start_threaded method.
114    server.start().unwrap();
115}
examples/application_paste_bin.rs (lines 41-71)
21fn main() {
22    // Create Server
23    let mut server = Server::new("localhost", 8080).state(RwLock::new(Vec::new()));
24
25    // New paste interface
26    server.route(Method::GET, "/", |_req| {
27        Response::new().content(Content::HTML).text(
28            r#"
29        <form action="/new-form" method="post">
30        <input type="text" name="name" id="name" placeholder="Title">
31        
32        <br />
33        <textarea id="body" name="body" rows="5" cols="33"></textarea>
34        <input type="submit" value="Submit" />
35    </form>
36    "#,
37        )
38    });
39
40    // New paste API handler
41    server.stateful_route(Method::POST, "/new", move |app, req| {
42        // Make sure paste data isn't too long
43        if req.body.len() > DATA_LIMIT {
44            return Response::new()
45                .status(Status::NotFound)
46                .text("Data too big!");
47        }
48
49        // Get the data as string
50        let body_str = String::from_utf8_lossy(&req.body).to_string();
51
52        // Get the name from the Name header
53        let name = req.headers.get("Name").unwrap_or("Untitled");
54
55        let paste = Paste {
56            name: name.to_owned(),
57            body: body_str,
58            time: Instant::now(),
59        };
60
61        // Push this paste to the pastes vector
62        let mut pastes = app.write().unwrap();
63        let id = pastes.len();
64        pastes.push(paste);
65
66        // Send Redirect response
67        Response::new()
68            .status(Status::MovedPermanently)
69            .header(HeaderType::Location, format!("/p/{id}"))
70            .text(format!("Redirecting to /p/{id}."))
71    });
72
73    // New paste form handler
74    server.stateful_route(Method::POST, "/new-form", |app, req| {
75        // Get data from response
76        let query = Query::from_body(String::from_utf8_lossy(&req.body).borrow());
77        let name = url::decode(query.get("name").unwrap_or("Untitled")).expect("Invalid name");
78        let body = url::decode(query.get("body").expect("No body supplied")).expect("Invalid body");
79
80        // Make sure paste data isn't too long
81        if body.len() > DATA_LIMIT {
82            return Response::new()
83                .status(Status::NotFound)
84                .text("Data too big!");
85        }
86
87        let paste = Paste {
88            name,
89            body,
90            time: Instant::now(),
91        };
92
93        // Push this paste to the pastes vector
94        let mut pastes = app.write().unwrap();
95        let id = pastes.len();
96        pastes.push(paste);
97
98        // Send Redirect response
99        Response::new()
100            .status(Status::MovedPermanently)
101            .text("Ok")
102            .header(HeaderType::Location, format!("/p/{}", id))
103    });
104
105    // Get pate handler
106    server.stateful_route(Method::GET, "/p/{id}", move |app, req| {
107        // Get is from path param
108        let id = req.param("id").unwrap().parse::<usize>().unwrap();
109
110        // Get the paste by id
111        let paste = &app.read().unwrap()[id];
112
113        // Send paste
114        Response::new().text(&paste.body)
115    });
116
117    // View all pastes
118    server.stateful_route(Method::GET, "/pastes", move |app, _req| {
119        // Starter HTML
120        let mut out = String::from(
121            r#"<a href="/">New Paste</a><meta charset="UTF-8"><table><tr><th>Name</th><th>Date</th><th>Link</th></tr>"#,
122        );
123
124        // Add a table row for each paste
125        for (i, e) in app.read().unwrap().iter().enumerate() {
126            out.push_str(&format!(
127                "<tr><td>{}</td><td>{}</td><td><a href=\"/p/{}\">๐Ÿ”—</a></td></tr>",
128                e.name,
129                fmt_relative_time(e.time.elapsed().as_secs()),
130                i
131            ));
132        }
133
134        // Send HTML
135        Response::new()
136            .text(format!("{}</table>", out))
137            .content(Content::HTML)
138    });
139
140    server.start().unwrap();
141}
Source

pub fn app(&self) -> Arc<State>

Gets a reference to the current server state set outside of stateful routes. Will panic if the server has no state.

ยงExample
// Create a server for localhost on port 8080
let mut server = Server::<u32>::new("localhost", 8080).state(101);

// Get its state and assert it is 101
assert_eq!(*server.app(), 101);

Auto Trait Implementationsยง

ยง

impl<State> Freeze for Server<State>

ยง

impl<State = ()> !RefUnwindSafe for Server<State>

ยง

impl<State> Send for Server<State>

ยง

impl<State> Sync for Server<State>

ยง

impl<State> Unpin for Server<State>

ยง

impl<State = ()> !UnwindSafe for Server<State>

Blanket Implementationsยง

Sourceยง

impl<T> Any for T
where T: 'static + ?Sized,

Sourceยง

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Sourceยง

impl<T> Borrow<T> for T
where T: ?Sized,

Sourceยง

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Sourceยง

impl<T> BorrowMut<T> for T
where T: ?Sized,

Sourceยง

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Sourceยง

impl<T> From<T> for T

Sourceยง

fn from(t: T) -> T

Returns the argument unchanged.

Sourceยง

impl<T, U> Into<U> for T
where U: From<T>,

Sourceยง

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Sourceยง

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Sourceยง

type Error = Infallible

The type returned in the event of a conversion error.
Sourceยง

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Sourceยง

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Sourceยง

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Sourceยง

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.