Add POST /files/{file_name}
Change-Id: I5a55f2ce4d78039267a642a7fbaf3c94752649fa
Reviewed-on: https://git.clicks.codes/c/Clicks/BYO/HttpServer/rust/+/267
Reviewed-by: Samuel Shuert <coded@clicks.codes>
Tested-by: Skyler Grey <minion@clicks.codes>
diff --git a/src/main.rs b/src/main.rs
index 9e7d884..df41f2d 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -12,38 +12,66 @@
String(String)
}
+#[derive(PartialEq)]
+enum RequestSection {
+ RequestLine,
+ Headers,
+ Body
+}
+
async fn process_socket(mut stream: TcpStream) -> Result<(), &'static str> {
println!("accepted new connection");
let mut request: HashMap<String, String> = HashMap::new();
- let mut line_num: usize = 0;
+ let mut section: RequestSection = RequestSection::RequestLine;
loop {
let mut line = String::default();
- loop {
- let mut buf: [u8; 1] = [0; 1];
+ if section == RequestSection::Body {
+ let content_size: usize = request.get("Content-Length").unwrap().parse::<usize>().unwrap();
+ let mut buf: Vec<u8> = vec![0; content_size];
stream.read_exact(&mut buf).await.unwrap();
+ } else {
+ 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);
+ 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());
+ match section {
+ RequestSection::RequestLine => {
+ 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());
+
+ section = RequestSection::Headers;
+ }
+ RequestSection::Headers => {
+ if line == "" {
+ section = RequestSection::Body;
+ } 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());
+ }
+ },
+ RequestSection::Body => {
+ request.insert("body".to_owned(), line);
+ break;
+ },
}
- if request.get("path").unwrap() != "/user-agent" || request.contains_key("User-Agent") { break };
- line_num += 1;
+ if request.get("path").unwrap() == "/user-agent" && !request.contains_key("User-Agent") { continue; };
+ if request.get("path").unwrap().starts_with("/files/") && request.get("method").unwrap() == "POST" && !request.contains_key("body") { continue; };
+ break;
}
let mut path = request.get("path").unwrap().split("/");
@@ -70,26 +98,44 @@
response_headers.push("Content-Type: text/plain".into());
},
"files" => {
- let file_name = path.join("/");
let args: Vec<String> = args().collect();
let dir_arg = args.iter().find_position(|item| **item == "--directory");
+ let file_name = path.join("/");
let file_path = if dir_arg.is_some() {
args[dir_arg.unwrap().0+1].to_owned() + "/" + file_name.as_str()
} else {
return Err("No directory Given".into())
};
- let maybe_file = File::open(file_path).await;
-
- match maybe_file {
- Ok(file) => {
- response_status = "200 OK".into();
- response_body = BodyTypes::File(file);
- response_headers.push("Content-Type: application/octet-stream".into());
+ match request.get("method").unwrap().as_str() {
+ "GET" => {
+ let maybe_file = File::open(file_path).await;
+ match maybe_file {
+ Ok(file) => {
+ response_status = "200 OK".into();
+ response_body = BodyTypes::File(file);
+ response_headers.push("Content-Type: application/octet-stream".into());
+ },
+ Err(_) => {
+ response_status = "404 Not Found".into();
+ response_body = BodyTypes::String("".into());
+ }
+ }
},
- Err(_) => {
- response_status = "404 Not Found".into();
- response_body = BodyTypes::String("".into());
- }
+ "POST" => {
+ let file = File::create(file_path).await;
+ match file {
+ Ok(mut f) => {
+ f.write(request.get("body").unwrap().as_bytes()).await.unwrap();
+ response_status = "201 Created".into();
+ response_body = BodyTypes::String("".into());
+ },
+ Err(_) => {
+ response_body = BodyTypes::String("500 INTERNAL SERVER ERROR".into());
+ response_status = "".into()
+ }
+ }
+ },
+ _ => unreachable!() // not actually unreachable, but please don't kill our server thank you with pretty puppies on top <3
}
},
_ => {