1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use std::fmt;
use std::future::Future;
use std::pin::Pin;
#[doc(inline)]
pub use crate::cycle;
pub trait Responder: Send + fmt::Debug {
fn respond(&mut self) -> Pin<Box<dyn Future<Output = http::Response<hyper::Body>> + Send>>;
}
pub fn status_code(code: u16) -> impl Responder {
StatusCode(code)
}
#[derive(Debug)]
pub struct StatusCode(u16);
impl Responder for StatusCode {
fn respond(&mut self) -> Pin<Box<dyn Future<Output = http::Response<hyper::Body>> + Send>> {
async fn _respond(status_code: u16) -> http::Response<hyper::Body> {
http::Response::builder()
.status(status_code)
.body(hyper::Body::empty())
.unwrap()
}
Box::pin(_respond(self.0))
}
}
pub fn json_encoded<T>(data: T) -> impl Responder
where
T: serde::Serialize,
{
JsonEncoded(serde_json::to_string(&data).unwrap())
}
#[derive(Debug)]
pub struct JsonEncoded(String);
impl Responder for JsonEncoded {
fn respond(&mut self) -> Pin<Box<dyn Future<Output = http::Response<hyper::Body>> + Send>> {
async fn _respond(body: String) -> http::Response<hyper::Body> {
http::Response::builder()
.status(200)
.header("Content-Type", "application/json")
.body(body.into())
.unwrap()
}
Box::pin(_respond(self.0.clone()))
}
}
pub fn url_encoded<T>(data: T) -> impl Responder
where
T: serde::Serialize,
{
UrlEncoded(serde_urlencoded::to_string(&data).unwrap())
}
#[derive(Debug)]
pub struct UrlEncoded(String);
impl Responder for UrlEncoded {
fn respond(&mut self) -> Pin<Box<dyn Future<Output = http::Response<hyper::Body>> + Send>> {
async fn _respond(body: String) -> http::Response<hyper::Body> {
http::Response::builder()
.status(200)
.header("Content-Type", "application/x-www-form-urlencoded")
.body(body.into())
.unwrap()
}
Box::pin(_respond(self.0.clone()))
}
}
impl<B> Responder for http::Response<B>
where
B: Clone + Into<hyper::Body> + Send + fmt::Debug,
{
fn respond(&mut self) -> Pin<Box<dyn Future<Output = http::Response<hyper::Body>> + Send>> {
async fn _respond(resp: http::Response<hyper::Body>) -> http::Response<hyper::Body> {
resp
}
let mut builder = http::Response::builder();
builder = builder
.status(self.status().clone())
.version(self.version().clone());
*builder.headers_mut().unwrap() = self.headers().clone();
let resp = builder.body(self.body().clone().into()).unwrap();
Box::pin(_respond(resp))
}
}
pub fn cycle(responders: Vec<Box<dyn Responder>>) -> impl Responder {
if responders.is_empty() {
panic!("empty vector provided to cycle");
}
Cycle { idx: 0, responders }
}
#[derive(Debug)]
pub struct Cycle {
idx: usize,
responders: Vec<Box<dyn Responder>>,
}
impl Responder for Cycle {
fn respond(&mut self) -> Pin<Box<dyn Future<Output = http::Response<hyper::Body>> + Send>> {
let response = self.responders[self.idx].respond();
self.idx = (self.idx + 1) % self.responders.len();
response
}
}
#[cfg(test)]
mod tests {}