1use std::net::ToSocketAddrs;
2
3use hyper::service::{make_service_fn, service_fn};
4use hyper::{Body, Request, Response, Server};
5use std::sync::Arc;
6
7use thruster::context::hyper_request::HyperRequest;
8use thruster::{App, Context, ReusableBoxFuture, ThrusterServer};
9
10use crate::body::ProtoBody;
11
12pub struct ProtoServer<T: 'static + Context + Clone + Send + Sync, S: Send> {
13 app: App<HyperRequest, T, S>,
14}
15
16impl<
17 T: Context<Response = Response<ProtoBody>> + Clone + Send + Sync,
18 S: 'static + Send + Sync,
19 > ThrusterServer for ProtoServer<T, S>
20{
21 type Context = T;
22 type Response = Response<ProtoBody>;
23 type Request = HyperRequest;
24 type State = S;
25
26 fn new(app: App<Self::Request, T, Self::State>) -> Self {
27 ProtoServer { app }
28 }
29
30 fn build(mut self, host: &str, port: u16) -> ReusableBoxFuture<()> {
31 self.app = self.app.commit();
32
33 let arc_app = Arc::new(self.app);
34 let addr = (host, port).to_socket_addrs().unwrap().next().unwrap();
35
36 ReusableBoxFuture::new(async move {
37 let service = make_service_fn(|socket: &hyper::server::conn::AddrStream| {
38 let app = arc_app.clone();
39 let ip = socket.remote_addr().ip();
40
41 async move {
42 Ok::<_, hyper::Error>(service_fn(move |req: Request<Body>| {
43 let mut req = HyperRequest::new(req);
44 req.ip = Some(ip);
45
46 app.match_and_resolve(req)
47 }))
48 }
49 });
50
51 let server = Server::bind(&addr).serve(service);
52
53 server.await.expect("Hyper server failed to start");
54 })
55 }
56}