sfo_http/
http_server.rs

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}