You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
126 lines
3.8 KiB
Rust
126 lines
3.8 KiB
Rust
use std::io::{Read, Write};
|
|
use std::net::TcpListener;
|
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
|
use std::str;
|
|
use std::str::FromStr;
|
|
use std::string::ParseError;
|
|
|
|
#[derive(Debug)]
|
|
struct RequestLine {
|
|
method: Option<String>,
|
|
path: Option<String>,
|
|
protocol: Option<String>,
|
|
}
|
|
|
|
impl RequestLine {
|
|
fn method(&self) -> String {
|
|
if let Some(method) = &self.method {
|
|
method.to_string()
|
|
} else {
|
|
String::from("")
|
|
}
|
|
}
|
|
fn path(&self) -> String {
|
|
if let Some(path) = &self.path {
|
|
path.to_string()
|
|
} else {
|
|
String::from("")
|
|
}
|
|
}
|
|
fn get_order_number(&self) -> String {
|
|
let path = self.path();
|
|
let path_tokens: Vec<String> = path.split("/").map(|s| s.parse().unwrap()).collect();
|
|
path_tokens[path_tokens.len() - 1].clone()
|
|
}
|
|
}
|
|
|
|
impl FromStr for RequestLine {
|
|
type Err = ParseError;
|
|
fn from_str(msg: &str) -> Result<Self, Self::Err> {
|
|
let mut msg_tokens = msg.split_ascii_whitespace();
|
|
|
|
let method = match msg_tokens.next() {
|
|
Some(token) => Some(String::from(token)),
|
|
None => None,
|
|
};
|
|
let path = match msg_tokens.next() {
|
|
Some(token) => Some(String::from(token)),
|
|
None => None,
|
|
};
|
|
let protocol = match msg_tokens.next() {
|
|
Some(token) => Some(String::from(token)),
|
|
None => None,
|
|
};
|
|
|
|
Ok(Self {
|
|
method: method,
|
|
path: path,
|
|
protocol: protocol,
|
|
})
|
|
}
|
|
}
|
|
fn main() {
|
|
// Start the origin server
|
|
let port = 3000;
|
|
let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), port);
|
|
let connection_listener = TcpListener::bind(socket_addr).unwrap();
|
|
|
|
println!("Running on port: {}", port);
|
|
|
|
for stream in connection_listener.incoming() {
|
|
// Read the first line of incoming HTTP request
|
|
// and convert it into RequestLine struct
|
|
let mut stream = stream.unwrap();
|
|
let mut buffer = [0; 200];
|
|
stream.read(&mut buffer).unwrap();
|
|
let req_line = "";
|
|
let string_request_line =
|
|
if let Some(line) = str::from_utf8(&buffer).unwrap().lines().next() {
|
|
line
|
|
} else {
|
|
println!("Invalid request line received");
|
|
req_line
|
|
};
|
|
|
|
let req_line = RequestLine::from_str(string_request_line).unwrap();
|
|
|
|
// Construct the HTTP response string and write it to the TCP stream
|
|
let html_response_string;
|
|
let order_status;
|
|
println!("len is {}", req_line.get_order_number().len());
|
|
|
|
if req_line.method() != "GET"
|
|
|| !req_line.path().starts_with("/order/status")
|
|
|| req_line.get_order_number().len() == 0
|
|
{
|
|
if req_line.get_order_number().len() == 0 {
|
|
order_status = format!("Please provide valid order number");
|
|
} else {
|
|
order_status = format!("Sorry,this page is not found");
|
|
}
|
|
|
|
html_response_string = format!(
|
|
"HTTP/1.1 404 Not Found\nContent-Type: text/html\nContent-Length:{}\n\n{}",
|
|
order_status.len(),
|
|
order_status
|
|
);
|
|
} else {
|
|
order_status = format!(
|
|
"Order status for order number {} is: Shipped\n",
|
|
req_line.get_order_number()
|
|
);
|
|
html_response_string = format!(
|
|
"HTTP/1.1 200 OK\nContent-Type: text/html\nContent-Length:{}\n\n{}",
|
|
order_status.len(),
|
|
order_status
|
|
);
|
|
}
|
|
|
|
println!(
|
|
"\nGoing to respond to client with:\n\n{}",
|
|
html_response_string
|
|
);
|
|
stream.write(html_response_string.as_bytes()).unwrap();
|
|
}
|
|
}
|