Skip to main content

br_web_server/
response.rs

1use crate::request::Request;
2use crate::websocket::Websocket;
3use crate::Protocol::HTTP2;
4use crate::Status;
5use crate::{ContentType, Encoding, Handler, HttpError, Method, Protocol, Upgrade};
6use chrono::{DateTime, Duration as dur, Utc};
7use hpack::Encoder;
8use json::{object, JsonValue};
9use log::{error, info};
10use std::io::Error;
11use std::path::{Path, PathBuf};
12use std::{fs, io, thread};
13const FLAG_END_STREAM: u8 = 0x01;
14const FLAG_END_HEADERS: u8 = 0x04;
15const DEFAULT_CACHE_MAX_AGE: u64 = 86400;
16/// 响应
17#[derive(Clone, Debug)]
18pub struct Response {
19    pub request: Request,
20    pub status: Status,
21    pub headers: JsonValue,
22    pub cookies: JsonValue,
23    /// 消息体
24    pub body: Vec<u8>,
25    /// HTTP2 使用
26    pub stream_id: u32,
27    /// ws 通信密钥
28    pub key: String,
29    /// ws 版本
30    pub version: String,
31    pub factory: fn(out: Websocket) -> Box<dyn Handler>,
32    /// 允许来源
33    pub allow_origins: Vec<&'static str>,
34    /// 允许方法
35    pub allow_methods: Vec<&'static str>,
36    /// 允许请求头
37    pub allow_headers: Vec<&'static str>,
38    /// 消息体类型
39    pub content_type: ContentType,
40    pub committed: bool,
41    pub stream_started: bool,
42    pub stream_finished: bool,
43}
44
45fn sanitize_header_value(value: &str) -> String {
46    value.chars().filter(|c| *c != '\r' && *c != '\n').collect()
47}
48
49impl Response {
50    pub fn new(request: &Request, factory: fn(out: Websocket) -> Box<dyn Handler>) -> Self {
51        Self {
52            request: request.clone(),
53            status: Status::default(),
54            headers: object! {},
55            cookies: object! {},
56            body: vec![],
57            stream_id: 0,
58            key: String::new(),
59            version: String::new(),
60            factory,
61            allow_origins: vec![],
62            allow_methods: vec![],
63            allow_headers: vec![],
64            content_type: ContentType::Other(String::new()),
65            committed: false,
66            stream_started: false,
67            stream_finished: false,
68        }
69    }
70    pub fn is_committed(&self) -> bool {
71        self.committed
72    }
73    pub fn handle(mut self) -> io::Result<()> {
74        match self.request.upgrade {
75            Upgrade::Websocket => {
76                self.handle_protocol_ws()?;
77                return Ok(());
78            }
79            Upgrade::Http | Upgrade::Other(_) => {}
80            Upgrade::H2c => {
81                let _ = self.handle_protocol_h2c();
82            }
83        }
84
85        match self.request.protocol {
86            Protocol::HTTP1_0 => self.handle_protocol_http0()?,
87            Protocol::HTTP1_1 => self.handle_protocol_http1()?,
88            Protocol::HTTP2 => self.handle_protocol_http2()?,
89            Protocol::HTTP3 | Protocol::Other(_) => {}
90        }
91        Ok(())
92    }
93    fn handle_protocol_http0(&mut self) -> io::Result<()> {
94        let websocket = Websocket::http(self.request.clone(), self.clone());
95        let mut factory = (self.factory)(websocket);
96        match self.request.method {
97            Method::OPTIONS => {
98                factory.on_options(self);
99                match self.on_options() {
100                    Ok(()) => match self.status(200).send() {
101                        Ok(()) => {}
102                        Err(e) => {
103                            return Err(Error::other(format!(
104                                "1004: {} {} {}",
105                                self.request.uri.path, e.code, e.body
106                            )))
107                        }
108                    },
109                    Err(e) => {
110                        return match self.status(e.code).txt(e.body.as_str()).send() {
111                            Ok(()) => Ok(()),
112                            Err(e2) => Err(Error::other(format!(
113                                "1005: {} {} {}",
114                                self.request.uri.path, e2.code, e2.body
115                            ))),
116                        }
117                    }
118                }
119            }
120            Method::GET => {
121                if let Ok(e) = self.read_resource() {
122                    if self.request.header.has_key("range") {
123                        return match self.status(206).range(&e).send() {
124                            Ok(()) => Ok(()),
125                            Err(e) => Err(Error::other(format!(
126                                "1003: {} {} {}",
127                                self.request.uri.path, e.code, e.body
128                            ))),
129                        };
130                    }
131                    return match self.status(200).file(&e).send() {
132                        Ok(_) => Ok(()),
133                        Err(e) => Err(Error::other(format!(
134                            "1003: {} {} {}",
135                            self.request.uri.path, e.code, e.body
136                        ))),
137                    };
138                }
139                factory.on_request(self.request.clone(), self);
140                if self.is_committed() {
141                    return Ok(());
142                }
143                factory.on_response(self);
144                if self.is_committed() {
145                    return Ok(());
146                }
147                match self.send() {
148                    Ok(()) => {}
149                    Err(e) => {
150                        return Err(Error::other(format!(
151                            "1002: {} {} {}",
152                            self.request.uri.path, e.code, e.body
153                        )))
154                    }
155                }
156            }
157            _ => {
158                factory.on_request(self.request.clone(), self);
159                if self.is_committed() {
160                    return Ok(());
161                }
162                factory.on_response(self);
163                if self.is_committed() {
164                    return Ok(());
165                }
166                match self.send() {
167                    Ok(_) => {}
168                    Err(e) => return Err(Error::other(format!("1001: {} {}", e.code, e.body))),
169                }
170            }
171        }
172        Ok(())
173    }
174    fn handle_protocol_http1(&mut self) -> io::Result<()> {
175        self.handle_protocol_http0()
176    }
177    fn handle_protocol_http2(&mut self) -> io::Result<()> {
178        let websocket = Websocket::http(self.request.clone(), self.clone());
179        let mut factory = (self.factory)(websocket);
180
181        match self.request.method {
182            Method::OPTIONS => {
183                factory.on_options(self);
184                match self.send() {
185                    Ok(_) => {}
186                    Err(e) => return Err(Error::other(format!("2001: {} {}", e.code, e.body))),
187                };
188            }
189            Method::GET => {
190                if let Ok(e) = self.read_resource() {
191                    return match self.status(200).file(&e).send() {
192                        Ok(_) => Ok(()),
193                        Err(e) => Err(Error::other(e.body)),
194                    };
195                }
196                factory.on_request(self.request.clone(), self);
197                if self.is_committed() {
198                    return Ok(());
199                }
200                factory.on_response(self);
201                if self.is_committed() {
202                    return Ok(());
203                }
204                match self.send() {
205                    Ok(()) => {}
206                    Err(e) => return Err(Error::other(format!("2002: {} {}", e.code, e.body))),
207                }
208            }
209            _ => {
210                factory.on_request(self.request.clone(), self);
211                if self.is_committed() {
212                    return Ok(());
213                }
214                factory.on_response(self);
215                if self.is_committed() {
216                    return Ok(());
217                }
218                match self.send() {
219                    Ok(_) => {}
220                    Err(e) => return Err(Error::other(format!("2003: {} {}", e.code, e.body))),
221                }
222            }
223        }
224        Ok(())
225    }
226    fn handle_protocol_ws(&mut self) -> io::Result<()> {
227        let mut websocket = Websocket::new(self.request.clone(), self.clone());
228        let _ = websocket.handle();
229        Ok(())
230    }
231    fn handle_protocol_h2c(&mut self) -> Result<(), HttpError> {
232        self.header("Upgrade", "h2c");
233        self.header("Connection", "Upgrade");
234        match self.status(101).send() {
235            Ok(()) => self.headers.clear(),
236            Err(e) => return Err(e),
237        };
238        self.request.protocol = HTTP2;
239        self.request
240            .scheme
241            .lock()
242            .map_err(|e| HttpError::new(500, &format!("lock: {}", e)))?
243            .http2_send_server_settings()?;
244        let mut data = vec![];
245        self.request
246            .scheme
247            .lock()
248            .map_err(|e| HttpError::new(500, &format!("lock: {}", e)))?
249            .read(&mut data)?;
250
251        let t = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
252        if let Some(pos) = data.windows(t.len()).position(|window| window == t) {
253            let _ = data.drain(..pos).collect::<Vec<u8>>();
254            data.drain(..t.len());
255        } else {
256            return Err(HttpError::new(400, "请求行错误"));
257        }
258        let (_payload, _frame_type, flags, _stream_id) = self
259            .request
260            .scheme
261            .lock()
262            .map_err(|e| HttpError::new(500, &format!("lock: {}", e)))?
263            .http2_packet(&mut data)?;
264        if flags & 0x01 == 0 {
265            self.request
266                .scheme
267                .lock()
268                .map_err(|e| HttpError::new(500, &format!("lock: {}", e)))?
269                .http2_settings_ack()?;
270        }
271        let (_payload, _frame_type, _flags, _stream_id) = self
272            .request
273            .scheme
274            .lock()
275            .map_err(|e| HttpError::new(500, &format!("lock: {}", e)))?
276            .http2_packet(&mut data)?;
277        let (payload, _frame_type, _flags, _stream_id) = self
278            .request
279            .scheme
280            .lock()
281            .map_err(|e| HttpError::new(500, &format!("lock: {}", e)))?
282            .http2_packet(&mut data)?;
283        if payload.len() == 4 {
284            let raw = u32::from_be_bytes(
285                <[u8; 4]>::try_from(&payload[..4])
286                    .map_err(|_| HttpError::new(400, "Invalid WindowUpdate frame data"))?,
287            );
288            let increment = raw & 0x7FFF_FFFF; // 屏蔽最高位保留位
289            if self.request.config.debug {
290                info!("WindowUpdate: increment = {} {:?}", increment, payload);
291            }
292        } else {
293            return Err(HttpError::new(
294                400,
295                format!("Invalid WindowUpdate frame length: {}", payload.len()).as_str(),
296            ));
297        }
298        Ok(())
299    }
300    /// 读取资源文件
301    /// 包含路径遍历保护:确保请求路径不会逃逸根目录
302    fn read_resource(&mut self) -> io::Result<PathBuf> {
303        // 安全检查:防止路径遍历攻击
304        let sanitized_path = self.request.uri.path.trim_start_matches('/');
305        if sanitized_path.contains("..") {
306            return Err(Error::other(
307                "Invalid path: directory traversal not allowed",
308            ));
309        }
310
311        if self.request.uri.path != "/" {
312            let base_dir = self
313                .request
314                .config
315                .root_path
316                .join(self.request.config.public.clone());
317            let file = base_dir.join(sanitized_path);
318            // 验证规范化路径仍在基础目录内
319            if let (Ok(canonical_base), Ok(canonical_file)) =
320                (base_dir.canonicalize(), file.canonicalize())
321            {
322                if canonical_file.starts_with(&canonical_base) && file.is_file() {
323                    return Ok(file);
324                }
325            }
326        }
327        if self.request.uri.path == "/" {
328            let file = self
329                .request
330                .config
331                .root_path
332                .join("webpage")
333                .join(self.request.config.webpage.clone())
334                .join("index.html");
335            if file.is_file() {
336                return Ok(file);
337            }
338        } else {
339            let base_dir = self
340                .request
341                .config
342                .root_path
343                .join("webpage")
344                .join(self.request.config.webpage.clone());
345            let file = base_dir.join(sanitized_path);
346            // 验证规范化路径仍在基础目录内
347            if let (Ok(canonical_base), Ok(canonical_file)) =
348                (base_dir.canonicalize(), file.canonicalize())
349            {
350                if canonical_file.starts_with(&canonical_base) && file.is_file() {
351                    return Ok(file);
352                }
353            }
354        }
355        Err(Error::other("Not a file"))
356    }
357    pub fn status(&mut self, code: u16) -> &mut Self {
358        self.status.set_code(code);
359        self
360    }
361    /// 跳转
362    pub fn location(&mut self, uri: &str) -> &mut Self {
363        self.header("Location", uri);
364        self
365    }
366    /// 设置 HOST
367    pub fn set_host(&mut self, host: &str) -> &mut Self {
368        self.header("Host", host);
369        self
370    }
371
372    /// 清理 header 值,防止 CRLF 注入
373    fn sanitize_header_value(value: &str) -> String {
374        sanitize_header_value(value)
375    }
376
377    fn ensure_default_http_headers(&mut self) {
378        self.header("Date", &self.get_date(0));
379
380        if !self.headers.has_key("X-Content-Type-Options") {
381            self.header("X-Content-Type-Options", "nosniff");
382        }
383        if !self.headers.has_key("X-Frame-Options") {
384            self.header("X-Frame-Options", "SAMEORIGIN");
385        }
386        if !self.headers.has_key("X-XSS-Protection") {
387            self.header("X-XSS-Protection", "1; mode=block");
388        }
389    }
390
391    fn build_http1_header_lines(&self) -> Vec<String> {
392        let mut header = vec![format!(
393            "{} {} {}",
394            self.request.protocol.str(),
395            self.status.code,
396            self.status.reason
397        )];
398        for (key, value) in self.headers.entries() {
399            header.push(format!("{key}: {value}"));
400        }
401
402        for (key, value) in self.cookies.entries() {
403            header.push(format!(
404                "Set-Cookie: {key}={value}; Path=/; HttpOnly; SameSite=Lax"
405            ));
406        }
407        header
408    }
409
410    pub fn stream_start(&mut self, content_type: &str) -> Result<(), HttpError> {
411        if self.stream_started {
412            return Ok(());
413        }
414        if !content_type.is_empty() && !self.headers.has_key("Content-Type") {
415            self.header("Content-Type", content_type);
416        }
417        if !self.headers.has_key("Cache-Control") {
418            self.header("Cache-Control", "no-cache");
419        }
420        if !self.headers.has_key("X-Accel-Buffering") {
421            self.header("X-Accel-Buffering", "no");
422        }
423        self.headers.remove("Content-Length");
424        self.headers.remove("content-length");
425        self.ensure_default_http_headers();
426
427        match self.request.protocol {
428            Protocol::HTTP1_0 | Protocol::HTTP1_1 => {
429                self.header("Transfer-Encoding", "chunked");
430                let header = format!("{}\r\n\r\n", self.build_http1_header_lines().join("\r\n"));
431                self.request
432                    .scheme
433                    .lock()
434                    .map_err(|e| HttpError::new(500, &format!("lock: {}", e)))?
435                    .write_all(header.as_bytes())?;
436            }
437            Protocol::HTTP2 => {
438                self.stream_id += 1;
439                let frames = self.http2_stream_headers(self.stream_id, 16_384);
440                let mut writer = self
441                    .request
442                    .scheme
443                    .lock()
444                    .map_err(|e| HttpError::new(500, &format!("lock: {}", e)))?;
445                for frame in frames {
446                    writer.write_all(&frame)?;
447                }
448            }
449            Protocol::HTTP3 | Protocol::Other(_) => {
450                return Err(HttpError::new(500, "当前协议暂不支持流式输出"));
451            }
452        }
453
454        self.committed = true;
455        self.stream_started = true;
456        self.stream_finished = false;
457        Ok(())
458    }
459
460    pub fn stream_chunk(&mut self, data: &[u8]) -> Result<(), HttpError> {
461        if !self.stream_started {
462            return Err(HttpError::new(500, "流式响应尚未开始"));
463        }
464        if self.stream_finished || data.is_empty() {
465            return Ok(());
466        }
467
468        match self.request.protocol {
469            Protocol::HTTP1_0 | Protocol::HTTP1_1 => {
470                let mut chunk = format!("{:X}\r\n", data.len()).into_bytes();
471                chunk.extend_from_slice(data);
472                chunk.extend_from_slice(b"\r\n");
473                self.request
474                    .scheme
475                    .lock()
476                    .map_err(|e| HttpError::new(500, &format!("lock: {}", e)))?
477                    .write_all(&chunk)?;
478            }
479            Protocol::HTTP2 => {
480                let frame = self.build_data_frame(self.stream_id, data, false);
481                self.request
482                    .scheme
483                    .lock()
484                    .map_err(|e| HttpError::new(500, &format!("lock: {}", e)))?
485                    .write_all(&frame)?;
486            }
487            Protocol::HTTP3 | Protocol::Other(_) => {
488                return Err(HttpError::new(500, "当前协议暂不支持流式输出"));
489            }
490        }
491        Ok(())
492    }
493
494    pub fn stream_end(&mut self) -> Result<(), HttpError> {
495        if !self.stream_started || self.stream_finished {
496            return Ok(());
497        }
498        match self.request.protocol {
499            Protocol::HTTP1_0 | Protocol::HTTP1_1 => {
500                self.request
501                    .scheme
502                    .lock()
503                    .map_err(|e| HttpError::new(500, &format!("lock: {}", e)))?
504                    .write_all(b"0\r\n\r\n")?;
505            }
506            Protocol::HTTP2 => {
507                let frame = self.build_data_frame(self.stream_id, &[], true);
508                self.request
509                    .scheme
510                    .lock()
511                    .map_err(|e| HttpError::new(500, &format!("lock: {}", e)))?
512                    .write_all(&frame)?;
513            }
514            Protocol::HTTP3 | Protocol::Other(_) => {
515                return Err(HttpError::new(500, "当前协议暂不支持流式输出"));
516            }
517        }
518        self.stream_finished = true;
519        Ok(())
520    }
521
522    pub fn header(&mut self, key: &str, value: &str) -> &mut Self {
523        self.headers[key] = Self::sanitize_header_value(value).into();
524        self
525    }
526    pub fn cookie(&mut self, key: &str, value: &str) -> &mut Self {
527        self.cookies[key] = value.into();
528        self
529    }
530    pub fn cookie_with_options(&mut self, options: CookieOptions) -> &mut Self {
531        self.cookies[options.name.as_str()] = options.to_header_value().into();
532        self
533    }
534    fn get_date(&self, s: i64) -> String {
535        let utc: DateTime<Utc> = Utc::now();
536        let future = utc + dur::seconds(s); // 加 3600 秒 = 1 小时
537        future.format("%a, %d %b %Y %H:%M:%S GMT").to_string()
538    }
539    /// HTML 返回
540    pub fn html(&mut self, value: &str) -> &mut Self {
541        if self.request.config.charset.is_empty() {
542            self.header(
543                "Content-Type",
544                format!("{};", Extension::form("html").as_str()).as_str(),
545            );
546        } else {
547            self.header(
548                "Content-Type",
549                format!(
550                    "{}; charset={}",
551                    Extension::form("html").as_str(),
552                    self.request.config.charset
553                )
554                .as_str(),
555            );
556        }
557        self.content_type = ContentType::Html;
558        self.body = value.as_bytes().to_vec();
559        self
560    }
561    /// TXT 返回
562    pub fn txt(&mut self, value: &str) -> &mut Self {
563        if self.request.config.charset.is_empty() {
564            self.header(
565                "Content-Type",
566                Extension::form("txt").as_str().to_string().as_str(),
567            );
568        } else {
569            self.header(
570                "Content-Type",
571                format!(
572                    "{}; charset={}",
573                    Extension::form("txt").as_str(),
574                    self.request.config.charset
575                )
576                .as_str(),
577            );
578        }
579        self.content_type = ContentType::Text;
580        self.body = value.as_bytes().to_vec();
581        self
582    }
583    /// JSON 返回
584    pub fn json(&mut self, value: JsonValue) -> &mut Self {
585        if self.request.config.charset.is_empty() {
586            self.header(
587                "Content-Type",
588                Extension::form("json").as_str().to_string().as_str(),
589            );
590        } else {
591            self.header(
592                "Content-Type",
593                format!(
594                    "{}; charset={}",
595                    Extension::form("json").as_str(),
596                    self.request.config.charset
597                )
598                .as_str(),
599            );
600        }
601        self.content_type = ContentType::Json;
602        self.body = value.to_string().into_bytes();
603        self
604    }
605    /// 下载 返回
606    pub fn download(&mut self, filename: &Path) -> &mut Self {
607        let Ok(file) = fs::read(filename) else {
608            self.status(404);
609            return self;
610        };
611        let extension = filename
612            .extension()
613            .and_then(|e| e.to_str())
614            .unwrap_or("")
615            .to_lowercase();
616
617        if self.request.config.charset.is_empty() {
618            self.header(
619                "Content-Type",
620                Extension::form(extension.as_str())
621                    .as_str()
622                    .to_string()
623                    .as_str(),
624            );
625        } else {
626            self.header(
627                "Content-Type",
628                format!(
629                    "{}; charset={}",
630                    Extension::form(extension.as_str()).as_str(),
631                    self.request.config.charset
632                )
633                .as_str(),
634            );
635        }
636
637        let encoded_file_name = br_crypto::encoding::urlencoding_encode(
638            filename
639                .file_name()
640                .and_then(|n| n.to_str())
641                .unwrap_or("download"),
642        );
643        self.header(
644            "Content-Disposition",
645            format!(r"attachment; filename={encoded_file_name}").as_str(),
646        );
647        self.header("Cache-Control", "no-cache");
648        self.header("ETag", br_crypto::md5::encrypt_hex(&file).as_str());
649        self.body = file;
650        self
651    }
652    /// 分片
653    pub fn range(&mut self, filename: &Path) -> &mut Self {
654        let Ok(file) = fs::read(filename) else {
655            self.status(404);
656            return self;
657        };
658        let range = self.request.header["range"].to_string();
659        let range = range.trim_start_matches("bytes=");
660        let parts: Vec<&str> = range.split('-').collect();
661
662        let range_start = match parts.first().and_then(|s| s.parse::<usize>().ok()) {
663            Some(v) => v,
664            None => {
665                self.status(416);
666                self.header("Content-Range", format!("bytes */{}", file.len()).as_str());
667                return self;
668            }
669        };
670
671        let range_end = if parts.len() > 1 && !parts[1].is_empty() {
672            match parts[1].parse::<usize>() {
673                Ok(v) => v,
674                Err(_) => {
675                    self.status(416);
676                    self.header("Content-Range", format!("bytes */{}", file.len()).as_str());
677                    return self;
678                }
679            }
680        } else {
681            file.len().saturating_sub(1)
682        };
683
684        if file.len() < range_end {
685            self.status(416);
686            self.header("Content-Range", format!("bytes */{}", file.len()).as_str());
687            return self;
688        }
689
690        let extension = filename
691            .extension()
692            .and_then(|e| e.to_str())
693            .unwrap_or("")
694            .to_lowercase();
695
696        if self.request.config.charset.is_empty() {
697            self.header(
698                "Content-Type",
699                Extension::form(extension.as_str())
700                    .as_str()
701                    .to_string()
702                    .as_str(),
703            );
704        } else {
705            self.header(
706                "Content-Type",
707                format!(
708                    "{}; charset={}",
709                    Extension::form(extension.as_str()).as_str(),
710                    self.request.config.charset
711                )
712                .as_str(),
713            );
714        }
715
716        self.header("Accept-Ranges", "bytes");
717        self.header(
718            "content-length",
719            (range_end - range_start + 1).to_string().as_str(),
720        );
721        self.header(
722            "Content-Range",
723            format!("bytes {}-{}/{}", range_start, range_end, file.len()).as_str(),
724        );
725        self.body = file[range_start..=range_end].to_vec();
726        self
727    }
728    /// Serves a file for inline display in the browser.
729    ///
730    /// # 文件返回
731    ///
732    /// This function will panic if the file extension cannot be converted to a string,
733    /// or if the filename cannot be converted to a valid UTF-8 string.
734    pub fn file(&mut self, filename: &Path) -> &mut Self {
735        let Ok(file) = fs::read(filename) else {
736            self.status(404);
737            return self;
738        };
739
740        self.header("Access-Control-Expose-Headers", "Content-Disposition");
741        let extension = match filename.extension() {
742            None => String::new(),
743            Some(e) => e.to_str().unwrap_or("").to_lowercase(),
744        };
745        if self.request.config.charset.is_empty() {
746            self.header(
747                "Content-Type",
748                Extension::form(extension.as_str())
749                    .as_str()
750                    .to_string()
751                    .as_str(),
752            );
753        } else {
754            self.header(
755                "Content-Type",
756                format!(
757                    "{}; charset={}",
758                    Extension::form(extension.as_str()).as_str(),
759                    self.request.config.charset
760                )
761                .as_str(),
762            );
763        }
764
765        self.header(
766            "Content-Disposition",
767            format!(
768                r#"inline; filename="{}""#,
769                filename
770                    .file_name()
771                    .and_then(|n| n.to_str())
772                    .unwrap_or("download")
773            )
774            .as_str(),
775        );
776
777        self.header("Accept-Ranges", "bytes");
778
779        self.header(
780            "Cache-Control",
781            format!("public, max-age={}", DEFAULT_CACHE_MAX_AGE).as_str(),
782        );
783        self.header("Expires", &self.get_date(DEFAULT_CACHE_MAX_AGE as i64));
784        self.body = file;
785        self
786    }
787    /// Sends the response over the given scheme.
788    ///
789    /// # Errors
790    ///
791    /// Returns an error if writing the response over the scheme fails.
792    pub fn send(&mut self) -> Result<(), HttpError> {
793        match &self.request.protocol {
794            Protocol::HTTP1_0 | Protocol::HTTP1_1 => Ok(self.send_http1()?),
795            Protocol::HTTP2 => Ok(self.send_http2()?),
796            Protocol::HTTP3 => {
797                error!("Other1:{:?} {:?}", thread::current().id(), self.request);
798                Err(HttpError::new(500, "暂未实现HTTP3"))
799            }
800            Protocol::Other(e) => {
801                error!("Other:{:?} {:?}", thread::current().id(), self.request);
802                Err(HttpError::new(
803                    500,
804                    format!(
805                        "暂未实现Other: {} {} {:?}",
806                        e,
807                        self.request.uri.path,
808                        thread::current().id()
809                    )
810                    .as_str(),
811                ))
812            }
813        }
814    }
815    fn send_http1(&mut self) -> Result<(), HttpError> {
816        let mut header = vec![];
817        header.push(format!(
818            "{} {} {}",
819            self.request.protocol.str(),
820            self.status.code,
821            self.status.reason
822        ));
823        self.ensure_default_http_headers();
824
825        match self.request.method {
826            Method::HEAD => {
827                self.header("Content-Length", self.body.len().to_string().as_str());
828                self.body = vec![];
829            }
830            Method::OPTIONS => {
831                self.body = vec![];
832            }
833            _ => {
834                if self.status.code == 101 {
835                    // WebSocket 升级响应不需要 Content-Length
836                } else {
837                    match self.request.accept_encoding {
838                        Encoding::Gzip => {
839                            self.header(
840                                "Content-Encoding",
841                                self.request.accept_encoding.clone().str(),
842                            );
843                            if let Ok(e) = self.request.accept_encoding.compress(&self.body) {
844                                self.body = e
845                            };
846                            self.header("Content-Length", self.body.len().to_string().as_str());
847                        }
848                        _ => {
849                            self.header("Content-Length", self.body.len().to_string().as_str());
850                        }
851                    }
852                }
853            }
854        };
855
856        for (key, value) in self.headers.entries() {
857            header.push(format!("{key}: {value}"));
858        }
859
860        for (key, value) in self.cookies.entries() {
861            header.push(format!(
862                "Set-Cookie: {key}={value}; Path=/; HttpOnly; SameSite=Lax"
863            ));
864        }
865
866        if self.request.config.debug {
867            info!("\r\n=================响应信息 {:?}=================\r\n{}\r\n===========================================",thread::current().id(),header.join("\r\n"));
868            match self.request.accept_encoding {
869                Encoding::Gzip => {}
870                _ => {
871                    match self.content_type {
872                        ContentType::Text
873                        | ContentType::Html
874                        | ContentType::Json
875                        | ContentType::FormUrlencoded => {
876                            info!("\r\n=================响应体 {:?}=================\r\n{}\r\n===========================================",thread::current().id(),String::from_utf8_lossy(self.body.as_slice()));
877                        }
878                        _ => {}
879                    };
880                }
881            }
882        }
883        let mut headers = format!("{}\r\n\r\n", header.join("\r\n")).into_bytes();
884        headers.extend(self.body.clone());
885        self.request
886            .scheme
887            .lock()
888            .map_err(|e| HttpError::new(500, &format!("lock: {}", e)))?
889            .write_all(headers.as_slice())?;
890        Ok(())
891    }
892    fn send_http2(&mut self) -> Result<(), HttpError> {
893        let max_frame_size: usize = 16_384;
894        self.stream_id += 1;
895        // 先构建所有帧,避免持锁期间借用 self
896        let header_frames = self.http2_header(self.stream_id, max_frame_size);
897        let data_frames = self.http2_body(self.stream_id, true, max_frame_size);
898
899        // 仅锁一次写端,顺序写出所有帧
900        let mut writer = self
901            .request
902            .scheme
903            .lock()
904            .map_err(|e| HttpError::new(500, &format!("lock: {}", e)))?;
905        for f in header_frames.clone() {
906            writer.write_all(&f)?;
907        }
908        for f in data_frames.clone() {
909            writer.write_all(&f)?;
910        }
911        Ok(())
912    }
913
914    fn http2_header(&mut self, stream_id: u32, max_frame_size: usize) -> Vec<Vec<u8>> {
915        let mut headers: Vec<(Vec<u8>, Vec<u8>)> = vec![
916            (
917                b":status".to_vec(),
918                self.status.code.to_string().into_bytes(),
919            ),
920            (b"date".to_vec(), self.get_date(0).into_bytes()),
921        ];
922
923        match self.request.method {
924            Method::HEAD => {
925                self.header("content-length", self.body.len().to_string().as_str());
926                self.body.clear(); // HEAD 响应不携带实体
927            }
928            Method::OPTIONS => {
929                self.body.clear();
930                self.header("content-length", "0");
931            }
932            _ => {
933                self.header("content-length", self.body.len().to_string().as_str());
934            }
935        }
936
937        headers.extend(self.headers.entries().map(|(k, v)| {
938            (
939                k.to_string().to_lowercase().into_bytes(),
940                v.to_string().into_bytes(),
941            )
942        }));
943        headers.extend(self.cookies.entries().map(|(k, v)| {
944            (
945                b"set-cookie".to_vec(),
946                format!("{k}={v}; Path=/; HttpOnly; SameSite=Lax").into_bytes(),
947            )
948        }));
949
950        if self.request.config.debug {
951            let dbg = headers
952                .iter()
953                .map(|(n, v)| {
954                    format!(
955                        "{}: {}",
956                        String::from_utf8_lossy(n),
957                        String::from_utf8_lossy(v)
958                    )
959                })
960                .collect::<Vec<_>>()
961                .join("\r\n");
962            info!("\n=================响应信息 {:?}=================\n{}\n===========================================",
963              std::thread::current().id(), dbg);
964        }
965
966        let mut encoder = Encoder::new();
967        // 2) HPACK 编码
968        let block = encoder.encode(headers.iter().map(|h| (&h.0[..], &h.1[..])));
969
970        let end_stream = self.body.is_empty();
971        let mut frames = Vec::new();
972        let mut remaining = block.as_slice();
973        let mut first = true;
974
975        while !remaining.is_empty() {
976            let take = remaining.len().min(max_frame_size);
977            let (chunk, rest) = remaining.split_at(take);
978            remaining = rest;
979
980            let is_last = remaining.is_empty();
981            let mut flags = 0u8;
982            if is_last {
983                flags |= FLAG_END_HEADERS;
984            }
985            if is_last && end_stream {
986                flags |= FLAG_END_STREAM;
987            }
988
989            // 9字节帧头
990            let mut f = Vec::with_capacity(9 + chunk.len());
991            let len = chunk.len();
992            f.push(((len >> 16) & 0xFF) as u8);
993            f.push(((len >> 8) & 0xFF) as u8);
994            f.push((len & 0xFF) as u8);
995            f.push(if first { 0x01 } else { 0x09 }); // HEADERS / CONTINUATION
996            f.push(flags);
997            f.extend_from_slice(&(stream_id & 0x7FFF_FFFF).to_be_bytes());
998            f.extend_from_slice(chunk);
999
1000            frames.push(f);
1001            first = false;
1002        }
1003
1004        // 如果 block 为空(极少见),也要至少发一个空 HEADERS(END_HEADERS [+END_STREAM])
1005        if frames.is_empty() {
1006            let mut f = vec![
1007                0,
1008                0,
1009                0,
1010                0x01,
1011                FLAG_END_HEADERS | if end_stream { FLAG_END_STREAM } else { 0 },
1012                0,
1013                0,
1014                0,
1015                0,
1016            ];
1017            f[5..9].copy_from_slice(&(stream_id & 0x7FFF_FFFF).to_be_bytes());
1018            frames.push(f);
1019        }
1020
1021        frames
1022    }
1023    fn http2_body(
1024        &mut self,
1025        stream_id: u32,
1026        end_stream: bool,
1027        max_frame_size: usize,
1028    ) -> Vec<Vec<u8>> {
1029        if self.body.is_empty() {
1030            return Vec::new();
1031        }
1032        let mut frames = Vec::new();
1033        let mut off = 0usize;
1034        let total = self.body.len();
1035
1036        while off < total {
1037            let take = (total - off).min(max_frame_size);
1038            let chunk = &self.body[off..off + take];
1039            off += take;
1040
1041            let last = off == total;
1042            frames.push(self.build_data_frame(stream_id, chunk, last && end_stream));
1043        }
1044        frames
1045    }
1046    fn http2_stream_headers(&mut self, stream_id: u32, max_frame_size: usize) -> Vec<Vec<u8>> {
1047        let mut headers: Vec<(Vec<u8>, Vec<u8>)> = vec![
1048            (
1049                b":status".to_vec(),
1050                self.status.code.to_string().into_bytes(),
1051            ),
1052            (b"date".to_vec(), self.get_date(0).into_bytes()),
1053        ];
1054
1055        headers.extend(self.headers.entries().filter_map(|(k, v)| {
1056            let key = k.to_string().to_lowercase();
1057            if key == "content-length" {
1058                return None;
1059            }
1060            Some((key.into_bytes(), v.to_string().into_bytes()))
1061        }));
1062        headers.extend(self.cookies.entries().map(|(k, v)| {
1063            (
1064                b"set-cookie".to_vec(),
1065                format!("{k}={v}; Path=/; HttpOnly; SameSite=Lax").into_bytes(),
1066            )
1067        }));
1068
1069        let mut encoder = Encoder::new();
1070        let block = encoder.encode(headers.iter().map(|h| (&h.0[..], &h.1[..])));
1071
1072        let mut frames = Vec::new();
1073        let mut remaining = block.as_slice();
1074        let mut first = true;
1075
1076        while !remaining.is_empty() {
1077            let take = remaining.len().min(max_frame_size);
1078            let (chunk, rest) = remaining.split_at(take);
1079            remaining = rest;
1080
1081            let is_last = remaining.is_empty();
1082            let mut flags = 0u8;
1083            if is_last {
1084                flags |= FLAG_END_HEADERS;
1085            }
1086
1087            let mut frame = Vec::with_capacity(9 + chunk.len());
1088            let len = chunk.len();
1089            frame.push(((len >> 16) & 0xFF) as u8);
1090            frame.push(((len >> 8) & 0xFF) as u8);
1091            frame.push((len & 0xFF) as u8);
1092            frame.push(if first { 0x01 } else { 0x09 });
1093            frame.push(flags);
1094            frame.extend_from_slice(&(stream_id & 0x7FFF_FFFF).to_be_bytes());
1095            frame.extend_from_slice(chunk);
1096            frames.push(frame);
1097            first = false;
1098        }
1099
1100        if frames.is_empty() {
1101            let mut frame = vec![0, 0, 0, 0x01, FLAG_END_HEADERS, 0, 0, 0, 0];
1102            frame[5..9].copy_from_slice(&(stream_id & 0x7FFF_FFFF).to_be_bytes());
1103            frames.push(frame);
1104        }
1105
1106        frames
1107    }
1108    fn build_data_frame(&self, stream_id: u32, payload: &[u8], end_stream: bool) -> Vec<u8> {
1109        let len = payload.len();
1110        let mut f = Vec::with_capacity(9 + len);
1111        f.push(((len >> 16) & 0xFF) as u8);
1112        f.push(((len >> 8) & 0xFF) as u8);
1113        f.push((len & 0xFF) as u8);
1114        f.push(0x00); // DATA
1115        f.push(if end_stream { FLAG_END_STREAM } else { 0 });
1116        f.extend_from_slice(&(stream_id & 0x7FFF_FFFF).to_be_bytes());
1117        if !payload.is_empty() {
1118            f.extend_from_slice(payload);
1119        }
1120        f
1121    }
1122    fn on_options(&mut self) -> Result<(), HttpError> {
1123        if self.allow_origins.is_empty() {
1124            self.header("Access-Control-Allow-Origin", "*");
1125        } else if self.request.header.has_key("origin") {
1126            if self.allow_origins.contains(&self.request.origin.as_str()) {
1127                self.header(
1128                    "Access-Control-Allow-Origin",
1129                    self.request.origin.to_string().as_str(),
1130                );
1131            } else {
1132                return Err(HttpError::new(403, "Origin not allowed"));
1133            }
1134        } else {
1135            return Err(HttpError::new(403, "Origin not allowed"));
1136        }
1137
1138        if self.allow_headers.is_empty() {
1139            if !self
1140                .request
1141                .header
1142                .has_key("access-control-request-headers")
1143            {
1144                return Err(HttpError::new(403, "headers not allowed"));
1145            }
1146            self.header(
1147                "Access-Control-Allow-Headers",
1148                self.request.header["access-control-request-headers"]
1149                    .to_string()
1150                    .as_str(),
1151            );
1152        } else if !self
1153            .request
1154            .header
1155            .has_key("access-control-request-headers")
1156        {
1157            let headers = self.allow_headers.join(",");
1158            self.header("Access-Control-Allow-Headers", headers.to_string().as_str());
1159        } else {
1160            let headers = self.allow_headers.join(",");
1161            self.header(
1162                "Access-Control-Allow-Headers",
1163                format!(
1164                    "{},{}",
1165                    self.request.header["access-control-request-headers"], headers
1166                )
1167                .as_str(),
1168            );
1169        }
1170
1171        if self.allow_methods.is_empty() {
1172            if !self.request.header.has_key("access-control-request-method") {
1173                return Err(HttpError::new(403, "methods not allowed"));
1174            }
1175            self.header(
1176                "Access-Control-Allow-Methods",
1177                self.request.header["access-control-request-method"]
1178                    .to_string()
1179                    .as_str(),
1180            );
1181        } else {
1182            let methods = self.allow_methods.join(",");
1183            self.header("Access-Control-Allow-Methods", methods.to_string().as_str());
1184        }
1185        self.header(
1186            "Vary",
1187            "Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
1188        );
1189        Ok(())
1190    }
1191}
1192
1193/// 文件类型
1194enum Extension {}
1195impl Extension {
1196    pub fn form(extension: &str) -> String {
1197        match extension.to_lowercase().as_str() {
1198            "html" | "htm" => "text/html",
1199            "css" => "text/css",
1200            "js" | "mjs" => "application/javascript",
1201            "json" => "application/json",
1202            "xml" => "application/xml",
1203            "txt" => "text/plain",
1204            "csv" => "text/csv",
1205            "md" => "text/markdown",
1206
1207            "png" => "image/png",
1208            "jpg" | "jpeg" => "image/jpeg",
1209            "gif" => "image/gif",
1210            "svg" => "image/svg+xml",
1211            "webp" => "image/webp",
1212            "ico" => "image/x-icon",
1213            "bmp" => "image/bmp",
1214            "tiff" | "tif" => "image/tiff",
1215            "avif" => "image/avif",
1216
1217            "mp4" => "video/mp4",
1218            "webm" => "video/webm",
1219            "avi" => "video/x-msvideo",
1220            "mov" => "video/quicktime",
1221            "mkv" => "video/x-matroska",
1222
1223            "mp3" => "audio/mpeg",
1224            "wav" => "audio/wav",
1225            "ogg" => "audio/ogg",
1226            "flac" => "audio/flac",
1227            "aac" => "audio/aac",
1228
1229            "woff" => "font/woff",
1230            "woff2" => "font/woff2",
1231            "ttf" => "font/ttf",
1232            "otf" => "font/otf",
1233            "eot" => "application/vnd.ms-fontobject",
1234
1235            "pdf" => "application/pdf",
1236            "doc" => "application/msword",
1237            "docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
1238            "xls" => "application/vnd.ms-excel",
1239            "xlsx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
1240            "ppt" => "application/vnd.ms-powerpoint",
1241            "pptx" => "application/vnd.openxmlformats-officedocument.presentationml.presentation",
1242
1243            "zip" => "application/zip",
1244            "rar" => "application/vnd.rar",
1245            "7z" => "application/x-7z-compressed",
1246            "tar" => "application/x-tar",
1247            "gz" => "application/gzip",
1248
1249            "wasm" => "application/wasm",
1250            "map" => "application/json",
1251            _ => "application/octet-stream",
1252        }
1253        .to_string()
1254    }
1255}
1256
1257#[derive(Clone, Debug)]
1258pub struct CookieOptions {
1259    pub name: String,
1260    pub value: String,
1261    pub path: Option<String>,
1262    pub domain: Option<String>,
1263    pub max_age: Option<i64>,
1264    pub expires: Option<String>,
1265    pub secure: bool,
1266    pub http_only: bool,
1267    pub same_site: SameSite,
1268}
1269
1270impl Default for CookieOptions {
1271    fn default() -> Self {
1272        Self {
1273            name: String::new(),
1274            value: String::new(),
1275            path: None,
1276            domain: None,
1277            max_age: None,
1278            expires: None,
1279            secure: true,
1280            http_only: false,
1281            same_site: SameSite::default(),
1282        }
1283    }
1284}
1285
1286#[derive(Clone, Debug, Default)]
1287pub enum SameSite {
1288    Strict,
1289    #[default]
1290    Lax,
1291    None,
1292}
1293
1294impl CookieOptions {
1295    #[must_use]
1296    pub fn new(name: &str, value: &str) -> Self {
1297        Self {
1298            name: name.to_string(),
1299            value: value.to_string(),
1300            path: Some("/".to_string()),
1301            http_only: true,
1302            same_site: SameSite::Lax,
1303            ..Default::default()
1304        }
1305    }
1306
1307    pub fn path(mut self, path: &str) -> Self {
1308        self.path = Some(path.to_string());
1309        self
1310    }
1311
1312    pub fn domain(mut self, domain: &str) -> Self {
1313        self.domain = Some(domain.to_string());
1314        self
1315    }
1316
1317    pub fn max_age(mut self, seconds: i64) -> Self {
1318        self.max_age = Some(seconds);
1319        self
1320    }
1321
1322    pub fn expires(mut self, date: &str) -> Self {
1323        self.expires = Some(date.to_string());
1324        self
1325    }
1326
1327    pub fn secure(mut self, secure: bool) -> Self {
1328        self.secure = secure;
1329        self
1330    }
1331
1332    pub fn http_only(mut self, http_only: bool) -> Self {
1333        self.http_only = http_only;
1334        self
1335    }
1336
1337    pub fn same_site(mut self, same_site: SameSite) -> Self {
1338        self.same_site = same_site;
1339        self
1340    }
1341
1342    #[must_use]
1343    pub fn to_header_value(&self) -> String {
1344        let mut parts = vec![format!(
1345            "{}={}",
1346            sanitize_header_value(&self.name),
1347            sanitize_header_value(&self.value)
1348        )];
1349
1350        if let Some(ref path) = self.path {
1351            parts.push(format!("Path={path}"));
1352        }
1353        if let Some(ref domain) = self.domain {
1354            parts.push(format!("Domain={domain}"));
1355        }
1356        if let Some(max_age) = self.max_age {
1357            parts.push(format!("Max-Age={max_age}"));
1358        }
1359        if let Some(ref expires) = self.expires {
1360            parts.push(format!("Expires={expires}"));
1361        }
1362        if self.secure {
1363            parts.push("Secure".to_string());
1364        }
1365        if self.http_only {
1366            parts.push("HttpOnly".to_string());
1367        }
1368        match self.same_site {
1369            SameSite::Strict => parts.push("SameSite=Strict".to_string()),
1370            SameSite::Lax => parts.push("SameSite=Lax".to_string()),
1371            SameSite::None => parts.push("SameSite=None".to_string()),
1372        }
1373
1374        parts.join("; ")
1375    }
1376}