rust_web_server/app/controller/not_found/
mod.rs1use file_ext::FileExt;
2use crate::controller::Controller;
3use crate::header::Header;
4use crate::mime_type::MimeType;
5use crate::range::Range;
6use crate::request::Request;
7use crate::response::{Response, STATUS_CODE_REASON_PHRASE};
8use crate::server::ConnectionInfo;
9
10pub struct NotFoundController;
11
12impl Controller for NotFoundController {
13 fn is_matching(_request: &Request, _connection: &ConnectionInfo) -> bool {
14 true
15 }
16
17 fn process(request: &Request, mut response: Response, _connection: &ConnectionInfo) -> Response {
18 if NotFoundController::is_static_path_with_other_method(request) {
22 response.status_code = *STATUS_CODE_REASON_PHRASE.n405_method_not_allowed.status_code;
23 response.reason_phrase = STATUS_CODE_REASON_PHRASE.n405_method_not_allowed.reason_phrase.to_string();
24 response.headers.push(Header { name: Header::_ALLOW.into(), value: NotFoundController::STATIC_ALLOW.into() });
25 response.content_range_list = vec![Range::get_content_range(
26 b"405 Method Not Allowed".to_vec(),
27 MimeType::TEXT_PLAIN.to_string(),
28 )];
29 return response;
30 }
31
32 response.status_code = *STATUS_CODE_REASON_PHRASE.n404_not_found.status_code;
33 response.reason_phrase = STATUS_CODE_REASON_PHRASE.n404_not_found.reason_phrase.to_string();
34
35
36 if FileExt::does_file_exist(NotFoundController::NOT_FOUND_FILEPATH) {
37 let boxed_content_range =
38 Range::get_content_range_of_a_file(NotFoundController::NOT_FOUND_FILEPATH);
39
40 if boxed_content_range.is_ok() {
41 let content_range = boxed_content_range.unwrap();
42 let content_range_list = vec![content_range];
43 response.content_range_list = content_range_list;
44 } else {
45 let error = boxed_content_range.err().unwrap();
46 let mime_type = MimeType::TEXT_HTML.to_string();
47 let content_range = Range::get_content_range(
48 Vec::from(error.as_bytes()),
49 mime_type
50 );
51
52 let content_range_list = vec![content_range];
53 response.content_range_list = content_range_list;
54 response.status_code = *STATUS_CODE_REASON_PHRASE.n500_internal_server_error.status_code;
55 response.reason_phrase = STATUS_CODE_REASON_PHRASE.n500_internal_server_error.reason_phrase.to_string();
56 }
57 } else {
58 let not_found_file = include_bytes!("404.html");
59
60 let content_range =
61 Range::get_content_range(not_found_file.to_vec(), MimeType::TEXT_HTML.to_string());
62
63
64 let content_range_list = vec![content_range];
65 response.content_range_list = content_range_list;
66
67 }
68
69 response
70 }
71}
72
73impl NotFoundController {
74 pub const STATIC_ALLOW: &'static str = "GET, HEAD, OPTIONS";
76
77 fn is_static_path_with_other_method(request: &Request) -> bool {
80 use crate::request::METHOD;
81 if request.method == METHOD.get || request.method == METHOD.head || request.method == METHOD.options {
82 return false;
83 }
84 let Ok(components) = crate::url::URL::parse_request_target(&request.request_uri) else { return false };
85 if components.path == "/" {
86 return false;
87 }
88 let Ok(fs_path) = crate::app::controller::static_resource::static_fs_path(&components.path) else { return false };
89 std::fs::metadata(&fs_path).is_ok() && crate::app::controller::static_resource::inside_root(&fs_path)
90 }
91}
92
93impl NotFoundController {
95 pub const NOT_FOUND_FILEPATH: &'static str = "404.html";
96
97 pub fn is_matching_request(_request: &Request) -> bool {
98 true
99 }
100
101 pub fn process_request(_request: &Request, mut response: Response) -> Response {
102 response.status_code = *STATUS_CODE_REASON_PHRASE.n404_not_found.status_code;
103 response.reason_phrase = STATUS_CODE_REASON_PHRASE.n404_not_found.reason_phrase.to_string();
104
105
106 if FileExt::does_file_exist(NotFoundController::NOT_FOUND_FILEPATH) {
107 let boxed_content_range =
108 Range::get_content_range_of_a_file(NotFoundController::NOT_FOUND_FILEPATH);
109
110 if boxed_content_range.is_ok() {
111 let content_range = boxed_content_range.unwrap();
112 let content_range_list = vec![content_range];
113 response.content_range_list = content_range_list;
114 } else {
115 let error = boxed_content_range.err().unwrap();
116 let mime_type = MimeType::TEXT_HTML.to_string();
117 let content_range = Range::get_content_range(
118 Vec::from(error.as_bytes()),
119 mime_type
120 );
121
122 let content_range_list = vec![content_range];
123 response.content_range_list = content_range_list;
124 response.status_code = *STATUS_CODE_REASON_PHRASE.n500_internal_server_error.status_code;
125 response.reason_phrase = STATUS_CODE_REASON_PHRASE.n500_internal_server_error.reason_phrase.to_string();
126 }
127 } else {
128 let not_found_file = include_bytes!("404.html");
129
130 let content_range =
131 Range::get_content_range(not_found_file.to_vec(), MimeType::TEXT_HTML.to_string());
132
133
134 let content_range_list = vec![content_range];
135 response.content_range_list = content_range_list;
136
137 }
138
139 response
140 }
141}