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