How can I read body and content type in http request

Without using external crate, hoe can I read content type and body content in http request, assuming I'm listening to TcpListener as below:

use std::fs;
use std::io::prelude::*;
use std::net::TcpListener;
use std::net::TcpStream;

fn main() {
    let listener = TcpListener::bind("127.0.0.1:7879").unwrap();

    for stream in listener.incoming() {
        let stream = stream.unwrap();
        handle_connection(stream);
    }
}

// --snip--

fn handle_connection(mut stream: TcpStream) {
    let mut buffer = [0; 1024];
    stream.read(&mut buffer).unwrap();
    let get = b"GET / HTTP/1.1\r\n";
    let post = b"POST / HTTP/1.1\r\n";
    
    if buffer.starts_with(get) {
        let contents = fs::read_to_string("hello.html").unwrap();

        let response = format!(
            "HTTP/1.1 200 OK\r\nContent-Length: {}\r\n\r\n{}",
            contents.len(),
            contents
        );

        stream.write(response.as_bytes()).unwrap();
        stream.flush().unwrap();
    } else {
        // read content type
        // read body content
    }
}

I tried:

    let mut buffer = [0; 1024];
    stream.read(&mut buffer).unwrap();
    use std::str;
    let x = str::from_utf8(&buffer).unwrap();
    println!("{}", x);

And got output as below once I posted JSON:

POST / HTTP/1.1
Host: 127.0.0.1:7879
Connection: keep-alive
Content-Length: 15
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36 Edg/84.0.522.59
Content-Type: text/plain;charset=UTF-8
Accept: */*
Origin: chrome-extension://ihgpcfpkpmdcghlnaofdmjkoemnlijdi
Sec-Fetch-Site: none
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9

{name: "Hasan"}

And as below once I posted form data

POST / HTTP/1.1
Host: 127.0.0.1:7879
Connection: keep-alive
Content-Length: 140
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36 Edg/84.0.522.59
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryWmCR1qEdzQwjZZy4
Accept: */*
Origin: chrome-extension://ihgpcfpkpmdcghlnaofdmjkoemnlijdi
Sec-Fetch-Site: none
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9

------WebKitFormBoundaryWmCR1qEdzQwjZZy4
Content-Disposition: form-data; name="name"

Hasan
------WebKitFormBoundaryWmCR1qEdzQwjZZy4--

The content type is found on the line starting with Content-Type:. The body starts the first time two newlines are found in a row.

1 Like

If you're doing this for educational purpose, then see RFC 7230: Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing for syntax definition. Note that HTTP response bodies may use chunked encoding, so reading may involve some parsing and processing.

If you need to parse raw HTTP streams, see httparse — Rust web dev library // Lib.rs

If you just need to get the data, use Reqwest — WebAssembly in Rust // Lib.rs

5 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.