Skip to main content

nanofish_client/
handler.rs

1use crate::{
2    error::Error,
3    header::HttpHeader,
4    request::HttpRequest,
5    response::{HttpResponse, ResponseBody},
6    status_code::StatusCode,
7};
8use heapless::Vec;
9
10/// Trait for handling HTTP requests
11#[allow(async_fn_in_trait)]
12pub trait HttpHandler {
13    /// Handle an incoming HTTP request and return a response
14    async fn handle_request(
15        &mut self,
16        request: &HttpRequest<'_>,
17    ) -> Result<HttpResponse<'_>, Error>;
18}
19
20/// A simple handler that serves basic endpoints for testing
21#[derive(Debug)]
22pub struct SimpleHandler;
23
24impl HttpHandler for SimpleHandler {
25    async fn handle_request(
26        &mut self,
27        request: &HttpRequest<'_>,
28    ) -> Result<HttpResponse<'_>, Error> {
29        let mut headers = Vec::new();
30        match request.path {
31            "/" => {
32                let _ = headers.push(HttpHeader::new("Content-Type", "text/html"));
33                Ok(HttpResponse {
34                    status_code: StatusCode::Ok,
35                    headers,
36                    body: ResponseBody::Text("<h1>Hello from nanofish HTTP server!</h1>"),
37                })
38            }
39            "/health" => {
40                let _ = headers.push(HttpHeader::new("Content-Type", "application/json"));
41                Ok(HttpResponse {
42                    status_code: StatusCode::Ok,
43                    headers,
44                    body: ResponseBody::Text("{\"status\":\"ok\"}"),
45                })
46            }
47            _ => {
48                let _ = headers.push(HttpHeader::new("Content-Type", "text/plain"));
49                Ok(HttpResponse {
50                    status_code: StatusCode::NotFound,
51                    headers,
52                    body: ResponseBody::Text("404 Not Found"),
53                })
54            }
55        }
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62    use crate::{HttpMethod, HttpRequest, StatusCode};
63    use heapless::Vec;
64
65    #[test]
66    fn test_simple_handler() {
67        // Test root path
68        let mut handler = SimpleHandler;
69        let request = HttpRequest {
70            method: HttpMethod::GET,
71            path: "/",
72            version: "HTTP/1.1",
73            headers: Vec::new(),
74            body: b"",
75        };
76
77        let response = futures_lite::future::block_on(handler.handle_request(&request)).unwrap();
78        assert_eq!(response.status_code, StatusCode::Ok);
79        assert_eq!(
80            response.body.as_str(),
81            Some("<h1>Hello from nanofish HTTP server!</h1>")
82        );
83
84        // Test health endpoint
85        let mut handler = SimpleHandler;
86        let request = HttpRequest {
87            method: HttpMethod::GET,
88            path: "/health",
89            version: "HTTP/1.1",
90            headers: Vec::new(),
91            body: b"",
92        };
93
94        let response = futures_lite::future::block_on(handler.handle_request(&request)).unwrap();
95        assert_eq!(response.status_code, StatusCode::Ok);
96        assert_eq!(response.body.as_str(), Some("{\"status\":\"ok\"}"));
97
98        // Test 404 path
99        let mut handler = SimpleHandler;
100        let request = HttpRequest {
101            method: HttpMethod::GET,
102            path: "/nonexistent",
103            version: "HTTP/1.1",
104            headers: Vec::new(),
105            body: b"",
106        };
107
108        let response = futures_lite::future::block_on(handler.handle_request(&request)).unwrap();
109        assert_eq!(response.status_code, StatusCode::NotFound);
110        assert_eq!(response.body.as_str(), Some("404 Not Found"));
111    }
112}