-1

i tried use tokio(tokio={version="1", features=["full"]}) to implement a simple http server. The code is below. The weired thing is the server can receive the request from browser, but the brower can't receive the response from the server. Is there any bug in my code?


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;
        });
    }
}

Keith
  • 807
  • 7
  • 13
  • It depends on your OS probably, but if your source code file does not use \r\n as line separators, the response string actually contains lines separated just by \n. This is not a valid HTTP response, so the browser may be ignoring it. – Vladimir Matveev Dec 02 '22 at 22:50
  • You also have to check how many bytes `write` actually wrote. You probably meant to use `write_all` in it's stead. – cafce25 Dec 02 '22 at 22:57
  • thanks for answering, inspired by the answers, i found that there need a extra line separator between status line and entity body. – Keith Dec 02 '22 at 23:28

1 Answers1

0

there need a extra line separator between status line and entity body. the browser can pase the response when the response_str 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>"
Keith
  • 807
  • 7
  • 13