|
|
|
@ -1,9 +1,9 @@ |
|
|
|
use std::net::{TcpListener, TcpStream}; |
|
|
|
use std::thread; |
|
|
|
use std::io::{BufReader, prelude::*}; |
|
|
|
use std::boxed::Box; |
|
|
|
use crate::routes::proxy; |
|
|
|
use crate::models::HttpRequest::HttpRequest; |
|
|
|
use std::io::{BufReader, BufRead, Write, prelude::*}; |
|
|
|
use crate::models::{http_header::HttpHeader, HttpRequest::HttpRequest, user::User}; |
|
|
|
use crate::parsers::{parse_headers, parse_json_body}; |
|
|
|
use crate::routes::proxy::proxy; |
|
|
|
|
|
|
|
pub fn http_server() { |
|
|
|
let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); |
|
|
|
@ -24,43 +24,47 @@ pub fn http_server() { |
|
|
|
} |
|
|
|
|
|
|
|
fn handle_connection(mut stream: TcpStream) { |
|
|
|
// Handle the connection (currently does nothing)
|
|
|
|
let reader = BufReader::new(&mut stream); |
|
|
|
let http_request = reader.lines().next().unwrap().unwrap(); |
|
|
|
let mut reader = BufReader::new(&mut stream); |
|
|
|
let mut header_lines: Vec<String> = Vec::new(); |
|
|
|
|
|
|
|
let parsed_request = parse_http_request(&http_request); |
|
|
|
match parsed_request { |
|
|
|
Ok(request) => { |
|
|
|
proxy::proxy(request, &stream); |
|
|
|
// Read the HTTP request line by line
|
|
|
|
loop { |
|
|
|
let mut line = String::new(); |
|
|
|
match reader.read_line(&mut line) { |
|
|
|
Ok(0) => break, // EOF
|
|
|
|
Ok(_) => { |
|
|
|
println!("Received line: {}", line.trim()); |
|
|
|
if line.trim().is_empty() { |
|
|
|
break; // End of headers
|
|
|
|
} |
|
|
|
header_lines.push(line); |
|
|
|
} |
|
|
|
Err(e) => { |
|
|
|
eprintln!("Error reading request: {}", e); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
Err(e) => { |
|
|
|
eprintln!("Failed to parse HTTP request: {}", e); |
|
|
|
} |
|
|
|
println!("Finished!"); |
|
|
|
let headers = parse_headers(header_lines); |
|
|
|
|
|
|
|
let mut body = String::new(); |
|
|
|
|
|
|
|
if let Some(length) = headers.content_length { |
|
|
|
let mut body_buffer = vec![0; length]; |
|
|
|
if let Err(e) = reader.read_exact(&mut body_buffer) { |
|
|
|
eprintln!("Error reading body: {}", e); |
|
|
|
} else { |
|
|
|
body = String::from_utf8_lossy(&body_buffer).to_string(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
let request = HttpRequest { |
|
|
|
headers, |
|
|
|
body: if body.is_empty() { None } else { Some(body) }, |
|
|
|
}; |
|
|
|
|
|
|
|
proxy(request, &stream); |
|
|
|
} |
|
|
|
|
|
|
|
// FUNCTION TO PARSE HTTP REQUESTS
|
|
|
|
fn parse_http_request(request: &str) -> Result<HttpRequest, Box<dyn std::error::Error>> { |
|
|
|
let parts: Vec<&str> = request.split_whitespace().collect(); |
|
|
|
|
|
|
|
if parts[1].ends_with('/') == false && parts[1].contains('.') == false { |
|
|
|
// ADD TRAILING / IF MISSING
|
|
|
|
println!("Adding trailing / to path"); |
|
|
|
let new_path = format!("{}/", parts[1]); |
|
|
|
let new_request = format!("{} {} {}", parts[0], new_path, parts[2]); |
|
|
|
return parse_http_request(&new_request); |
|
|
|
} |
|
|
|
|
|
|
|
if parts.len() >= 3 { |
|
|
|
let request = HttpRequest { |
|
|
|
method: parts[0].to_string(), |
|
|
|
path: parts[1].to_string(), |
|
|
|
version: parts[2].to_string(), |
|
|
|
}; |
|
|
|
Ok(request) |
|
|
|
} else { |
|
|
|
Err("Invalid HTTP request".into()) |
|
|
|
} |
|
|
|
} |