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 https://tools.ietf.org/html/rfc7230#section-3.2 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 https://lib.rs/httparse

If you just need to get the data, use https://lib.rs/reqwest

4 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.