1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use afire::{
    middleware::{MiddleResult, Middleware},
    Content, Header, Method, Request, Response, Server,
};

use crate::Example;

// In afire Middleware is a trait that is implemented and can modify Requests and Response before and after Routes
// You can use Middleware to Log Requests, Ratelimit Requests, add Analytics, etc.
// The Middleware functions for this are `pre` and `post` for before and after the routes, there is also `end` which is called after the response is sent to the client
//
// There are two types of hooks: raw and non-raw.
// The raw hooks are passed a Result, and their default implementation calls the non-raw hooks if the Result is Ok.
// This allows you to handle errors (like page not found), while maintaining a clean API for middleware that doesn't need to handle errors.
//
// In the different middleware hooks you can return a MiddleResult, which is an enum with 3 variants:
// - Continue: Continue to the next middleware or route
// - Abort: Stop the middleware chain
// - Send: Immediately send this response to the client and stop the middleware chain
//
// For more info, checkout the documentation for Middleware here: https://docs.rs/afire/latest/afire/middleware/trait.Middleware.html

// Lets make a Middleware that will log the request to the console
// And to show how to modify the response, we will add a header to the response

struct Log;

// Now we will Implement Middleware for Log
impl Middleware for Log {
    // Redefine the `pre` function
    // (Runs before Routes)
    fn pre(&self, req: &mut Request) -> MiddleResult {
        // Print some info
        println!("[{}] {} {}", req.address.ip(), req.method, req.path);

        // Continue to forward the request to the next middleware or route
        MiddleResult::Continue
    }

    // Lets also modify the outgoing response by adding a header
    fn post(&self, _req: &Request, res: &mut Response) -> MiddleResult {
        res.headers.push(Header::new("X-Example", "Middleware"));
        MiddleResult::Continue
    }
}

pub struct MiddlewareExample;

impl Example for MiddlewareExample {
    fn name(&self) -> &'static str {
        "middleware"
    }

    fn exec(&self) {
        // Create a new Server instance on localhost port 8080
        let mut server = Server::<()>::new("localhost", 8080);

        // Define a basic route
        server.route(Method::GET, "/", |_req| {
            Response::new().text("Hello World!").content(Content::TXT)
        });

        // Here is where we will attach our Middleware to the Server
        // This is super easy
        Log.attach(&mut server);

        // You can now goto http://localhost:8080 you should see that the request is printed to the console
        // It should look something like this: `[127.0.0.1] GET `

        // Start the server
        // This will block the current thread
        server.start().unwrap();
    }
}