Skip to content

Commit eb623fc

Browse files
committed
pass 8th stage
1 parent 72429dc commit eb623fc

File tree

1 file changed

+60
-27
lines changed

1 file changed

+60
-27
lines changed

src/main.rs

+60-27
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::thread;
55

66
use itertools::Itertools;
77
use nom::branch::alt;
8+
use nom::bytes::complete::take_until1;
89
use nom::bytes::streaming::{tag_no_case as tag, take_until};
910
use nom::IResult;
1011
use thiserror::Error;
@@ -73,41 +74,70 @@ fn not_found(stream: &mut TcpStream) -> Result<(), std::io::Error> {
7374
Ok(())
7475
}
7576

77+
fn ok(stream: &mut TcpStream) -> Result<(), std::io::Error> {
78+
stream.write("HTTP/1.1 200 OK\r\n\r\n".as_bytes())?;
79+
Ok(())
80+
}
81+
82+
fn created(stream: &mut TcpStream) -> Result<(), std::io::Error> {
83+
stream.write("HTTP/1.1 201 Created\r\n\r\n".as_bytes())?;
84+
Ok(())
85+
}
86+
7687
fn handle_connection(mut stream: TcpStream, path: Option<PathBuf>) -> Result<(), ConnectionError> {
77-
let mut buffer = [0; 1024];
78-
let len = stream.read(&mut buffer)?; // read 1K bytes for now
88+
let mut buffer = [0; 10000];
89+
let len = stream.read(&mut buffer)?;
7990

80-
let utf8 = String::from_utf8_lossy(&buffer[..=len]);
91+
let utf8 = String::from_utf8_lossy(&buffer[..len]);
8192
let req = parse_request(&utf8)
8293
.map_err(|e| ConnectionError::ParsingError(e.to_string()))?
8394
.1;
8495

8596
println!("Request: {req:?}");
8697

87-
if req.path == "/" {
88-
stream.write("HTTP/1.1 200 OK\r\n\r\n".as_bytes()).unwrap();
89-
} else if req.path.starts_with("/echo/") {
90-
let txt = &req.path[6..];
91-
send_text_content(&mut stream, txt)?;
92-
} else if req.path.starts_with("/files/") {
93-
let path = path.unwrap_or_else(|| PathBuf::from("."));
94-
let file_path = path.join(&req.path[7..]);
95-
96-
match std::fs::read_to_string(file_path) {
97-
Ok(file) => send_content(&mut stream, "application/octet-stream", &file)?,
98-
Err(_) => not_found(&mut stream)?,
98+
match req {
99+
Request { path: "/", .. } => {
100+
ok(&mut stream)?;
101+
}
102+
_ if req.path.starts_with("/echo/") => {
103+
let txt = &req.path[6..];
104+
send_text_content(&mut stream, txt)?;
105+
}
106+
req @ Request { method: "GET", .. } if req.path.starts_with("/files/") => {
107+
let path = path.unwrap_or_else(|| PathBuf::from("."));
108+
let file_path = path.join(&req.path[7..]);
109+
110+
match std::fs::read_to_string(file_path) {
111+
Ok(file) => send_content(&mut stream, "application/octet-stream", &file)?,
112+
Err(_) => not_found(&mut stream)?,
113+
};
114+
}
115+
req @ Request { method: "POST", .. } if req.path.starts_with("/files/") => {
116+
let path = path.unwrap_or_else(|| PathBuf::from("."));
117+
let file_path = path.join(&req.path[7..]);
118+
119+
if let Ok(()) = std::fs::write(file_path, req.body) {
120+
created(&mut stream)?;
121+
} else {
122+
not_found(&mut stream)?; // todo: fix
123+
}
124+
}
125+
req @ Request {
126+
path: "/user-agent",
127+
..
128+
} => {
129+
let ua = req
130+
.headers
131+
.iter()
132+
.find(|(k, _)| *k == "User-Agent")
133+
.map(|(_, v)| v)
134+
.unwrap_or(&"Unknown");
135+
136+
send_text_content(&mut stream, ua)?;
137+
}
138+
_ => {
139+
not_found(&mut stream)?;
99140
}
100-
} else if req.path == "/user-agent" {
101-
let ua = req
102-
.headers
103-
.iter()
104-
.find(|(k, _)| *k == "User-Agent")
105-
.map(|(_, v)| v)
106-
.unwrap_or(&"Unknown");
107-
108-
send_text_content(&mut stream, ua)?;
109-
} else {
110-
not_found(&mut stream)?;
111141
}
112142

113143
stream.flush()?;
@@ -124,6 +154,7 @@ pub struct Request<'a> {
124154
path: &'a str,
125155
version: &'a str,
126156
headers: Vec<(&'a str, &'a str)>,
157+
body: &'a str,
127158
}
128159

129160
fn parse_headers(input: &str) -> IResult<&str, Vec<(&str, &str)>> {
@@ -132,7 +163,7 @@ fn parse_headers(input: &str) -> IResult<&str, Vec<(&str, &str)>> {
132163
let mut rest = input;
133164

134165
loop {
135-
let Ok((rst, name)): IResult<&str, &str> = take_until(":")(rest) else {
166+
let Ok((rst, name)): IResult<&str, &str> = take_until1(":")(rest) else {
136167
break;
137168
};
138169
let (rst, _) = tag(": ")(rst)?;
@@ -156,6 +187,7 @@ fn parse_request(input: &str) -> IResult<&str, Request> {
156187
let (rest, _) = tag("\r\n")(rest)?;
157188

158189
let (rest, headers) = parse_headers(rest)?;
190+
let (rest, _) = tag("\r\n")(rest)?;
159191

160192
return Ok((
161193
rest,
@@ -164,6 +196,7 @@ fn parse_request(input: &str) -> IResult<&str, Request> {
164196
path,
165197
version,
166198
headers,
199+
body: rest,
167200
},
168201
));
169202
}

0 commit comments

Comments
 (0)