1use crate::{Authorization, Connection, ContentType, Encoding, HttpError, Language, Method, Upgrade, Uri};
2use crate::config::{Config};
3use chrono::{DateTime, Local};
4use json::{array, object, JsonValue};
5use log::{info};
6use std::io::{Write};
7use std::path::{Path};
8use std::{env, fs, io, thread};
9use std::cmp::PartialEq;
10use std::fs::OpenOptions;
11use std::sync::{Arc, Mutex};
12use std::time::Instant;
13use crate::stream::{Protocol, Scheme};
14
15#[derive(Clone, Debug)]
17pub struct Request {
18 pub config: Config,
19 pub header_line: String,
21 pub protocol: Protocol,
23 pub method: Method,
25 pub uri: Uri,
27 pub origin: String,
29 pub header: JsonValue,
31 pub cookie: JsonValue,
33 pub query: JsonValue,
35 pub params: JsonValue,
37 pub authorization: Authorization,
39 pub handle_time: String,
41 pub datetime: String,
43 pub timestamp: i64,
45 pub client_ip: String,
47 pub proxy_ip: String,
49 pub server_ip: String,
51 pub upgrade: Upgrade,
53 pub connection: Connection,
55 pub accept_encoding: Encoding,
57 start_time: Instant,
59 pub body_data: Vec<u8>,
61 content_length: usize,
63 pub content_type: ContentType,
65 boundary: String,
67 pub scheme: Arc<Mutex<Scheme>>,
68 pub accept_language: Language,
70}
71
72
73impl Request {
74 pub fn new(config: Config, scheme: Arc<Mutex<Scheme>>) -> Self {
75
76 let client_ip = scheme.lock().unwrap().client_ip();
78 let server_ip = scheme.lock().unwrap().server_ip();
80 let local: DateTime<Local> = Local::now();
81 Self {
82 config,
83 header_line: String::new(),
84 protocol: Protocol::Other(String::new()),
85 method: Method::Other(String::new()),
86 uri: Uri::default(),
87 origin: String::new(),
88 header: object! {},
89 cookie: object! {},
90 query: object! {},
91 params: object! {},
92 authorization: Authorization::Other(String::new()),
93 handle_time: String::new(),
94 scheme,
95 start_time: Instant::now(),
96 datetime: local.format("%Y-%m-%d %H:%M:%S").to_string(),
97 timestamp: local.timestamp(),
98 client_ip,
99 server_ip,
100 proxy_ip: String::new(),
101 upgrade: Upgrade::Other(String::new()),
102 connection: Connection::Other(String::new()),
103 accept_encoding: Encoding::None,
104 body_data: vec![],
105 content_length: 0,
106 content_type: ContentType::Other(String::new()),
107 boundary: String::new(),
108 accept_language: Language::ZhCN,
109 }
110 }
111
112 pub fn handle(&mut self) -> Result<(), HttpError> {
113 let mut data = vec![];
114 {
116 self.scheme.lock().unwrap().read(&mut data)?;
117 if let Some(pos) = data.windows(2).position(|window| window == [13, 10]) {
118 let header_data = data.drain(..pos).collect::<Vec<u8>>();
119 let header_data = String::from_utf8_lossy(header_data.as_slice());
120 data.drain(..2);
121 self.handle_header_line(header_data.trim())?;
122 } else {
123 return Err(HttpError::new(400, "请求行错误"));
124 }
125 }
126
127 match &self.protocol {
129 Protocol::HTTP1_0 | Protocol::HTTP1_1 => {
130 {
132 loop {
133 if let Some(pos) = data.windows(4).position(|window| window == [13, 10, 13, 10]) {
134 self.handle_header(data.drain(..pos).collect::<Vec<u8>>())?;
135 data.drain(..4);
136 self.body_data = data;
137 break;
138 }
139 self.scheme.lock().unwrap().read(&mut data)?;
140 }
141 }
142 {
144 if self.content_length > 0 {
145 loop {
146 if self.body_data.len() >= self.content_length {
147 break;
148 }
149 self.scheme.lock().unwrap().read(&mut self.body_data)?;
150 }
151 self.handle_body(self.body_data.clone())?;
152 }
153 }
154 self.handle_time = format!("{:?}", self.start_time.elapsed());
155 }
156 Protocol::HTTP2 => {
157 let header = data.drain(..8).collect::<Vec<u8>>();
158 if header.ne(b"\r\nSM\r\n\r\n") {
159 return Err(HttpError::new(400, "HTTP2格式错误"));
160 }
161 self.scheme.lock().unwrap().http2_send_server_settings()?;
162
163 let scheme_arc = self.scheme.clone();
164 let mut scheme = scheme_arc.lock().unwrap();
165
166 scheme.http2_handle_header(&mut data, self)?;
167 self.body_data = scheme.http2_handle_body(&mut data, self.clone())?;
168 self.handle_body(self.body_data.clone())?;
169 self.handle_time = format!("{:?}", self.start_time.elapsed());
170
171 }
172 Protocol::HTTP3 => return Err(HttpError::new(500, format!("未支持: HTTP3 {:?}", self.protocol).as_str())),
173 Protocol::Other(e) => return Err(HttpError::new(500, format!("未支持: Other {e} {:?}", self.protocol).as_str())),
174 }
175 Ok(())
176 }
177 pub fn handle_header_line(&mut self, line: &str) -> Result<(), HttpError> {
179 self.header_line = br_crypto::encoding::urlencoding_decode(line);
180 if self.header_line.is_empty() {
181 return Err(HttpError::new(400, "请求行错误"));
182 }
183 let mut it = self.header_line.split_whitespace();
184 let method = it.next();
185 let target = it.next();
186 let version = it.next();
187
188 self.protocol = match version {
190 None => return Err(HttpError::new(400, "协议版本错误")),
191 Some(e) => Protocol::from(e)
192 };
193 match &self.protocol {
195 Protocol::HTTP1_0 => {
196 self.method = match method {
197 None => return Err(HttpError::new(400, "请求类型错误")),
198 Some(e) => Method::from(e)
199 };
200 self.uri = match target {
201 None => return Err(HttpError::new(400, "请求资源错误")),
202 Some(e) => Uri::from(e)
203 };
204 self.query = self.uri.get_query_params();
205 }
206 Protocol::HTTP1_1 => {
207 self.method = match method {
208 None => return Err(HttpError::new(400, "请求类型错误")),
209 Some(e) => Method::from(e)
210 };
211 self.uri = match target {
212 None => return Err(HttpError::new(400, "请求资源错误")),
213 Some(e) => Uri::from(e)
214 };
215 self.query = self.uri.get_query_params();
216 }
217 Protocol::HTTP2 => {
218
219 }
220 Protocol::HTTP3 => return Err(HttpError::new(400, format!("{:?}协议暂未实现", self.protocol).as_str())),
221 Protocol::Other(name) => return Err(HttpError::new(400, format!("{name}协议暂未实现").as_str())),
222 }
223 Ok(())
224 }
225 pub fn handle_header(&mut self, data: Vec<u8>) -> Result<(), HttpError> {
226 let headers = String::from_utf8_lossy(data.as_slice());
227 if self.config.debug {
228 info!("\r\n=================请求头 {:?}=================\r\n{}\r\n{headers}\r\n========================================",thread::current().id(),self.header_line);
229 }
230 match &self.protocol {
231 Protocol::HTTP1_0 => {
232 for item in headers.lines() {
233 self.header_line_set(item)?;
234 }
235 }
236 Protocol::HTTP1_1 => {
237 for item in headers.lines() {
238 self.header_line_set(item)?;
239 }
240 if !self.header.has_key("host") {
241 return Err(HttpError::new(400, "请求头错误"));
242 }
243 }
244 Protocol::HTTP2 => {
245 return Err(HttpError::new(400, "HTTP2格式错误"));
246 }
247 Protocol::HTTP3 => return Err(HttpError::new(400, "暂时未开放")),
248 Protocol::Other(name) => {
249 return Err(HttpError::new(400, format!("未知协议格式: {}", name).as_str()));
250 }
251 }
252 Ok(())
253 }
254
255 fn header_line_set(&mut self, line: &str) -> Result<(), HttpError> {
256 match line.trim().find(":") {
257 None => return Err(HttpError::new(400, format!("请求头[{line}]错误").as_str())),
258 Some(e) => {
259 let key = line[..e].trim().to_lowercase().clone();
260 let value = line[e + 1..].trim();
261 self.set_header(key.as_str(), value)?;
262 }
263 }
264 Ok(())
265 }
266 pub fn set_header(&mut self, key: &str, value: &str) -> Result<(), HttpError> {
267 self.header[key] = value.into();
268 if value.len() > 8192 {
269 return Err(HttpError::new(400, "header longer than 8192 characters"));
270 }
271 match key {
272 "origin" => self.origin = value.to_string(),
273 "content-type" => {
274 let t = value.split_whitespace().collect::<Vec<&str>>();
275 if !t.is_empty() {
276 match t[0] {
277 _ if t[0].contains("multipart/form-data") => {
278 self.boundary = t[1].trim().trim_start_matches("boundary=").to_string();
279 self.content_type = ContentType::from("multipart/form-data");
280 }
281 _ => {
282 self.content_type = ContentType::from(t[0].trim_end_matches(";"));
283 }
284 }
285 }
286 self.header[key] = self.content_type.str().into();
287 }
288 "content-length" => self.content_length = value.parse::<usize>().unwrap_or(0),
289 "accept-language" => self.accept_language = Language::from(value),
290 "authorization" => self.authorization = Authorization::from(value),
291 "upgrade" => self.upgrade = Upgrade::from(value),
292 "connection" => self.connection = Connection::from(value),
293 "accept-encoding" => self.accept_encoding = Encoding::from(value),
294 "cookie" => {
295 let _ = value.split(';').collect::<Vec<&str>>().iter().map(|&x| {
296 match x.find('=') {
297 None => {}
298 Some(index) => {
299 let key = x[..index].trim().to_string();
300 let val = x[index + 1..].trim().to_string();
301 let _ = self.cookie.insert(key.as_str(), val);
302 }
303 }
304 ""
305 }).collect::<Vec<&str>>();
306 }
307 "x-forwarded-for" => self.proxy_ip = value.to_string(),
308 "x-real-ip" => self.client_ip = value.to_string(),
309 _ => {}
310 }
311
312 Ok(())
313 }
314 pub fn handle_body(&mut self, data: Vec<u8>) -> Result<(), HttpError> {
315 if self.config.debug {
316 info!("\r\n=================请求体 {:?}=================\r\n长度: {}\r\n========================================",thread::current().id(),self.content_length);
317 }
318 if data.len() != self.content_length {
319 return Err(HttpError::new(400, format!("Content-Length mismatch: header={}, actual={}", self.content_length, data.len()).as_str()));
320 }
321 if self.content_length == 0 {
322 return Ok(());
323 }
324 match &self.content_type {
325 ContentType::FormData => {
326 let boundary_marker = format!("--{}", self.boundary);
327 let parts = split_vec_u8(&data, boundary_marker.as_bytes());
328
329 let mut fields = object! {};
330
331 for part in parts {
332 let (header, body) = match part.windows(b"\r\n\r\n".len()).position(|window| window == b"\r\n\r\n") {
333 None => continue,
334 Some(_) => {
335 let mut re = split_vec_u8(part.as_slice(), "\r\n\r\n".as_bytes());
336 let header = re[0].clone();
337 let t = re[1].len() - 2;
338 let body = re[1].drain(..t).collect::<Vec<u8>>();
339 (header, body)
340 }
341 };
342 let headers = String::from_utf8_lossy(header.as_slice());
343 let mut field_name = "";
344 let mut filename = "";
345 let mut content_type = ContentType::Other("".to_string());
346
347 for header in headers.lines() {
348 if header.to_lowercase().starts_with("content-disposition:") {
349 match header.find("filename=\"") {
350 None => {}
351 Some(filename_start) => {
352 let filename_len = filename_start + 10;
353 let filename_end = header[filename_len..].find('"').unwrap() + filename_len;
354 filename = &header[filename_len..filename_end];
355 }
356 }
357 match header.find("name=\"") {
358 None => {}
359 Some(name_start) => {
360 let name_start = name_start + 6;
361 let name_end = header[name_start..].find('"').unwrap() + name_start;
362 field_name = &header[name_start..name_end];
363 }
364 }
365 }
366 if header.to_lowercase().starts_with("content-type:") {
367 content_type = ContentType::from(header.to_lowercase().trim_start_matches("content-type:").trim());
368 }
369 }
370
371 if filename.is_empty() {
372 let text = String::from_utf8_lossy(body.as_slice());
373 fields[field_name.to_string()] = JsonValue::from(text.into_owned());
374 continue;
375 }
376 let extension = Path::new(filename).extension().and_then(|ext| ext.to_str()); let suffix = extension.unwrap_or("txt");
378 let filename = if extension.is_none() {
379 format!("{filename}.txt")
380 } else {
381 filename.to_string()
382 };
383
384 let mut temp_dir = env::temp_dir();
385 temp_dir.push(filename.clone());
386 let Ok(mut temp_file) = fs::File::create(&temp_dir) else { continue };
387 if temp_file.write(body.as_slice()).is_ok() {
388 if fields[field_name.to_string()].is_empty() {
389 fields[field_name.to_string()] = array![];
390 }
391 fields[field_name.to_string()].push(object! {
392 id:br_crypto::sha256::encrypt_hex(&body.clone()),
393 name:filename,
394 suffix:suffix,
395 size:body.len(),
396 type:content_type.str(),
397 file:temp_dir.to_str()
398 }).unwrap();
399 }
400 }
401 self.params = fields;
402 }
403 ContentType::FormUrlencoded => {
404 let input = String::from_utf8_lossy(&data);
405 let mut list = object! {};
406 for pair in input.split('&') {
407 if let Some((key, val)) = pair.split_once('=') {
408 let key = br_crypto::encoding::urlencoding_decode(key);
409 let val = br_crypto::encoding::urlencoding_decode(val);
410 let _ = list.insert(key.as_str(), val);
411 }
412 }
413 self.params = list;
414 }
415 ContentType::Json => {
416 let text = String::from_utf8_lossy(data.as_slice());
417 self.params = json::parse(text.into_owned().as_str()).unwrap_or(object! {});
418 }
419 ContentType::Xml | ContentType::Html | ContentType::Text | ContentType::Javascript => {
420 let text = String::from_utf8_lossy(data.as_slice());
421 self.params = text.into_owned().into();
422 }
423 ContentType::Other(_) => {}
424 ContentType::Stream => {}
425 }
426 Ok(())
427 }
428 pub fn save_log(&mut self) -> io::Result<()> {
430 if !self.config.log {
431 return Ok(());
432 }
433 let local: DateTime<Local> = Local::now();
434 let time_dir = local.format("%Y-%m-%d-%H").to_string();
435 let time_dir = time_dir.split('-').collect::<Vec<&str>>();
436
437 let mut res = self.config.root_path.join(self.config.runtime.clone()).join("log");
438 for item in &time_dir {
439 res.push(item);
440 }
441 fs::create_dir_all(res.parent().unwrap())?;
442 let log_file = format!("{}.log", res.to_str().unwrap());
443 let mut file = OpenOptions::new()
444 .append(true) .create(true) .open(log_file)?;
448 let data = format!(
449 "[{}] {} ClientIP: {} {} {} ContentLength: {} ContentType: {} Time: {:?} Thread: {:?}\r\n",
450 self.datetime,
451 self.protocol.str(),
452 self.client_ip,
453 self.method.str(),
454 self.uri.url,
455 self.content_length,
456 self.content_type.clone().str(),
457 self.handle_time,
458 thread::current().id()
459 );
460 file.write_all(data.as_bytes())?;
461 Ok(())
462 }
463}
464
465fn split_vec_u8(data: &[u8], delimiter: &[u8]) -> Vec<Vec<u8>> {
466 let mut parts = Vec::new();
467 let mut start = 0;
468 let mut i = 0;
469
470 while i <= data.len().saturating_sub(delimiter.len()) {
471 if &data[i..i + delimiter.len()] == delimiter {
472 parts.push(data[start..i].to_vec());
473 i += delimiter.len();
474 start = i;
475 } else {
476 i += 1;
477 }
478 }
479 if start <= data.len() {
481 parts.push(data[start..].to_vec());
482 }
483 parts
484}
485