actix_prerender/
builder.rs1use crate::middleware::Inner;
2use crate::{middleware, PrerenderError, PrerenderMiddleware};
3use actix_service::{Service, Transform};
4use actix_utils::future;
5use actix_utils::future::Ready;
6use actix_web::body::{EitherBody, MessageBody};
7use actix_web::dev::{ServiceRequest, ServiceResponse};
8use actix_web::Error;
9use reqwest::header::HeaderMap;
10use reqwest::Client;
11use std::rc::Rc;
12use url::Url;
13
14#[derive(Clone)]
44pub struct Prerender {
45 inner: Rc<Inner>,
46}
47
48#[derive()]
49pub struct PrerenderBuilder {
50 pub(crate) forward_headers: bool,
51 pub(crate) before_render_fn: Option<fn(&ServiceRequest, &mut HeaderMap)>,
52}
53
54fn default_client() -> Client {
55 Client::builder()
56 .gzip(true)
57 .timeout(std::time::Duration::new(25, 0))
58 .build()
59 .unwrap()
60}
61
62impl PrerenderBuilder {
63 pub fn use_prerender_io(self, token: String) -> Prerender {
65 let inner = Inner {
66 before_render_fn: self.before_render_fn,
67 forward_headers: self.forward_headers,
68 inner_client: default_client(),
69 prerender_service_url: middleware::prerender_url(),
70 prerender_token: Some(token),
71 };
72
73 Prerender { inner: Rc::new(inner) }
74 }
75
76 pub fn use_custom_prerender_url(self, prerender_service_url: &str) -> Result<Prerender, PrerenderError> {
78 let prerender_service_url = Url::parse(prerender_service_url).map_err(|_| PrerenderError::InvalidUrl)?;
79
80 let inner = Inner {
81 before_render_fn: self.before_render_fn,
82 forward_headers: self.forward_headers,
83 inner_client: default_client(),
84 prerender_service_url,
85 prerender_token: None,
86 };
87
88 Ok(Prerender { inner: Rc::new(inner) })
89 }
90
91 pub fn set_before_render_fn(mut self, prerender_func: fn(req: &ServiceRequest, headers: &mut HeaderMap)) -> Self {
93 self.before_render_fn = Some(prerender_func);
94 self
95 }
96
97 pub const fn forward_headers(mut self) -> Self {
99 self.forward_headers = true;
100 self
101 }
102}
103
104impl Prerender {
105 pub fn build() -> PrerenderBuilder {
106 PrerenderBuilder {
107 forward_headers: false,
108 before_render_fn: None,
109 }
110 }
111}
112
113impl<S, B> Transform<S, ServiceRequest> for Prerender
114where
115 S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
116 S::Future: 'static,
117
118 B: MessageBody + 'static,
119{
120 type Response = ServiceResponse<EitherBody<B>>;
121 type Error = Error;
122 type Transform = PrerenderMiddleware<S>;
123 type InitError = ();
124 type Future = Ready<Result<Self::Transform, Self::InitError>>;
125
126 fn new_transform(&self, service: S) -> Self::Future {
127 future::ok(PrerenderMiddleware {
128 service,
129 inner: Rc::clone(&self.inner),
130 })
131 }
132}