Search code examples
rustrust-tokio

How to know when the server has received the whole request?


I am implementing the HTTP/1.1 protocol from scratch for academic purpose. I have implemented the RequestBuilder which builds the request object successively from the buffer passed. This is the code to handle the opened socket.

async fn process_socket(stream: TcpStream) -> Result<Request> {
    let mut request_builder = RequestBuilder::new();
    let mut buffer: [u8; 1024] = unsafe { MaybeUninit::uninit().assume_init() };

    loop {
        stream.readable().await?;
        match stream.try_read(&mut buffer) {
            Ok(0) => {
                break;
            }
            Ok(n) => (),
            Err(ref e) if e.kind() == ErrorKind::WouldBlock => {
                continue;
            }
            Err(e) => {
                return Err(e.into());
            }
        }
        request_builder.parse(&buffer);
    }

    let request = request_builder.build()?;
    Ok(request)
}

request_builder.parse(&buffer); will take the next part of the buffer and parses the request further. My question is, how to break the loop when the client has sent the whole request. When I make a request to the server using curl localhost:8080, the whole request is parsed.

Expected behaviour

The loop would have been broken after reading the whole request stream.

Actual behaviour

The loop is stuck at stream.readable().await?; after reading the whole request into buffer. Currently, when I kill curl command using Ctrl+C, the loop is broken using Ok(0), but I want it to break after reading the who


Solution

  • You need to interpret the HTTP request, as the TCP connection will not get half-closed by a client. A FIN by the client which would violate the protocol) is the only way readable() returns (with an Err) unless the client sends more data (which breaks the HTTP specification).