-use tokio::join;
+use std::str;
-async fn guten_tag() {
- println!("Guten Tag!");
-}
+use tokio::io::{ AsyncReadExt, AsyncWriteExt };
+use tokio::net::{TcpListener, TcpStream};
#[tokio::main]
async fn main() {
- let task1 = tokio::spawn(async {
- println!("Hello, world!");
- });
- let task2 = tokio::spawn(guten_tag());
+ let listener = TcpListener::bind("127.0.0.1:8181").await.unwrap();
+
+ loop {
+ let (stream, _) = listener.accept().await.unwrap();
+ tokio::spawn(async move { handle_connection(stream).await });
+ }
+}
+
+async fn handle_connection(mut stream: TcpStream) {
+ // Read the first 16 characters from the incoming stream
+ let mut buffer = [0; 16];
+ assert!(stream.read(&mut buffer).await.unwrap() >= 16);
+ // First 4 characters are used to detect HTTP method
+ let method_type = match str::from_utf8(&buffer[0..4]) {
+ Ok(v) => v,
+ Err(e) => panic!("Invalid UTF-8 sequence: {}", e),
+ };
+
+ let contents = match method_type {
+ "GET " => {
+ // todo: return real balance
+ format!("{{\"balance\": {}}}", 0.0)
+ }
+ "POST" => {
+ // Take characters after 'POST /' until whitespace is detected.
+ let input: String = buffer[6..16]
+ .iter()
+ .take_while(|x| **x != 32u8)
+ .map(|x| *x as char)
+ .collect();
+ let balance_update = input.parse::<f32>().unwrap();
+ // todo: add balance update handling
+ format!("{{\"balance\": {}}}", balance_update)
+ }
+ _ => {
+ panic!("Invalid HTTP method!")
+ }
+ };
- let (r1, r2) = join!(task1, task2);
- r1.unwrap();
- r2.unwrap()
+ let response = format!(
+ "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: {}\r\n\r\n{}",
+ contents.len(),
+ contents
+ );
+ assert!(stream.write(response.as_bytes()).await.unwrap() > 0);
+ stream.flush().await.unwrap();
}