//! HTML Form Example //! ================= //! //! Start the server: //! ``` //! cargo run --package servlin --features urlencoded --example html_form //! Finished dev [unoptimized + debuginfo] target(s) in 0.25s //! Running `target/debug/examples/html_form` //! Access the server at http://127.0.0.1:8000/ //! 2023-04-20T17:18:57Z info "code":200,"body_len":370,"http_method":"GET","path":"/","request_id":3504837461057921534 //! 2023-04-20T17:18:57Z info "code":404,"body_len":9,"http_method":"GET","path":"/favicon.ico","request_id":14979834421061568265 //! 2023-04-20T17:19:08Z info "code":303,"body_len":0,"http_method":"POST","path":"/increment","request_id":10633635939599229141 //! 2023-04-20T17:19:08Z info "code":200,"body_len":370,"http_method":"GET","path":"/","request_id":2615853109542701666 //! 2023-04-20T17:19:08Z info "code":404,"body_len":9,"http_method":"GET","path":"/favicon.ico","request_id":6599307416411604969 //! 2023-04-20T17:19:15Z info "code":303,"body_len":0,"http_method":"POST","path":"/increment","request_id":1471059950980094153 //! 2023-04-20T17:19:15Z info "code":200,"body_len":370,"http_method":"GET","path":"/","request_id":13807176225544983707 //! 2023-04-20T17:19:15Z info "code":404,"body_len":9,"http_method":"GET","path":"/favicon.ico","request_id":6733001312936409561 //! 2023-04-20T17:19:24Z info "code":303,"body_len":0,"http_method":"POST","path":"/add","request_id":2450901135286845771 //! 2023-04-20T17:19:24Z info "code":200,"body_len":370,"http_method":"GET","path":"/","request_id":18076069727349126411 //! ^C //! ``` //! //! Access the form with your web browser: //! #![forbid(unsafe_code)] use safina::executor::Executor; use serde::Deserialize; use servlin::log::log_request_and_response; use servlin::{socket_addr_127_0_0_1, Error, HttpServerBuilder, Request, Response}; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; struct State { count: AtomicUsize, } impl State { pub fn new() -> Self { Self { count: AtomicUsize::new(0), } } pub fn get(&self) -> usize { self.count.load(Ordering::Acquire) } pub fn increment(&self) { self.count.fetch_add(1, Ordering::AcqRel); } pub fn add(&self, n: usize) { self.count.fetch_add(n, Ordering::AcqRel); } } #[allow(clippy::needless_pass_by_value)] fn index(state: Arc) -> Response { Response::html( 200, format!( " Example

Example

Count: {}


", state.get() ), ) } #[allow(clippy::needless_pass_by_value)] fn increment(state: Arc) -> Response { state.increment(); Response::redirect_303("/") } #[allow(clippy::needless_pass_by_value)] fn add(state: Arc, req: Request) -> Result { #[derive(Deserialize)] struct Input { num: usize, } let input: Input = req.urlencoded()?; let num = if input.num > 5 { return Err(Error::client_error(Response::text(400, "num is too big"))); } else { input.num }; state.add(num); Ok(Response::redirect_303("/")) } fn handle_req(state: Arc, req: Request) -> Result { match (req.method(), req.url().path()) { ("GET", "/health") => Ok(Response::text(200, "ok")), ("GET", "/") => Ok(index(state)), ("POST", "/increment") => Ok(increment(state)), ("POST", "/add") => add(state, req), _ => Ok(Response::text(404, "Not found")), } } pub fn main() { println!("Access the server at http://127.0.0.1:8000/"); safina::timer::start_timer_thread(); let executor: Arc = Arc::default(); let state = Arc::new(State::new()); let request_handler = move |req: Request| log_request_and_response(req, |req| handle_req(state, req)).unwrap(); executor .block_on( HttpServerBuilder::new() .listen_addr(socket_addr_127_0_0_1(8000)) .max_conns(100) .spawn_and_join(request_handler), ) .unwrap(); }