credence_lib/render/
context.rs1use super::{
2 super::{configuration::*, middleware::*},
3 constants::*,
4 default_preparer::*,
5 preparer::*,
6 rendered_page::*,
7 renderer::*,
8 templates::*,
9};
10
11use {
12 ::axum::{
13 http::{header::*, *},
14 response::Response,
15 },
16 compris::{annotate::*, normal::*, ser::*, *},
17 httpdate::*,
18 kutil::{
19 http::*,
20 std::{collections::*, immutable::*},
21 },
22 std::result::Result,
23};
24
25#[derive(Debug)]
27pub struct RenderContext<'own> {
28 pub rendered_page: &'own RenderedPage,
30
31 pub variables: FastHashMap<ByteString, Variant<WithAnnotations>>,
33
34 pub socket: Option<Socket>,
36
37 pub uri_path: ByteString,
39
40 pub original_uri_path: Option<ByteString>,
42
43 pub query: Option<QueryMap>,
45
46 pub last_modified: Option<HttpDate>,
48
49 pub is_json: (bool, bool),
51
52 pub renderer: Renderer,
54
55 pub templates: &'own Templates,
57
58 pub configuration: &'own CredenceConfiguration,
60}
61
62impl<'own> RenderContext<'own> {
63 pub fn new(
65 rendered_page: &'own RenderedPage,
66 variables: FastHashMap<ByteString, Variant<WithAnnotations>>,
67 socket: Option<Socket>,
68 uri_path: ByteString,
69 original_uri_path: Option<ByteString>,
70 query: Option<QueryMap>,
71 last_modified: Option<HttpDate>,
72 is_json: (bool, bool),
73 renderer: Renderer,
74 templates: &'own Templates,
75 configuration: &'own CredenceConfiguration,
76 ) -> Self {
77 Self {
78 rendered_page,
79 variables,
80 socket,
81 uri_path,
82 original_uri_path,
83 query,
84 last_modified,
85 is_json,
86 renderer,
87 templates,
88 configuration,
89 }
90 }
91
92 pub async fn prepare<PreparerT>(&mut self, preparer: PreparerT) -> Result<(), StatusCode>
94 where
95 PreparerT: RenderPreparer,
96 {
97 preparer.prepare(self).await
98 }
99
100 pub async fn prepare_default(&mut self) -> Result<(), StatusCode> {
102 self.prepare(DefaultRenderedPageHandler).await
103 }
104
105 pub async fn into_response(self) -> Result<Response, StatusCode> {
107 let template = self.rendered_page.annotations.template(&self.configuration.render);
108 let html = self.templates.render(template, &self.variables).await?;
109 let mut headers = self.rendered_page.merged_headers()?;
110
111 if let Some(last_modified) = &self.last_modified {
112 headers
113 .set_string_value(LAST_MODIFIED, &last_modified.to_string())
114 .map_err_internal_server("set Last-Modified")?;
115 }
116
117 if self.is_json.0 {
118 let json = self.into_json()?;
119 response_from_bytes(json.into_bytes(), JSON_MEDIA_TYPE_STRING, headers)
120 } else {
121 response_from_bytes(html.into_bytes(), HTML_MEDIA_TYPE_STRING, headers)
122 }
123 }
124
125 fn into_json(self) -> Result<ByteString, StatusCode> {
126 Serializer::new(Format::JSON)
127 .with_pretty(self.is_json.1)
128 .stringify_modal(&self.variables_into_variant(), &SerializationMode::for_json())
129 .map_err_internal_server("serialize JSON")
130 }
131
132 fn variables_into_variant(self) -> Variant<WithAnnotations> {
133 self.variables.into_iter().map(|(key, value)| (key.into(), value.clone())).collect()
134 }
135}