1use std::fmt::Debug;
2use std::future::Future;
3use std::path::Path;
4use http::{HeaderName, HeaderValue, StatusCode};
5use http::header::COOKIE;
6use serde::de::DeserializeOwned;
7use serde::Serialize;
8use crate::errors::HttpResult;
9
10#[async_trait::async_trait(?Send)]
11pub trait Request: 'static {
12 fn peer_addr(&self) -> Option<String>;
13 fn local_addr(&self) -> Option<String>;
14 fn remote(&self) -> Option<String>;
15 fn host(&self) -> Option<String>;
16 fn content_type(&self) -> Option<String>;
17 fn header(&self,
18 key: impl Into<HeaderName>, ) -> Option<HeaderValue>;
19 fn header_all(&self, key: impl Into<HeaderName>) -> Vec<HeaderValue>;
20 fn param(&self, key: &str) -> HttpResult<&str>;
21 fn query<T: DeserializeOwned>(&self) -> HttpResult<T>;
22 async fn body_string(&mut self) -> HttpResult<String>;
23 async fn body_bytes(&mut self) -> HttpResult<Vec<u8>>;
24 async fn body_json<T: DeserializeOwned>(&mut self) -> HttpResult<T>;
25 async fn body_form<T: DeserializeOwned>(&mut self) -> HttpResult<T>;
26 fn get_cookie(&self, cookie_name: &str) -> Option<String> {
27 let cookie = self.header_all(COOKIE);
28 if cookie.is_empty() {
29 return None;
30 }
31 let cookie_str = match cookie.last().unwrap().to_str() {
32 Ok(v) => v,
33 Err(_) => return None,
34 };
35 let cookie_list: Vec<_> = cookie_str.split(";").collect();
36 let cookie_list: Vec<(String, String)> = cookie_list.into_iter().map(|v| {
37 let cookie_list: Vec<_> = v.split("=").collect();
38 cookie_list
39 }).filter(|v| v.len() == 2).map(|v| (v[0].trim().to_string(), v[1].trim().to_string())).collect();
40
41 for (name, value) in cookie_list.into_iter() {
42 if name.as_str() == cookie_name {
43 return Some(value);
44 }
45 }
46
47 None
48 }
49}
50
51pub trait Response: 'static {
52 fn from_result<T: Serialize, C: Debug + Copy + Sync + Send + 'static + Into<u16>>(ret: sfo_result::Result<T, C>) -> Self;
53 fn new(status: StatusCode) -> Self;
54 fn insert_header(&mut self, name: HeaderName, value: HeaderValue);
55 fn set_content_type(&mut self, content_type: &str) -> HttpResult<()>;
56 fn set_body(&mut self, body: Vec<u8>);
57}
58
59#[async_trait::async_trait(?Send)]
60pub trait Endpoint<Req: Request, Resp: Response>: Send + Sync + 'static {
61 async fn call(&self, req: Req) -> HttpResult<Resp>;
62}
63
64#[async_trait::async_trait(?Send)]
65impl<Req, Resp, F, Fut> Endpoint<Req, Resp> for F
66where
67 Req: Request,
68 Resp: Response,
69 F: 'static + Send + Clone + Sync + Fn(Req) -> Fut,
70 Fut: Future<Output = HttpResult<Resp>> + 'static,
71{
72 async fn call(&self, req: Req) -> HttpResult<Resp> {
73 let fut = (self)(req);
74 fut.await
75 }
76}
77
78pub trait Route<Req: Request, Resp: Response> {
79 fn get(&mut self, ep: impl Endpoint<Req, Resp>) -> &mut Self;
80 fn post(&mut self, ep: impl Endpoint<Req, Resp>) -> &mut Self;
81 fn put(&mut self, ep: impl Endpoint<Req, Resp>) -> &mut Self;
82 fn delete(&mut self, ep: impl Endpoint<Req, Resp>) -> &mut Self;
83 fn serve_dir(&mut self, dir: impl AsRef<Path>) -> HttpResult<&mut Self>;
84 fn serve_file(&mut self, file: impl AsRef<Path>) -> HttpResult<&mut Self>;
85}
86
87pub trait HttpServer<Req: Request, Resp: Response, R: Route<Req, Resp>> {
88 fn at(&mut self, path: &str) -> R;
89}