http_mini_lib/utils/
http_server.rs1use crate::traits::stream_trait::StreamTrait;
2use crate::utils::fs::get_dir_contents_as_html;
3use crate::utils::mimes::get_mime_type;
4use crate::utils::{fs, http_response};
5use std::ffi::OsStr;
6use std::io::Error;
7use std::net::{IpAddr, SocketAddr, TcpListener, TcpStream};
8use std::path::Path;
9
10pub fn run(address: &str, mut port: i32) -> Result<TcpListener, Error> {
12 if !(1..=65535).contains(&port) {
13 println!("Invalid port number {}. Using port 8080", port);
14 port = 8080;
15 }
16
17 let ip: IpAddr = address.parse().unwrap();
18 let addr = SocketAddr::new(ip, port as u16);
19 let result_tcp_listener = TcpListener::bind(addr);
20
21 if result_tcp_listener.is_err() {
22 return Err(result_tcp_listener.err().unwrap());
23 }
24
25 let listener = result_tcp_listener?;
26
27 Ok(listener)
28}
29
30pub fn handle_connection(
32 stream: TcpStream,
33 source_dir: &Path,
34 executable_name: &OsStr,
35 address: &str,
36) {
37 let http_request = stream.parse();
38 if http_request.is_err() {
39 http_response::send(
40 &stream,
41 "HTTP/1.1 400 Bad Request",
42 None,
43 Option::from(Vec::from(http_request.err().unwrap().to_string())),
44 );
45 return;
46 }
47
48 let request = http_request.unwrap();
49
50 let request_path = request.path;
52 if request_path.is_none() {
53 http_response::send(&stream, "HTTP/1.1 400 Bad Request", None, None);
54 return;
55 }
56
57 let file_path = source_dir.join(request_path.unwrap().trim_start_matches('/'));
58
59 if file_path.is_dir() {
61 let dir_contents_as_html = get_dir_contents_as_html(&file_path, source_dir, address);
62 if dir_contents_as_html.is_err() {
63 http_response::send(&stream, "HTTP/1.1 500 Internal Server Error", None, None);
64 return;
65 }
66
67 http_response::send(
68 &stream,
69 "HTTP/1.1 200 OK",
70 Option::from(vec![("Content-Type".to_string(), "text/html".to_string())]),
71 Option::from(Vec::from(dir_contents_as_html.ok().unwrap())),
72 );
73 return;
74 }
75
76 if !fs::validate_path(file_path.as_ref()) {
77 http_response::send(&stream, "HTTP/1.1 404 Not Found", None, None);
78 return;
79 }
80
81 let file_contents = fs::get_file_contents(file_path.to_str().unwrap());
82 if file_contents.is_err() {
83 http_response::send(
84 &stream,
85 "HTTP/1.1 400 Bad Request",
86 None,
87 Option::from(Vec::from(file_contents.err().unwrap().to_string())),
88 );
89 return;
90 }
91
92 if file_path.file_name().is_none() || file_path.file_name().unwrap() == executable_name {
94 http_response::send(&stream, "HTTP/1.1 400 Bad Request", None, None);
95 return;
96 }
97
98 let mut response_headers: Vec<(String, String)> = vec![];
101 let mut has_content_type = false;
102 if file_path.extension().is_some() {
103 let mt = get_mime_type(file_path.extension().unwrap().to_str().unwrap());
104 has_content_type = true;
105 response_headers.push(("Content-Type".to_string(), mt));
106 }
107 if !has_content_type {
108 response_headers.push(("Content-Type".to_string(), "text/plain".to_string()));
109 }
110
111 let status_line = format!("{} 200 OK", request.protocol.unwrap());
112 http_response::send(
113 &stream,
114 status_line.as_str(),
115 Option::from(response_headers),
116 Option::from(file_contents.unwrap()),
117 );
118}