create a http server and read the request body in rust

To create an HTTP server in Rust, we need to use the hyper crate. Here's an example code for a simple HTTP server that runs on localhost:8080 and reads the request body:

main.rs
use hyper::{Body, Method, Request, Response, Server};
use hyper::header::{HeaderValue, CONTENT_TYPE};
use hyper::rt::Future;
use hyper::service::service_fn_ok;

fn main() {
    // Build the server and set up a closure to handle each incoming request
    let addr = ([127, 0, 0, 1], 8080).into();
    let new_service = || {
        service_fn_ok(handle_request)
    };
    let server = Server::bind(&addr)
        .serve(new_service)
        .map_err(|e| eprintln!("server error: {}", e));
    println!("Listening on http://{}", addr);

    // Run the server
    hyper::rt::run(server);
}

fn handle_request(req: Request<Body>) -> Response<Body> {
    if req.method() == &Method::POST {
        let content_type = req.headers()
            .get(CONTENT_TYPE)
            .and_then(|value| value.to_str().ok())
            .unwrap_or("text/plain");
        let body = req.into_body()
            .concat2()
            .map(|chunk| {
                let body = String::from_utf8_lossy(&chunk).into_owned();
                println!("Request body: {}", body);
                format!("Hello, World! You sent a {} request with body: {}\n", content_type, body)
            })
            .map_err(|err| {
                eprintln!("Error reading body: {}", err);
                "Error reading request body".into()
            });
        Response::builder()
            .status(200)
            .header(CONTENT_TYPE, HeaderValue::from_static("text/plain"))
            .body(Body::wrap_stream(body))
            .expect("Response builder error")
    } else {
        Response::builder()
            .status(404)
            .header(CONTENT_TYPE, HeaderValue::from_static("text/plain"))
            .body(Body::from("404 Not Found"))
            .expect("Response builder error")
    }
}
1783 chars
51 lines

In the handle_request function, we first check if the request method is POST. If it is, we get the content_type from the request headers (defaulting to "text/plain" if not found), and then read the request body using req.into_body().concat2(). The concat2 function returns a Future that resolves to a Chunk, which we can convert to a String using String::from_utf8_lossy. Finally, we return a Response with a status of 200, a body containing a greeting that includes the content_type and the request body, and a content type of "text/plain".

If the request method is not POST, we return a 404 Not Found response.

To test the server, you can use a tool like curl:

main.rs
$ curl -d 'test' http://localhost:8080/
Hello, World! You sent a text/plain request with body: test
100 chars
3 lines

related categories

gistlibby LogSnag