1use crate::config::Config;
2use crate::stream::Scheme;
3use crate::{
4 parse_content_type_header_value, split_boundary, Authorization, Connection, ContentType,
5 Encoding, HttpError, Language, Method, Protocol, Upgrade, Uri,
6};
7use chrono::{DateTime, Local};
8use json::{array, object, JsonValue};
9use log::info;
10use std::cmp::PartialEq;
11use std::fs::OpenOptions;
12use std::io::Write;
13use std::path::Path;
14use std::sync::{Arc, Mutex};
15use std::time::Instant;
16use std::{env, fs, io, thread};
17
18const MAX_HEADER_VALUE_LEN: usize = 8192;
19
20#[derive(Clone, Debug)]
22pub struct Request {
23 pub config: Config,
24 pub header_line: String,
26 pub protocol: Protocol,
28 pub method: Method,
30 pub uri: Uri,
32 pub origin: String,
34 pub header: JsonValue,
36 pub cookie: JsonValue,
38 pub query: JsonValue,
40 pub params: JsonValue,
42 pub authorization: Authorization,
44 pub handle_time: f64,
46 pub datetime: String,
48 pub timestamp: i64,
50 pub client_ip: String,
52 pub proxy_ip: String,
54 pub server_ip: String,
56 pub upgrade: Upgrade,
58 pub connection: Connection,
60 pub accept_encoding: Encoding,
62 start_time: Instant,
64 pub body_data: Vec<u8>,
66 content_length: usize,
68 pub content_type: ContentType,
70 boundary: String,
72 pub scheme: Arc<Mutex<Scheme>>,
73 pub accept_language: Language,
75}
76
77impl Request {
78 pub fn new(config: Config, scheme: Arc<Mutex<Scheme>>) -> Self {
79 let client_ip = scheme.lock().map(|mut s| s.client_ip()).unwrap_or_default();
81 let server_ip = scheme.lock().map(|mut s| s.server_ip()).unwrap_or_default();
83 let local: DateTime<Local> = Local::now();
84 Self {
85 config,
86 header_line: String::new(),
87 protocol: Protocol::Other(String::new()),
88 method: Method::Other(String::new()),
89 uri: Uri::default(),
90 origin: String::new(),
91 header: object! {},
92 cookie: object! {},
93 query: object! {},
94 params: object! {},
95 authorization: Authorization::Other(String::new()),
96 handle_time: 0.0,
97 scheme,
98 start_time: Instant::now(),
99 datetime: local.format("%Y-%m-%d %H:%M:%S").to_string(),
100 timestamp: local.timestamp(),
101 client_ip,
102 server_ip,
103 proxy_ip: String::new(),
104 upgrade: Upgrade::Other(String::new()),
105 connection: Connection::Other(String::new()),
106 accept_encoding: Encoding::None,
107 body_data: vec![],
108 content_length: 0,
109 content_type: ContentType::Other(String::new()),
110 boundary: String::new(),
111 accept_language: Language::ZhCN,
112 }
113 }
114
115 pub fn handle(&mut self) -> Result<(), HttpError> {
116 let mut data = vec![];
117 {
119 self.scheme
120 .lock()
121 .map_err(|e| HttpError::new(500, &format!("lock: {}", e)))?
122 .read(&mut data)?;
123 if let Some(pos) = data.windows(2).position(|window| window == [13, 10]) {
124 let header_data = data.drain(..pos).collect::<Vec<u8>>();
125 let header_data = String::from_utf8_lossy(header_data.as_slice());
126 data.drain(..2);
127 self.handle_header_line(header_data.trim())?;
128 } else {
129 return Err(HttpError::new(400, "请求行错误"));
130 }
131 }
132
133 match &self.protocol {
135 Protocol::HTTP1_0 | Protocol::HTTP1_1 => {
136 {
138 loop {
139 if let Some(pos) = data
140 .windows(4)
141 .position(|window| window == [13, 10, 13, 10])
142 {
143 self.handle_header(data.drain(..pos).collect::<Vec<u8>>())?;
144 data.drain(..4);
145 self.body_data = data;
146 break;
147 }
148 self.scheme
149 .lock()
150 .map_err(|e| HttpError::new(500, &format!("lock: {}", e)))?
151 .read(&mut data)?;
152 }
153 }
154 {
156 if self.content_length > 0 {
157 if self.content_length > self.config.max_body_size {
158 return Err(HttpError::new(
159 413,
160 &format!(
161 "Request body too large: {} > {}",
162 self.content_length, self.config.max_body_size
163 ),
164 ));
165 }
166 loop {
167 if self.body_data.len() >= self.content_length {
168 break;
169 }
170 self.scheme
171 .lock()
172 .map_err(|e| HttpError::new(500, &format!("lock: {}", e)))?
173 .read(&mut self.body_data)?;
174 }
175 self.handle_body(self.body_data.clone())?;
176 }
177 }
178 self.handle_time = self.start_time.elapsed().as_micros() as f64 / 1000.0;
179 }
180 Protocol::HTTP2 => {
181 let header = data.drain(..8).collect::<Vec<u8>>();
182 if header.ne(b"\r\nSM\r\n\r\n") {
183 return Err(HttpError::new(400, "HTTP2格式错误"));
184 }
185 self.scheme
186 .lock()
187 .map_err(|e| HttpError::new(500, &format!("lock: {}", e)))?
188 .http2_send_server_settings()?;
189
190 let scheme_arc = self.scheme.clone();
191 let mut scheme = scheme_arc
192 .lock()
193 .map_err(|e| HttpError::new(500, &format!("lock: {}", e)))?;
194
195 scheme.http2_handle_header(&mut data, self)?;
196 self.body_data = scheme.http2_handle_body(&mut data, self.clone())?;
197 self.handle_body(self.body_data.clone())?;
198 self.handle_time = self.start_time.elapsed().as_micros() as f64 / 1000.0;
199 }
200 Protocol::HTTP3 => {
201 return Err(HttpError::new(
202 500,
203 format!("未支持: HTTP3 {:?}", self.protocol).as_str(),
204 ))
205 }
206 Protocol::Other(e) => {
207 return Err(HttpError::new(
208 500,
209 format!("未支持: Other {e} {:?}", self.protocol).as_str(),
210 ))
211 }
212 }
213 Ok(())
214 }
215 pub fn handle_header_line(&mut self, line: &str) -> Result<(), HttpError> {
217 self.header_line = br_crypto::encoding::urlencoding_decode(line);
218 if self.header_line.is_empty() {
219 return Err(HttpError::new(400, "请求行错误"));
220 }
221 let mut it = self.header_line.split_whitespace();
222 let method = it.next();
223 let target = it.next();
224 let version = it.next();
225
226 self.protocol = match version {
228 None => return Err(HttpError::new(400, "协议版本错误")),
229 Some(e) => Protocol::from(e),
230 };
231 match &self.protocol {
233 Protocol::HTTP1_0 => {
234 self.method = match method {
235 None => return Err(HttpError::new(400, "HTTP10请求类型错误")),
236 Some(e) => Method::from(e),
237 };
238 self.uri = match target {
239 None => return Err(HttpError::new(400, "HTTP10请求资源错误")),
240 Some(e) => Uri::from(e),
241 };
242 self.query = self.uri.get_query_params();
243 }
244 Protocol::HTTP1_1 => {
245 self.method = match method {
246 None => return Err(HttpError::new(400, "HTTP11请求类型错误")),
247 Some(e) => Method::from(e),
248 };
249 self.uri = match target {
250 None => return Err(HttpError::new(400, "HTTP11请求资源错误")),
251 Some(e) => Uri::from(e),
252 };
253 self.query = self.uri.get_query_params();
254 }
255 Protocol::HTTP2 => {}
256 Protocol::HTTP3 => {
257 return Err(HttpError::new(
258 400,
259 format!("{:?}协议暂未实现", self.protocol).as_str(),
260 ))
261 }
262 Protocol::Other(name) => {
263 return Err(HttpError::new(400, format!("{name}协议暂未实现").as_str()))
264 }
265 }
266 Ok(())
267 }
268 pub fn handle_header(&mut self, data: Vec<u8>) -> Result<(), HttpError> {
269 let headers = String::from_utf8_lossy(data.as_slice());
270 if self.config.debug {
271 info!("\r\n=================请求头 {:?}=================\r\n{}\r\n{headers}\r\n========================================",thread::current().id(),self.header_line);
272 }
273 match &self.protocol {
274 Protocol::HTTP1_0 => {
275 for item in headers.lines() {
276 self.header_line_set(item)?;
277 }
278 }
279 Protocol::HTTP1_1 => {
280 for item in headers.lines() {
281 self.header_line_set(item)?;
282 }
283 if !self.header.has_key("host") {
284 return Err(HttpError::new(400, "请求头错误"));
285 }
286 }
287 Protocol::HTTP2 => {
288 return Err(HttpError::new(400, "HTTP2格式错误"));
289 }
290 Protocol::HTTP3 => return Err(HttpError::new(400, "暂时未开放")),
291 Protocol::Other(name) => {
292 return Err(HttpError::new(
293 400,
294 format!("未知协议格式: {}", name).as_str(),
295 ));
296 }
297 }
298 Ok(())
299 }
300
301 fn header_line_set(&mut self, line: &str) -> Result<(), HttpError> {
302 match line.trim().find(":") {
303 None => return Err(HttpError::new(400, format!("请求头[{line}]错误").as_str())),
304 Some(e) => {
305 let key = line[..e].trim().to_lowercase().clone();
306 let value = line[e + 1..].trim();
307 self.set_header(key.as_str(), value)?;
308 }
309 }
310 Ok(())
311 }
312 pub fn set_header(&mut self, key: &str, value: &str) -> Result<(), HttpError> {
313 self.header[key] = value.into();
314 if value.len() > MAX_HEADER_VALUE_LEN {
315 return Err(HttpError::new(400, "header longer than 8192 characters"));
316 }
317 match key {
318 "origin" => self.origin = value.to_string(),
319 "content-type" => {
320 let (mime, params) = parse_content_type_header_value(value);
321 if !mime.is_empty() {
322 if mime == "multipart/form-data" {
323 if let Some(b) = params.get("boundary") {
325 self.boundary = b.to_string();
326 } else {
327 let lower = value.to_lowercase();
329 if let Some(pos) = lower.find("boundary=") {
330 let raw = &value[pos + "boundary=".len()..];
331 let raw = raw.split(';').next().unwrap_or(raw).trim();
332 let raw = raw.trim_matches('"');
333 self.boundary = raw.to_string();
334 }
335 }
336 self.content_type = ContentType::from("multipart/form-data");
337 } else {
338 self.content_type = ContentType::from(mime.as_str());
340 }
341 }
342 self.header[key] = self.content_type.str().into();
343 }
344 "content-length" => self.content_length = value.parse::<usize>().unwrap_or(0),
345 "accept-language" => self.accept_language = Language::from(value),
346 "authorization" => self.authorization = Authorization::from(value),
347 "upgrade" => self.upgrade = Upgrade::from(value),
348 "connection" => self.connection = Connection::from(value),
349 "accept-encoding" => self.accept_encoding = Encoding::from(value),
350 "cookie" => {
351 let _ = value
352 .split(';')
353 .collect::<Vec<&str>>()
354 .iter()
355 .map(|&x| {
356 match x.find('=') {
357 None => {}
358 Some(index) => {
359 let key = x[..index].trim().to_string();
360 let val = x[index + 1..].trim().to_string();
361 let _ = self.cookie.insert(key.as_str(), val);
362 }
363 }
364 ""
365 })
366 .collect::<Vec<&str>>();
367 }
368 "x-forwarded-for" => self.proxy_ip = value.to_string(),
369 "x-real-ip" => self.client_ip = value.to_string(),
370 _ => {}
371 }
372
373 Ok(())
374 }
375 pub fn handle_body(&mut self, data: Vec<u8>) -> Result<(), HttpError> {
376 if self.config.debug {
377 info!("\r\n=================请求体 {:?}=================\r\n长度: {}\r\n========================================",thread::current().id(),self.content_length);
378 }
379 if data.len() != self.content_length {
380 return Err(HttpError::new(
381 400,
382 format!(
383 "Content-Length mismatch: header={}, actual={}",
384 self.content_length,
385 data.len()
386 )
387 .as_str(),
388 ));
389 }
390 if self.content_length == 0 {
391 return Ok(());
392 }
393 match &self.content_type {
394 ContentType::FormData => {
395 let parts = match split_boundary(data, &self.boundary) {
396 Ok(e) => e,
397 Err(_) => return Err(HttpError::new(400, "Invalid boundary marker")),
398 };
399 let mut fields = object! {};
400
401 for part in parts {
402 let (header, body) = match part
403 .windows(b"\r\n\r\n".len())
404 .position(|window| window == b"\r\n\r\n")
405 {
406 None => continue,
407 Some(e) => {
408 let header = part[..e].to_vec();
409 let body = part[e + 4..].to_vec();
410 let body = body[..body.len()].to_vec();
411 (header, body)
412 }
413 };
414 let headers = String::from_utf8_lossy(header.as_slice());
415 let mut field_name = "";
416 let mut filename = "";
417 let mut content_type = ContentType::Other("".to_string());
418
419 for header in headers.lines() {
420 if header.to_lowercase().starts_with("content-disposition:") {
421 match header.find("filename=\"") {
422 None => {}
423 Some(filename_start) => {
424 let filename_len = filename_start + 10;
425 if let Some(end_offset) = header[filename_len..].find('"') {
426 let filename_end = end_offset + filename_len;
427 filename = &header[filename_len..filename_end];
428 }
429 }
430 }
431 match header.find("name=\"") {
432 None => {}
433 Some(name_start) => {
434 let name_start = name_start + 6;
435 if let Some(end_offset) = header[name_start..].find('"') {
436 let name_end = end_offset + name_start;
437 field_name = &header[name_start..name_end];
438 }
439 }
440 }
441 }
442 if header.to_lowercase().starts_with("content-type:") {
443 content_type = ContentType::from(
444 header
445 .to_lowercase()
446 .trim_start_matches("content-type:")
447 .trim(),
448 );
449 }
450 }
451
452 if filename.is_empty() {
453 let text = String::from_utf8_lossy(body.as_slice()).into_owned();
454 fields[field_name.to_string()] = match text.as_str() {
455 "true" => JsonValue::Boolean(true),
456 "false" => JsonValue::Boolean(false),
457 s => {
458 if let Ok(n) = s.parse::<i64>() {
459 n.into()
460 } else if let Ok(f) = s.parse::<f64>() {
461 f.into()
462 } else {
463 text.into()
464 }
465 }
466 };
467 continue;
468 }
469 let extension = Path::new(filename).extension().and_then(|ext| ext.to_str()); let suffix = extension.unwrap_or("txt");
471 let filename = if extension.is_none() {
472 format!("{filename}.txt")
473 } else {
474 filename.to_string()
475 };
476
477 let mut temp_dir = env::temp_dir();
478 temp_dir.push(filename.clone());
479 let Ok(mut temp_file) = fs::File::create(&temp_dir) else {
480 continue;
481 };
482 if temp_file.write(body.as_slice()).is_ok() {
483 if fields[field_name.to_string()].is_empty() {
484 fields[field_name.to_string()] = array![];
485 }
486 fields[field_name.to_string()]
487 .push(object! {
488 id:br_crypto::sha256::encrypt_hex(&body.clone()),
489 name:filename,
490 suffix:suffix,
491 size:body.len(),
492 type:content_type.str(),
493 file:temp_dir.to_str()
494 })
495 .unwrap_or_else(|e| log::warn!("JSON push failed: {}", e));
496 }
497 }
498 self.params = fields;
499 }
500 ContentType::FormUrlencoded => {
501 let input = String::from_utf8_lossy(&data);
502 let mut list = object! {};
503 for pair in input.split('&') {
504 if let Some((key, val)) = pair.split_once('=') {
505 let key = br_crypto::encoding::urlencoding_decode(key);
506 let val = br_crypto::encoding::urlencoding_decode(val);
507 let _ = list.insert(key.as_str(), val);
508 }
509 }
510 self.params = list;
511 }
512 ContentType::Json => {
513 let text = String::from_utf8_lossy(data.as_slice());
514 self.params = json::parse(text.into_owned().as_str()).unwrap_or(object! {});
515 }
516 ContentType::Xml | ContentType::Html | ContentType::Text | ContentType::Javascript => {
517 let text = String::from_utf8_lossy(data.as_slice());
518 self.params = text.into_owned().into();
519 }
520 ContentType::Other(_) => {}
521 ContentType::Stream => {}
522 }
523 Ok(())
524 }
525 pub fn save_log(&mut self) -> io::Result<()> {
527 if !self.config.log {
528 return Ok(());
529 }
530 let local: DateTime<Local> = Local::now();
531 let time_dir = local.format("%Y-%m-%d-%H").to_string();
532 let time_dir = time_dir.split('-').collect::<Vec<&str>>();
533
534 let mut res = self
535 .config
536 .root_path
537 .join(self.config.runtime.clone())
538 .join("log");
539 for item in &time_dir {
540 res.push(item);
541 }
542 let parent = res.parent().ok_or_else(|| {
543 io::Error::new(io::ErrorKind::NotFound, "log parent directory not found")
544 })?;
545 fs::create_dir_all(parent)?;
546 let log_file = format!("{}.log", res.to_str().unwrap_or("log"));
547 let mut file = OpenOptions::new()
548 .append(true) .create(true) .open(log_file)?;
552 let data = format!(
553 "[{}] {} ClientIP: {} {} {} ContentLength: {} ContentType: {} Time: {:?} Thread: {:?}\r\n",
554 self.datetime,
555 self.protocol.str(),
556 self.client_ip,
557 self.method.str(),
558 self.uri.url,
559 self.content_length,
560 self.content_type.clone().str(),
561 self.handle_time,
562 thread::current().id()
563 );
564 file.write_all(data.as_bytes())?;
565 Ok(())
566 }
567}