Created
May 15, 2022 15:00
-
-
Save saward/5f65782c799e739c648551b00dc64c86 to your computer and use it in GitHub Desktop.
Async Rust based on Tower blog example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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