tokiotest_httpserver/
handler.rs

1use std::convert::Infallible;
2use std::sync::Arc;
3use futures::future::BoxFuture;
4use hyper::{Body, HeaderMap, Method, Request};
5use crate::StatusCode;
6
7pub type Response = hyper::Response<hyper::Body>;
8pub type HandlerCallback = Arc<dyn Fn(Request<hyper::Body>) -> BoxFuture<'static, Result<Response, Infallible>> + Send + Sync>;
9
10#[derive(Default, Clone)]
11pub struct HandlerBuilder {
12    path: String,
13    method: Method,
14    headers: HeaderMap,
15    status_code: StatusCode
16}
17
18#[allow(dead_code)]
19impl HandlerBuilder {
20    pub fn new(path: &str) -> HandlerBuilder {
21        HandlerBuilder {
22            path: String::from(path),
23            method: Method::GET,
24            headers: HeaderMap::new(),
25            status_code: StatusCode::INTERNAL_SERVER_ERROR
26        }
27    }
28
29    pub fn method(mut self, method: Method) -> HandlerBuilder {
30        self.method = method;
31        self
32    }
33
34    pub fn status_code(mut self, status_code: StatusCode) -> HandlerBuilder {
35        self.status_code = status_code;
36        self
37    }
38
39    pub fn headers(mut self, headers: HeaderMap) -> HandlerBuilder {
40        self.headers = headers;
41        self
42    }
43
44    pub fn build(self) -> HandlerCallback {
45        let Self { path, method, status_code, headers } = self;
46        Arc::new(move |req: Request<Body>| {
47            let cloned_path = path.clone();
48            let cloned_method = method.clone();
49            let cloned_headers = headers.clone();
50            Box::pin(async move {
51                if req.uri().path().eq(cloned_path.as_str()) && req.method().eq(&cloned_method)
52                && Self::contains_headers(req.headers(), &cloned_headers) {
53                    Ok(hyper::Response::builder().status(status_code).body(Body::empty()).unwrap())
54                } else {
55                    Ok(hyper::Response::builder().status(StatusCode::INTERNAL_SERVER_ERROR).body(Body::empty()).unwrap())
56                }
57            })
58        })
59    }
60
61    fn contains_headers(headers_reference: &HeaderMap, headers_to_be_contained: &HeaderMap) -> bool {
62        for (header, value) in headers_to_be_contained {
63            if !headers_reference.get(header).eq(&Some(value)) {
64                return false;
65            }
66        }
67        true
68    }
69}
70
71pub async fn default_handle(_req: Request<Body>) ->  Result<Response, Infallible> {
72    Ok(hyper::Response::builder().status(StatusCode::INTERNAL_SERVER_ERROR).body(Body::empty()).unwrap())
73}