Search code examples
httprustrust-tokio

Why does browser not receive the reponse from custom HTTP server?


I'm using Tokio to implement a simple HTTP server. The weird thing is the server can receive the request from browser, but the browser can't receive the response from the server.

# Cargo.toml
[dependencies]
tokio = { version = "1", features = ["full"] }
use tokio::{self, net};
use tokio::io::{AsyncReadExt, AsyncWrite, AsyncWriteExt};
use tokio::net::TcpStream;

async fn process(mut stream: TcpStream) {
    let mut buf = [0u8; 4096];
    loop {
        let n = stream.read(&mut buf).await.unwrap();
        if n == 0 {
            break;
        }
        let s = String::from_utf8_lossy(&buf[0..n]).to_string();
        print!("{}", s);
        if s.ends_with("\r\n\r\n") {
            println!("request received");
            break;
        }
    }

    let response_str = "HTTP/1.1 200 OK
<!DOCTYPE html>
<html lang=\"en\">
<head>
<meta charset=\"udf-8\">
<title>Hello!</title>
</head>
<body>
HELLO
</body>
</html>
        ";
    println!("response");
    // browser doesn't receive the response that this line of code send.
    stream.write(response_str.as_bytes()).await.unwrap();
    stream.flush().await.unwrap();
    println!("response DONE");
}

#[tokio::main]
async fn main() {
    let listener = net::TcpListener::bind("127.0.0.1:9998").await.unwrap();
    loop {
        let (stream, _) = listener.accept().await.unwrap();
        tokio::spawn(async move{
            process(stream).await;
        });
    }
}

Is there any bug in my code?


Solution

  • The HTTP response had a slightly wrong format. There needs to be a extra newline between the status/headers and body. The browser was able to parse the response when written like this:

    let response_str = "HTTP/1.1 200 OK
    
    <!DOCTYPE html>
    <html lang=\"en\">
    <head>
    <meta charset=\"udf-8\">
    <title>Hello!</title>
    </head>
    <body>
    HELLO
    </body>
    </html>"