1use std::cell::RefCell;
2use std::collections::HashMap;
3use std::fs::OpenOptions;
4use std::io::Read;
5use std::net::TcpStream;
6
7use multimap::MultiMap;
8
9use std::sync::Arc;
10
11use std::ops::Range;
12
13use std::rc::Rc;
14
15use std::ffi::OsStr;
16use std::io;
17use std::io::prelude::*;
18
19pub use tera::{Context, Tera};
20
21pub mod mime;
22
23use hmac::Hmac;
24use sha2::Sha256;
25
26use crate::cookie::Cookie;
27
28use serde_json::Value;
29use std::collections::BTreeMap;
30
31pub mod http_response_table {
32 const STATE_TABLE: [(u16, &str); 20] = [
33 (101, "101 Switching Protocals\r\n"),
34 (200, "200 OK\r\n"),
35 (201, "201 Created\r\n"),
36 (202, "202 Accepted\r\n"),
37 (204, "204 No Content\r\n"),
38 (206, "206 Partial Content\r\n"),
39 (300, "300 Multiple Choices\r\n"),
40 (301, "301 Moved Permanently\r\n"),
41 (302, "302 Moved Temporarily\r\n"),
42 (304, "304 Not Modified\r\n"),
43 (400, "400 Bad Request\r\n"),
44 (401, "401 Unauthorized\r\n"),
45 (403, "403 Forbidden\r\n"),
46 (404, "404 Not Found\r\n"),
47 (413, "413 Request Entity Too Large\r\n"),
48 (416, "416 Requested Range Not Satisfiable\r\n"),
49 (500, "500 Internal Server Error\r\n"),
50 (501, "501 Not Implemented\r\n"),
51 (502, "502 Bad Gateway\r\n"),
52 (503, "503 Service Unavailable\r\n"),
53 ];
54
55 pub(super) fn get_httpstatus_from_code(code: u16) -> &'static str {
56 match STATE_TABLE.binary_search_by_key(&code, |&(k, _)| k) {
57 Ok(index) => STATE_TABLE[index].1,
58 Err(_) => panic!("not supporting such a http state code"),
59 }
60 }
61
62 const HTTP_METHODS: [(u8, &str); 9] = [
63 (0, "GET"),
64 (1, "POST"),
65 (2, "OPTIONS"),
66 (3, "DELETE"),
67 (4, "HEAD"),
68 (5, "PUT"),
69 (6, "PATCH"),
70 (7, "CONNECT"),
71 (8, "TRACE"),
72 ];
73 pub const GET: u8 = 0;
75 pub const POST: u8 = 1;
77 pub const OPTIONS: u8 = 2;
79 pub const DELETE: u8 = 3;
81 pub const HEAD: u8 = 4;
83 pub const PUT: u8 = 5;
85 pub const PATCH: u8 = 6;
87 pub const CONNECT: u8 = 7;
89 pub const TRACE: u8 = 8;
91 pub fn get_httpmethod_from_code(code: u8) -> &'static str {
92 match HTTP_METHODS.binary_search_by_key(&code, |&(k, _)| k) {
93 Ok(index) => HTTP_METHODS[index].1,
94 Err(_) => panic!("not supporting such a http state code"),
95 }
96 }
97}
98pub struct Request<'a> {
99 pub(super) header_pair: HashMap<&'a str, &'a str>,
100 pub(super) url: &'a str,
101 pub(super) method: &'a str,
102 pub(super) version: &'a str,
103 pub(super) body: BodyContent<'a>,
104 pub(super) conn_: Rc<RefCell<&'a mut TcpStream>>,
105 pub(super) secret_key: Arc<Hmac<Sha256>>,
106 pub(super) ctx: RefCell<BTreeMap<String, Value>>,
107}
108
109impl<'a> Request<'a> {
110 pub fn get_header(&self, key: &str) -> Option<&str> {
114 let r = self.header_pair.keys().find(|&&ik| {
115 if ik.to_lowercase() == key.to_lowercase() {
116 true
117 } else {
118 false
119 }
120 });
121 match r {
122 Some(r) => {
123 return Some(self.header_pair.get(*r).unwrap()); }
125 None => {
126 return None;
127 }
128 }
129 }
130
131 pub fn get_param(&self, k: &str) -> Option<&str> {
136 match self.url.split_once("?") {
137 Some((_, v)) => {
138 let r = v.split("&");
139 for e in r {
140 match e.split_once("=") {
141 Some((ik, iv)) => {
142 if ik == k {
143 return Some(iv);
144 }
145 }
146 None => {}
147 }
148 }
149 None
150 }
151 None => None,
152 }
153 }
154
155 pub fn get_params(&self) -> Option<HashMap<&str, &str>> {
160 match self.url.split_once("?") {
161 Some((_, v)) => {
162 let r = v.split("&");
163 let mut map = HashMap::new();
164 for e in r {
165 match e.split_once("=") {
166 Some((ik, iv)) => {
167 map.insert(ik, iv);
168 }
169 None => {}
170 }
171 }
172 if map.len() == 0 {
173 None
174 } else {
175 Some(map)
176 }
177 }
178 None => None,
179 }
180 }
181
182 pub fn get_headers(&self) -> HashMap<&str, &str> {
185 self.header_pair.clone()
186 }
187 pub fn get_version(&self) -> &str {
189 self.version
190 }
191
192 pub fn get_query(&self, k: &str) -> Option<&str> {
198 if let BodyContent::UrlForm(x) = &self.body {
199 let r = x.keys().find(|&&ik| {
200 if ik.to_lowercase() == k.to_lowercase() {
201 true
202 } else {
203 false
204 }
205 });
206 match r {
207 Some(r) => {
208 return Some(x.get(*r).unwrap()); }
210 None => {
211 return None;
212 }
213 }
214 } else if let BodyContent::Multi(x) = &self.body {
215 let r = x.keys().find(|&ik| {
216 if ik.to_lowercase() == k.to_lowercase() {
217 true
218 } else {
219 false
220 }
221 });
222 match r {
223 Some(s) => {
224 let v = x.get(s).unwrap(); match v {
226 MultipleFormData::Text(v) => {
227 return Some(*v);
228 }
229 MultipleFormData::File(_) => return None,
230 }
231 }
232 None => {
233 return None;
234 }
235 }
236 } else {
237 None
238 }
239 }
240
241 pub fn get_file(&self, k: &str) -> Option<&'_ MultipleFormFile> {
251 if let BodyContent::Multi(x) = &self.body {
252 let r = x.keys().find(|&ik| {
253 if k.to_lowercase() == ik.to_lowercase() {
254 true
255 } else {
256 false
257 }
258 });
259 match r {
260 Some(s) => {
261 let item = x.get(s).unwrap(); if let MultipleFormData::File(file) = item {
263 return Some(file);
264 } else {
265 return None;
266 }
267 }
268 None => return None,
269 }
270 } else {
271 None
272 }
273 }
274
275 pub fn get_queries(&self) -> Option<HashMap<&str, &str>> {
278 if let BodyContent::UrlForm(x) = &self.body {
279 Some(x.clone())
280 } else if let BodyContent::Multi(x) = &self.body {
281 let mut v = HashMap::new();
282 for (k, item) in x {
283 match item {
284 MultipleFormData::Text(text) => {
285 v.insert(k.as_str(), *text);
286 }
287 MultipleFormData::File(_) => {}
288 }
289 }
290 if v.len() != 0 {
291 return Some(v);
292 } else {
293 return None;
294 }
295 } else {
296 None
297 }
298 }
299
300 pub fn get_files(&self) -> Option<Vec<&MultipleFormFile>> {
302 if let BodyContent::Multi(x) = &self.body {
303 let mut vec = Vec::new();
304 for (_k, v) in x {
305 match v {
306 MultipleFormData::Text(_) => {}
307 MultipleFormData::File(file) => {
308 vec.push(file);
309 }
310 }
311 }
312 if vec.len() != 0 {
313 return Some(vec);
314 } else {
315 return None;
316 }
317 } else {
318 None
319 }
320 }
321
322 pub fn plain_body(&self) -> Option<&str> {
325 if let BodyContent::PureText(x) = self.body {
326 Some(x)
327 } else {
328 None
329 }
330 }
331
332 pub fn has_body(&self) -> bool {
334 if let BodyContent::None = self.body {
335 false
336 } else {
337 true
338 }
339 }
340
341 pub fn get_conn(&self) -> Rc<RefCell<&'a mut TcpStream>> {
345 Rc::clone(&self.conn_)
346 }
347
348 pub fn get_method(&self) -> &str {
350 self.method
351 }
352
353 pub fn get_url(&self) -> &str {
355 self.url
356 }
357
358 pub(crate) fn get_secret_key(&self) -> Arc<Hmac<Sha256>> {
359 Arc::clone(&self.secret_key)
360 }
361
362 pub fn url_to_path(&self) -> &str {
364 match self.url.find("?") {
365 Some(pos) => &self.url[..pos],
366 None => self.url,
367 }
368 }
369
370 pub fn get_context(&self) -> &RefCell<BTreeMap<String, Value>> {
374 &self.ctx
375 }
376}
377
378pub struct ResponseConfig<'b, 'a> {
379 res: &'b mut Response<'a>,
380 has_failure: bool,
381}
382
383impl<'b, 'a> ResponseConfig<'b, 'a> {
384 fn get_map_key(map: &MultiMap<String, String>, key: &str) -> Option<String> {
385 let r = map.keys().find(|&ik| {
386 if ik.to_lowercase() == key.to_lowercase() {
387 true
388 } else {
389 false
390 }
391 });
392 Some((r?).clone())
393 }
394
395 pub fn chunked(&mut self) -> &mut Self {
397 if self.has_failure {
398 return self;
399 }
400 if self.res.method == "HEAD" {
401 return self;
402 }
403 self.res
404 .add_header(String::from("Transfer-Encoding"), String::from("chunked"));
405 if let Some(key) = Self::get_map_key(&self.res.header_pair, "content-length") {
406 self.res.header_pair.remove(&key);
407 }
408 self.res.chunked.enable = true;
409 self
410 }
411
412 pub fn status(&mut self, code: u16) -> &mut Self {
414 if self.has_failure {
415 return self;
416 }
417 self.res.http_state = code;
418 self
419 }
420
421 pub fn specify_file_name(&mut self, name: &str) -> &mut Self {
424 if self.has_failure {
425 return self;
426 }
427 match &self.res.body {
428 BodyType::Memory(_, _) => {}
429 BodyType::File(_, _) => {
430 if !self.res.header_exist("Content-Disposition") {
431 self.res.add_header(
432 "Content-Disposition".to_string(),
433 format!("attachment; filename=\"{name}\""),
434 );
435 }
436 }
437 BodyType::None => {}
438 }
439 self
440 }
441
442 pub fn enable_range(&mut self) -> &mut Self {
444 if self.has_failure {
445 return self;
446 }
447 self.res
448 .add_header(String::from("Accept-Ranges"), String::from("bytes"));
449 if self.res.method == "HEAD" {
450 match &self.res.body {
451 BodyType::Memory(_, buffs) => {
452 self.res
453 .add_header(String::from("Content-length"), buffs.len().to_string());
454 self.res.http_state = 200;
455 }
456 BodyType::File(path, _) => {
457 match std::fs::OpenOptions::new().read(true).open(path) {
458 Ok(file) => {
459 match file.metadata() {
460 Ok(meta) => {
461 self.res.add_header(
462 String::from("Content-length"),
463 meta.len().to_string(),
464 );
465 self.res.http_state = 200;
466 }
467 Err(_) => {
468 self.has_failure = true;
469 self.res.write_state(404);
470 }
471 };
472 }
473 Err(_) => {
474 self.has_failure = true;
475 self.res.write_state(404);
476 }
477 }
478 }
479 BodyType::None => {}
480 }
481 } else {
482 match self.res.get_request_header_value("Range") {
483 Some(v) => {
484 self.res.range = parse_range_content(v);
485 }
486 None => {
487 self.res.range = ResponseRangeMeta::None;
488 }
489 }
490 }
491 self
492 }
493
494 pub fn with_cookies<T: MoreThanOneCookie<Output = Cookie>>(&mut self, v: T) -> &mut Self {
498 if self.has_failure {
499 return self;
500 }
501 for e in v.into_vec() {
502 match e.to_string() {
503 Some(s) => {
504 self.res.add_header(String::from("set-cookie"), s);
505 }
506 None => {
507 continue;
508 }
509 }
510 }
511 self
512 }
513
514 pub fn charset(&mut self, v: &str) -> &mut Self {
515 if self.has_failure {
516 return self;
517 }
518 self.res.charset = Some(v.to_string());
519 self
520 }
521}
522
523pub trait MoreThanOneCookie {
524 type Output;
525 fn into_vec(self) -> Vec<Self::Output>;
526}
527
528impl MoreThanOneCookie for Cookie {
529 type Output = Cookie;
530
531 fn into_vec(self) -> Vec<Self::Output> {
532 vec![self]
533 }
534}
535
536impl<const I: usize> MoreThanOneCookie for [Cookie; I] {
537 type Output = Cookie;
538
539 fn into_vec(self) -> Vec<Self::Output> {
540 Vec::from(self)
541 }
542}
543
544fn parse_range_content(v: &str) -> ResponseRangeMeta {
545 match v.trim().split_once("=") {
546 Some(v) => {
547 let v = v.1;
548 match v.trim().split_once("-") {
549 Some(v) => {
550 let start;
551 let end;
552 if v.0 != "" {
553 let mut exception = false;
554 let r: u64 = v.0.parse().unwrap_or_else(|_| {
555 exception = true;
556 0
557 });
558 if r == 0 && exception == true {
559 start = None;
560 } else {
561 start = Some(r);
562 }
563 } else {
564 start = None;
565 }
566 if v.1 != "" {
567 let mut exception = false;
568 let r: u64 = v.1.parse().unwrap_or_else(|_| {
569 exception = true;
570 0
571 });
572 if r == 0 && exception == true {
573 end = None;
574 } else {
575 end = Some(r);
576 }
577 } else {
578 end = None;
579 }
580 ResponseRangeMeta::Range(start, end)
581 }
582 None => ResponseRangeMeta::Range(None, None),
583 }
584 }
585 None => ResponseRangeMeta::Range(None, None),
586 }
587}
588
589pub struct ResponseChunkMeta {
590 pub(super) enable: bool,
591 pub(super) chunk_size: usize,
592}
593
594impl ResponseChunkMeta {
595 pub(super) fn new(chunk_size: u32) -> Self {
596 ResponseChunkMeta {
597 enable: false,
598 chunk_size: chunk_size as usize,
599 }
600 }
601}
602
603pub enum ResponseRangeMeta {
604 Range(Option<u64>, Option<u64>),
605 None,
606}
607
608pub enum MemoryType {
609 String(String),
610 Binary,
611}
612
613pub enum BodyType {
614 Memory(MemoryType, Vec<u8>),
615 File(String, Option<String>),
616 None,
617}
618
619pub struct Response<'a> {
620 pub(super) header_pair: MultiMap<String, String>,
621 pub(super) version: &'a str,
622 pub(super) method: &'a str,
623 pub(super) http_state: u16,
625 pub(super) body: BodyType,
626 pub(super) chunked: ResponseChunkMeta,
627 pub(super) conn_: Rc<RefCell<&'a mut TcpStream>>,
628 pub(super) range: ResponseRangeMeta,
629 pub(super) request_header: HashMap<&'a str, &'a str>,
630 pub(super) charset: Option<String>,
631}
632
633impl<'a> Response<'a> {
634 fn get_request_header_value(&mut self, k: &str) -> Option<&str> {
635 match self.request_header.keys().find(|&&ik| {
636 if k.to_lowercase() == ik.to_lowercase() {
637 true
638 } else {
639 false
640 }
641 }) {
642 Some(k) => Some(self.request_header.get(*k).unwrap()), None => None,
644 }
645 }
646
647 pub fn remove_header(&mut self, key: String) {
659 let r = self.header_pair.keys().find(|&ik| {
660 if key.to_lowercase() == ik.to_lowercase() {
661 true
662 } else {
663 false
664 }
665 });
666 match r {
667 Some(k) => {
668 let s = k.clone();
669 let map = &mut self.header_pair;
670 map.remove(&s);
671 }
672 None => {}
673 }
674 }
675
676 pub fn add_header(&mut self, key: String, value: String) {
682 self.header_pair.insert(key, value);
683 }
684
685 fn set_default_content_type(&mut self) {
686 if !self.header_exist("Content-Type") {
687 match &self.body {
688 BodyType::Memory(kind, _) => {
689 match kind {
690 MemoryType::String(extension) => match &self.charset {
691 Some(charset) => {
692 self.add_header(
693 "Content-type".to_string(),
694 format!("{}; charset={}", extension, charset),
695 );
696 }
697 None => {
698 self.add_header(
699 "Content-type".to_string(),
700 format!("{}; charset=utf-8", extension),
701 );
702 }
703 },
704 MemoryType::Binary => {}
705 };
706 }
707 BodyType::File(_, extension) => {
708 if let Some(x) = extension {
709 match &self.charset {
710 Some(charset) => {
711 self.add_header(
712 "Content-type".to_string(),
713 format!("{}; charset={}", x, charset),
714 );
715 }
716 None => {
717 self.add_header(
718 "Content-type".to_string(),
719 format!("{}; charset=utf-8", x),
720 );
721 }
722 }
723 }
724 }
725 BodyType::None => {}
726 }
727 }
728 }
729 pub(super) fn header_to_string(&mut self) -> Vec<u8> {
730 let mut buffs = Vec::new();
732 let state_text = http_response_table::get_httpstatus_from_code(self.http_state);
733 buffs.extend_from_slice(format!("{} {}", self.version, state_text).as_bytes());
734 self.set_default_content_type();
735 for (k, v) in &self.header_pair {
736 for value in v {
737 buffs.extend_from_slice(format!("{}: {}\r\n", k, value).as_bytes());
738 }
739 }
740 buffs.extend_from_slice(b"\r\n");
741 buffs
742 }
743
744 fn take_body_size(&mut self) -> io::Result<u64> {
745 match &self.body {
746 BodyType::Memory(_, buff) => Ok(buff.len() as u64),
747 BodyType::File(path, _) => match std::fs::OpenOptions::new().read(true).open(path) {
748 Ok(file) => Ok(file.metadata()?.len()),
749 Err(e) => Err(e),
750 },
751 BodyType::None => Ok(0),
752 }
753 }
754
755 pub(super) fn take_body_buff(&mut self) -> io::Result<LayzyBuffers> {
756 let body_size = self.take_body_size()?;
757 match self.range {
758 ResponseRangeMeta::Range(start, end) => {
759 let mut beg_pos;
760 let end_pos;
761 let mut lack_beg = false;
762 if let Some(x) = start {
763 beg_pos = x;
764 } else {
765 beg_pos = 0;
766 lack_beg = true;
767 }
768 if let Some(x) = end {
769 if lack_beg {
770 end_pos = body_size - 1;
771 beg_pos = body_size - x;
772 } else {
773 end_pos = x;
774 }
775 } else {
776 if lack_beg {
777 self.write_state(416);
778 return Err(io::Error::new(
779 io::ErrorKind::InvalidData,
780 "bad requested range values with form [ - ]",
781 ));
782 }
783 end_pos = body_size - 1;
784 }
785 if beg_pos > end_pos || (beg_pos > (body_size - 1)) || end_pos >= body_size {
786 self.write_state(416);
787 return Err(io::Error::new(
788 io::ErrorKind::InvalidData,
789 "bad requested range values due to out of range",
790 ));
791 }
792
793 let v = format!("bytes {}-{}/{}", beg_pos, end_pos, body_size);
794 let len = (end_pos - beg_pos + 1).to_string();
795 self.add_header(String::from("Content-Range"), v);
796 let key = "Content-Length".to_string();
797 self.remove_header(key.clone());
798
799 if !self.chunked.enable {
800 self.add_header(key, len);
801 }
802 self.http_state = 206;
803
804 match &self.body {
805 BodyType::Memory(_, buffs) => {
806 let slice = &buffs[beg_pos as usize..=end_pos as usize];
807 let mut ret_buff = Vec::new();
808 ret_buff.extend_from_slice(slice);
809 return Ok(LayzyBuffers {
810 buffs: LayzyBuffersType::Memory(ret_buff),
811 len: slice.len() as u64,
812 });
813 }
814 BodyType::File(path, _) => {
815 let mut file = std::fs::OpenOptions::new().read(true).open(path)?;
816 let need_size = end_pos - beg_pos + 1;
817 file.seek(std::io::SeekFrom::Start(beg_pos))?;
818 return Ok(LayzyBuffers {
819 buffs: LayzyBuffersType::File(FileType {
820 file: Box::new(file),
821 buffs: Vec::new(),
822 }),
823 len: need_size,
824 });
825 }
826 BodyType::None => {
827 return Ok(LayzyBuffers {
828 buffs: LayzyBuffersType::None,
829 len: 0,
830 });
831 }
832 };
833 }
834 ResponseRangeMeta::None => match &self.body {
835 BodyType::Memory(_, buffs) => {
836 return Ok(LayzyBuffers {
837 buffs: LayzyBuffersType::Memory(buffs.clone()),
838 len: buffs.len() as u64,
839 });
840 }
841 BodyType::File(path, _) => {
842 let file = std::fs::OpenOptions::new().read(true).open(path)?;
843 return Ok(LayzyBuffers {
844 buffs: LayzyBuffersType::File(FileType {
845 file: Box::new(file),
846 buffs: Vec::new(),
847 }),
848 len: body_size as u64,
849 });
850 }
851 BodyType::None => {
852 return Ok(LayzyBuffers {
853 buffs: LayzyBuffersType::None,
854 len: 0,
855 });
856 }
857 },
858 }
859 }
860
861 pub fn header_exist(&self, s: &str) -> bool {
868 let r = self.header_pair.keys().find(|&k| {
869 if k.to_lowercase() == s.to_lowercase() {
870 true
871 } else {
872 false
873 }
874 });
875 match r {
876 Some(_) => true,
877 None => false,
878 }
879 }
880
881 pub fn get_header(&self, k: &str) -> Option<&Vec<String>> {
884 self.header_pair.get_vec(k)
885 }
886 pub fn write_string(&mut self, v: &str) -> ResponseConfig<'_, 'a> {
888 self.add_header(String::from("Content-length"), v.len().to_string());
889 self.body = BodyType::Memory(MemoryType::String("text/plain".to_string()), v.into());
890 ResponseConfig {
891 res: self,
892 has_failure: false,
893 }
894 }
895
896 pub fn write_binary(&mut self, v: Vec<u8>) -> ResponseConfig<'_, 'a> {
898 self.add_header(String::from("Content-length"), v.len().to_string());
899 self.body = BodyType::Memory(MemoryType::Binary, v);
900 ResponseConfig {
901 res: self,
902 has_failure: false,
903 }
904 }
905
906 pub fn write_state(&mut self, code: u16) {
908 self.http_state = code;
909 self.add_header(String::from("Content-length"), 0.to_string());
910 self.body = BodyType::None;
911 }
912
913 pub fn write_file(&mut self, path: String) -> ResponseConfig<'_, 'a> {
915 match std::fs::OpenOptions::new().read(true).open(path.clone()) {
916 Ok(file) => {
917 match file.metadata() {
918 Ok(meta) => {
919 self.add_header(String::from("Content-length"), meta.len().to_string());
920 }
921 Err(_) => {
922 self.write_string(&format!("{} cannot get file length", path))
923 .status(404);
924 return ResponseConfig {
925 res: self,
926 has_failure: true,
927 };
928 }
929 };
930 let extension = std::path::Path::new(&path)
931 .extension()
932 .and_then(OsStr::to_str);
933
934 match extension {
935 Some(extension) => {
936 let content_type = mime::extension_to_content_type(extension);
937 self.body = BodyType::File(path, Some(content_type.to_string()));
938 }
939 None => {
940 self.body = BodyType::File(path, None);
941 }
942 }
943 return ResponseConfig {
944 res: self,
945 has_failure: false,
946 };
947 }
948 Err(_) => {
949 self.write_string(&format!("{} file not found", path))
950 .status(404);
951 return ResponseConfig {
952 res: self,
953 has_failure: true,
954 };
955 }
956 }
957 }
958
959 pub fn render_view(
963 &mut self,
964 factory: impl Fn(&Request) -> tera::Result<String>,
965 context: &Request,
966 ) -> ResponseConfig<'_, 'a> {
967 match factory(context) {
968 Ok(s) => {
969 return self.write_string(&s);
970 }
971 Err(e) => {
972 self.write_string(&format!("Render view error: {}", e.to_string()))
973 .status(404);
974 return ResponseConfig {
975 res: self,
976 has_failure: true,
977 };
978 }
979 }
980 }
981
982 pub fn render_view_once(&mut self, path: &str, context: &Context) -> ResponseConfig<'_, 'a> {
986 match OpenOptions::new().read(true).open(path) {
987 Ok(mut file) => {
988 let mut s = String::new();
989 match file.read_to_string(&mut s) {
990 Ok(_) => match Tera::one_off(&s, &context, true) {
991 Ok(s) => {
992 self.add_header(String::from("Content-length"), s.len().to_string());
993 let extension = std::path::Path::new(&path)
994 .extension()
995 .and_then(OsStr::to_str);
996
997 match extension {
998 Some(extension) => {
999 let content_type = mime::extension_to_content_type(extension);
1000 self.body = BodyType::Memory(
1001 MemoryType::String(content_type.to_string()),
1002 s.into(),
1003 );
1004 }
1005 None => {
1006 self.body = BodyType::Memory(
1007 MemoryType::String("text/plain".to_string()),
1008 s.into(),
1009 );
1010 }
1011 }
1012 return ResponseConfig {
1013 res: self,
1014 has_failure: false,
1015 };
1016 }
1017 Err(e) => {
1018 self.write_string(&format!("Render view error: {}", e.to_string()))
1019 .status(404);
1020 return ResponseConfig {
1021 res: self,
1022 has_failure: true,
1023 };
1024 }
1025 },
1026 Err(e) => {
1027 self.write_string(&format!("Render view error: {}", e.to_string()))
1028 .status(404);
1029 return ResponseConfig {
1030 res: self,
1031 has_failure: true,
1032 };
1033 }
1034 }
1035 }
1036 Err(e) => {
1037 self.write_string(&format!("Render view error: {}", e.to_string()))
1038 .status(404);
1039 return ResponseConfig {
1040 res: self,
1041 has_failure: true,
1042 };
1043 }
1044 }
1045 }
1046
1047 pub fn get_conn(&self) -> Rc<RefCell<&'a mut TcpStream>> {
1048 Rc::clone(&self.conn_)
1049 }
1050}
1051
1052#[derive(Debug)]
1053pub enum BodyContent<'a> {
1054 UrlForm(HashMap<&'a str, &'a str>),
1055 PureText(&'a str),
1056 Multi(HashMap<String, MultipleFormData<'a>>),
1057 None,
1058 Bad,
1059 TooLarge,
1060}
1061
1062#[derive(Debug)]
1063pub struct MultipleFormFile {
1064 pub filename: String,
1065 pub filepath: String,
1066 pub content_type: String,
1067 pub form_indice: String,
1068}
1069
1070#[derive(Debug)]
1071pub enum MultipleFormData<'a> {
1072 Text(&'a str),
1073 File(MultipleFormFile),
1074}
1075
1076pub(super) struct FileType {
1077 file: Box<std::fs::File>,
1078 buffs: Vec<u8>,
1079}
1080
1081pub(super) enum LayzyBuffersType {
1082 Memory(Vec<u8>),
1083 File(FileType),
1084 None,
1085}
1086pub(super) struct LayzyBuffers {
1087 buffs: LayzyBuffersType,
1088 len: u64,
1089}
1090
1091impl LayzyBuffers {
1092 pub fn len(&self) -> usize {
1093 self.len as usize
1094 }
1095
1096 pub fn get_slice_from_range(&mut self, index: Range<usize>) -> Result<&[u8], io::Error> {
1097 match &mut self.buffs {
1098 LayzyBuffersType::Memory(buffs) => Ok(&mut buffs[index]),
1099 LayzyBuffersType::File(file_v) => {
1100 let file = &mut file_v.file;
1101 let need_size = index.end - index.start;
1102 let buffs = &mut file_v.buffs;
1103 buffs.resize(need_size, b'\0');
1104 match file.read(&mut buffs[0..]) {
1105 Ok(read_size) => {
1106 if read_size != need_size {
1107 let msg = format!("cannot read enough bytes from the file, need bytes: {}, actual read bytes: {}",need_size,read_size);
1108 return Err(io::Error::new(io::ErrorKind::InvalidData, msg));
1109 }
1110 return Ok(&buffs[0..read_size]);
1111 }
1112 Err(e) => {
1113 return Err(e);
1114 }
1115 }
1116 }
1117 LayzyBuffersType::None => unreachable!(),
1118 }
1119 }
1120
1121 }
1142
1143