blob: 6320bd7e10b257bafa5ef24019994b490323bc26 [file] [log] [blame]
use std::{io::Result, collections::HashMap};
use tokio::{net::{TcpListener, TcpStream}, io::{AsyncReadExt, AsyncWriteExt}};
use itertools::Itertools;
use nom::AsChar;
async fn process_socket(mut stream: TcpStream) {
println!("accepted new connection");
let mut request: HashMap<String, String> = HashMap::new();
let mut line_num: usize = 0;
loop {
let mut line = String::default();
loop {
let mut buf: [u8; 1] = [0; 1];
stream.read_exact(&mut buf).await.unwrap();
let character = buf[0].as_char();
if character == '\n' {
break
} else if character != '\r' {
line.push(character);
}
}
if line_num == 0 {
let mut splits = line.split(' ');
request.insert("method".to_owned(), splits.next().unwrap().to_owned());
request.insert("path".to_owned(), splits.next().unwrap().to_owned());
} else {
let mut splits = line.split(":");
let key = splits.next().unwrap();
let value = splits.next().unwrap_or_default().trim();
request.insert(key.to_owned(), value.to_owned());
}
if request.get("path").unwrap() != "/user-agent" || request.contains_key("User-Agent") { break };
line_num += 1;
}
// println!("{:?}", request);
let mut path = request.get("path").unwrap().split("/");
let response_status: String;
let mut response_headers: Vec<String> = vec![];
let response_body: String;
// println!("{:?}", path);
path.next().unwrap();
match path.next().unwrap() {
"" => {
response_status = "200 OK".into();
response_body = "".into();
},
"echo" => {
response_status = "200 OK".into();
response_body = path.join("/");
response_headers.push("Content-Type: text/plain".into());
},
"user-agent" => {
response_status = "200 OK".into();
response_body = request.get("User-Agent").unwrap().into();
response_headers.push("Content-Type: text/plain".into());
},
_ => {
response_status = "404 Not Found".into();
response_body = "".into();
}
}
if response_body.len() > 0 {
response_headers.push(format!("Content-Length: {}", response_body.len()));
}
stream.write(format!("HTTP/1.1 {response_status}\r\n{}\r\n\r\n{response_body}", response_headers.join("\r\n")).as_bytes()).await.unwrap();
}
#[tokio::main]
async fn main() -> Result<()> {
let listener = TcpListener::bind("127.0.0.1:4221").await?;
let mut futures = vec![];
loop {
let (socket, _) = listener.accept().await?;
futures.push(tokio::spawn(process_socket(socket)));
}
}