Skip to main content

leyline/core/
service.rs

1use std::future::Future;
2use std::pin::Pin;
3use std::task::{Context, Poll};
4
5use http::{Request as HttpRequest, Response as HttpResponse};
6
7use crate::core::body::Body;
8use crate::core::{Kind, Response, Result, Session};
9
10#[derive(Clone, Debug)]
11pub struct LeylineService {
12    session: Session,
13}
14
15impl LeylineService {
16    pub fn new(session: Session) -> Self {
17        Self { session }
18    }
19}
20
21fn adapt(resp: Response) -> Result<HttpResponse<Body>> {
22    let mut builder = HttpResponse::builder().status(resp.status());
23    for (name, value) in resp.headers() {
24        builder = builder.header(name, value);
25    }
26    let body = Body::stream(resp.into_stream()?, None);
27    builder
28        .body(body)
29        .map_err(|e| crate::core::Error::new(Kind::Request).with_source(e))
30}
31
32impl tower_service::Service<HttpRequest<Body>> for LeylineService {
33    type Response = HttpResponse<Body>;
34    type Error = crate::core::Error;
35    type Future = Pin<Box<dyn Future<Output = Result<HttpResponse<Body>>> + Send>>;
36
37    fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<()>> {
38        Poll::Ready(Ok(()))
39    }
40
41    fn call(&mut self, req: HttpRequest<Body>) -> Self::Future {
42        let session = self.session.clone();
43        Box::pin(async move { adapt(session.execute(req).await?) })
44    }
45}