#![forbid(unsafe_code)]
use servlin::reexport::{safina_executor, safina_timer};
use servlin::{print_log_response, socket_addr_127_0_0_1, HttpServerBuilder, Request, Response};
use std::io::Read;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use temp_dir::TempDir;
pub struct State {
upload_count: AtomicUsize,
}
impl State {
#[allow(clippy::new_without_default)]
#[must_use]
pub fn new() -> Self {
State {
upload_count: AtomicUsize::new(0),
}
}
}
fn put(state: &Arc<State>, req: &Request) -> Result<Response, Response> {
if req.body.is_pending() {
return Ok(Response::get_body_and_reprocess(1024 * 1024));
}
let body_len = req.body.reader()?.bytes().count();
state.upload_count.fetch_add(1, Ordering::AcqRel);
Ok(Response::text(
200,
format!(
"Upload received, body_len={}, upload_count={}\n",
body_len,
state.upload_count.load(Ordering::Acquire)
),
))
}
fn handle_req(state: &Arc<State>, req: &Request) -> Result<Response, Response> {
match (req.method(), req.url().path()) {
("GET", "/health") => Ok(Response::text(200, "ok")),
("PUT", "/upload") => put(state, req),
(_, "/upload") => Ok(Response::method_not_allowed_405(&["PUT"])),
_ => Ok(Response::text(404, "Not found")),
}
}
pub fn main() {
println!("Access the server at http://127.0.0.1:8000/upload");
safina_timer::start_timer_thread();
let executor = safina_executor::Executor::default();
let cache_dir = TempDir::new().unwrap();
let state = Arc::new(State::new());
let request_handler = move |req: Request| print_log_response(&req, handle_req(&state, &req));
executor
.block_on(
HttpServerBuilder::new()
.listen_addr(socket_addr_127_0_0_1(8000))
.max_conns(100)
.small_body_len(64 * 1024)
.receive_large_bodies(cache_dir.path())
.spawn_and_join(request_handler),
)
.unwrap();
}