Skip to content

Instantly share code, notes, and snippets.

@saward
Created May 15, 2022 15:00
Show Gist options
  • Save saward/5f65782c799e739c648551b00dc64c86 to your computer and use it in GitHub Desktop.
Save saward/5f65782c799e739c648551b00dc64c86 to your computer and use it in GitHub Desktop.
Async Rust based on Tower blog example
use async_std::io::prelude::*;
use async_std::io::Error;
use async_std::net::{TcpListener, TcpStream};
use async_std::prelude::Future;
use async_std::task;
use std::time::Duration;
struct Server {
addr: String,
}
impl Server {
fn new(addr: String) -> Self {
Self { addr }
}
async fn run<F, Fut>(self, handler: F) -> Result<(), Error>
where
// `handler` now returns a generic type `Fut`...
F: Fn(String) -> Fut,
// ...which is a `Future` whose `Output` is an `HttpResponse`
Fut: Future<Output = String>,
{
let listener = TcpListener::bind(self.addr).await?;
loop {
let (mut connection, _) = listener.accept().await?;
let request = read_http_request(&mut connection).await?;
task::sleep(Duration::from_secs(10)).await;
// Await the future returned by `handler`
let response = handler(request).await;
write_http_response(connection, response).await?;
}
}
}
async fn read_http_request(stream: &mut TcpStream) -> Result<String, Error> {
let mut buffer = [0; 1024];
stream.read(&mut buffer).await?;
let request = format!("Request: {}", String::from_utf8_lossy(&buffer[..]));
Ok(request)
}
async fn basic_handler(request: String) -> String {
let contents = format!(
r#"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Hello!</title>
</head>
<body>
<h1>Hello!</h1>
<p>Hi from Rust</p>
<pre>{}</pre>
</body>
</html>
"#,
request
);
format!(
"HTTP/1.1 200 OK\r\nContent-Length: {}\r\n\r\n{}",
contents.len(),
contents,
)
}
async fn write_http_response(mut stream: TcpStream, response: String) -> Result<(), Error> {
stream.write(response.as_bytes()).await?;
stream.flush().await?;
Ok(())
}
fn main() -> std::io::Result<()> {
let server = Server::new("127.0.0.1:8989".to_string());
task::block_on(server.run(basic_handler))?;
Ok(())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment