add a request handler
This commit is contained in:
parent
f7a7cddde5
commit
81d9b0f38d
3
src/handlers/mod.rs
Normal file
3
src/handlers/mod.rs
Normal file
@ -0,0 +1,3 @@
|
||||
pub mod request;
|
||||
|
||||
pub use request::handle_request;
|
||||
108
src/handlers/request.rs
Normal file
108
src/handlers/request.rs
Normal file
@ -0,0 +1,108 @@
|
||||
//! request handles properly the incoming request
|
||||
//! it will parse the request according to the HTTP message specifications
|
||||
//! see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum HTTPVersion {
|
||||
HTTP1,
|
||||
HTTP2,
|
||||
}
|
||||
|
||||
impl Into<String> for HTTPVersion {
|
||||
fn into(self) -> String {
|
||||
match self {
|
||||
HTTP1 => "HTTP/1.1".to_string(),
|
||||
HTTP2 => "HTTP/2.2".to_string(),
|
||||
_ => "UNKNOWN".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Request defined the HTTP request
|
||||
// TODO: method, target, version must be set in new struct : `HTTPStartLine`
|
||||
#[derive(Debug)]
|
||||
pub struct HTTPRequest {
|
||||
pub method: String,
|
||||
pub target: String,
|
||||
pub version: HTTPVersion,
|
||||
}
|
||||
|
||||
impl HTTPRequest {
|
||||
// associated function to build a new HTTPRequest
|
||||
fn new(method: String, target: String, version: HTTPVersion) -> Self {
|
||||
HTTPRequest {
|
||||
method,
|
||||
target,
|
||||
version,
|
||||
}
|
||||
}
|
||||
|
||||
fn parse(request: &str) -> Result<Self, &str> {
|
||||
// declare a new `request` var to borrow to &str `request`
|
||||
let request = request.to_string();
|
||||
|
||||
let request_parts: Vec<&str> = request.split(" ").collect();
|
||||
if request_parts.len() < 3 {
|
||||
return Err("unable to parse the request correctly");
|
||||
}
|
||||
|
||||
Ok(HTTPRequest::new(
|
||||
request_parts[0].to_string(),
|
||||
request_parts[1].to_string(),
|
||||
HTTPVersion::HTTP1,
|
||||
))
|
||||
}
|
||||
|
||||
fn is_valid(self) -> bool {
|
||||
return self.method != "" && self.target != "";
|
||||
}
|
||||
|
||||
// TODO: to be tested
|
||||
pub fn start_line(self) -> String {
|
||||
let version: String = self.version.into();
|
||||
return format!("{} {} {}", self.method, self.target, version);
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for HTTPRequest {
|
||||
fn default() -> Self {
|
||||
HTTPRequest {
|
||||
method: "".to_string(),
|
||||
target: "".to_string(),
|
||||
version: HTTPVersion::HTTP1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for HTTPRequest {
|
||||
fn from(request: &str) -> Self {
|
||||
match Self::parse(request) {
|
||||
Ok(v) => v,
|
||||
Err(v) => {
|
||||
eprintln!("{}", format!("[ERR]: {v}"));
|
||||
return HTTPRequest::default();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_request(request: &str) -> HTTPRequest {
|
||||
return HTTPRequest::from(request);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_handle_request() {
|
||||
let test_cases: [(&str, bool); 5] = [
|
||||
("GET / HTTP/1.1", true),
|
||||
("POST HTTP/1.1", false),
|
||||
("", false),
|
||||
("fjlqskjd /oks?id=65 HTTP/2", true),
|
||||
(" ", false),
|
||||
];
|
||||
|
||||
for (request, is_valid) in test_cases {
|
||||
let http_request = HTTPRequest::from(request);
|
||||
println!("{:?}", http_request);
|
||||
assert_eq!(http_request.is_valid(), is_valid);
|
||||
}
|
||||
}
|
||||
13
src/main.rs
13
src/main.rs
@ -1,3 +1,5 @@
|
||||
mod handlers;
|
||||
|
||||
use std::fs;
|
||||
use std::io::prelude::*;
|
||||
use std::net::TcpListener;
|
||||
@ -6,6 +8,8 @@ use std::net::TcpStream;
|
||||
use async_std::task;
|
||||
use std::time::Duration;
|
||||
|
||||
use handlers::handle_request;
|
||||
|
||||
// TODO: must be set in a conf file
|
||||
const SERVER_URL: &str = "127.0.0.1:9000";
|
||||
|
||||
@ -20,15 +24,18 @@ async fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: must properly handle the request
|
||||
async fn handle_connection(mut stream: TcpStream) {
|
||||
let mut buffer = [0; 1024];
|
||||
stream.read(&mut buffer).unwrap();
|
||||
|
||||
let get = b"GET / HTTP/1.1\r\n";
|
||||
|
||||
// TODO: request musy be parsed correctly
|
||||
let status_line = if buffer.starts_with(get) {
|
||||
// transform buffer bytes array into `String`
|
||||
let buffer_string = String::from_utf8_lossy(&buffer);
|
||||
let request = handle_request(&buffer_string);
|
||||
|
||||
// TODO: `Response` struct must be implemented
|
||||
let status_line = if request.target == "/".to_string() {
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
} else {
|
||||
"HTTP/1.1 404 NOT FOUND\r\n"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user