calculator/
calculator.rs

1use std::io;
2use std::net::TcpListener;
3use std::net::TcpStream;
4use std::thread;
5
6use rusty_http::Http;
7use rusty_http::Request;
8use rusty_http::Response;
9use rusty_http::StatusCode;
10
11fn add(request: Request, response: Response) -> io::Result<()> {
12    let Some(a) = request.params.get("a") else {
13        response.status_code(StatusCode::BadRequest)
14        .set_header("Content-Type", "text/html").flush()?
15        .add_to_body("<h1>400 Bad Request</h1>")
16        .add_to_body("<p>Parameter 'a' not found</p>").flush()?;
17        
18        return Ok(());
19    };
20
21    let Some(b) = request.params.get("b") else {
22        response.status_code(StatusCode::BadRequest)
23        .set_header("Content-Type", "text/html").flush()?
24        .add_to_body("<h1>400 Bad Request</h1>")
25        .add_to_body("<p>Parameter 'b' not found</p>").flush()?;
26        
27        return Ok(());
28    };
29
30    let Ok(a) = a.parse::<u8>() else {
31        response.status_code(StatusCode::BadRequest)
32        .set_header("Content-Type", "text/html").flush()?
33        .add_to_body("<h1>400 Bad Request</h1>")
34        .add_to_body("<p>Parameter 'a' can only be a number from 0 to 255</p>").flush()?;
35        
36        return Ok(());
37    };
38
39    let Ok(b) = b.parse::<u8>() else {
40        response.status_code(StatusCode::BadRequest)
41        .set_header("Content-Type", "text/html").flush()?
42        .add_to_body("<h1>400 Bad Request</h1>")
43        .add_to_body("<p>Parameter 'b' can only be a number from 0 to 255</p>").flush()?;
44        
45        return Ok(());
46    };
47
48    let content = format!("<h1>{} + {} = {}</h1>", a, b, a as u16 + b as u16);
49
50    response.status_code(StatusCode::Ok)
51    .set_header("Content-Type", "text/html").flush()?
52    .add_to_body(content).flush()?;
53
54    Ok(())
55}
56
57fn sub(request: Request, response: Response) -> io::Result<()> {
58    let Some(a) = request.params.get("a") else {
59        response.status_code(StatusCode::BadRequest)
60        .set_header("Content-Type", "text/html").flush()?
61        .add_to_body("<h1>400 Bad Request</h1>")
62        .add_to_body("<p>Parameter 'a' not found</p>").flush()?;
63        
64        return Ok(());
65    };
66
67    let Some(b) = request.params.get("b") else {
68        response.status_code(StatusCode::BadRequest)
69        .set_header("Content-Type", "text/html").flush()?
70        .add_to_body("<h1>400 Bad Request</h1>")
71        .add_to_body("<p>Parameter 'b' not found</p>").flush()?;
72        
73        return Ok(());
74    };
75
76    let Ok(a) = a.parse::<u8>() else {
77        response.status_code(StatusCode::BadRequest)
78        .set_header("Content-Type", "text/html").flush()?
79        .add_to_body("<h1>400 Bad Request</h1>")
80        .add_to_body("<p>Parameter 'a' can only be a number from 0 to 255</p>").flush()?;
81        
82        return Ok(());
83    };
84
85    let Ok(b) = b.parse::<u8>() else {
86        response.status_code(StatusCode::BadRequest)
87        .set_header("Content-Type", "text/html").flush()?
88        .add_to_body("<h1>400 Bad Request</h1>")
89        .add_to_body("<p>Parameter 'b' can only be a number from 0 to 255</p>").flush()?;
90        
91        return Ok(());
92    };
93
94    let content = format!("<h1>{} - {} = {}</h1>", a, b, a as i16 - b as i16);
95
96    response.status_code(StatusCode::Ok)
97    .set_header("Content-Type", "text/html").flush()?
98    .add_to_body(content).flush()?;
99
100    Ok(())
101}
102
103fn not_found(request: Request, response: Response) -> io::Result<()> {
104    let content = format!("<p>Page '{}' could not been found</p>", request.uri);
105
106    response.status_code(StatusCode::NotFound)
107    .set_header("Content-Type", "text/html").flush()?
108    .add_to_body("<h1>404 Not Found</h1>")
109    .add_to_body(content).flush()?;
110
111    Ok(())
112}
113
114fn init_stream(stream: TcpStream) -> io::Result<()> {
115    let (request, response) = Http::from(stream)?;
116
117    match request.uri.as_str() {
118        "/add" => add(request, response)?,
119        "/sub" => sub(request, response)?,
120        _      => not_found(request, response)?
121    }
122
123    Ok(())
124}
125
126fn main() -> io::Result<()> {
127    let listener = TcpListener::bind("127.0.0.1:8080")?;
128
129    for stream in listener.incoming().filter_map(Result::ok) {
130        thread::spawn(|| init_stream(stream));
131    }
132
133    Ok(())
134}