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 bytestring::*,
17 compris::{normal::*, ser::*, *},
18 httpdate::*,
19 kutil_http::*,
20 kutil_std::collections::*,
21 std::result::Result,
22};
23
24#[derive(Debug)]
26pub struct RenderContext<'own> {
27 pub rendered_page: &'own RenderedPage,
29
30 pub variables: FastHashMap<ByteString, Value>,
32
33 pub socket: Option<Socket>,
35
36 pub uri_path: ByteString,
38
39 pub original_uri_path: Option<ByteString>,
41
42 pub query: Option<QueryMap>,
44
45 pub last_modified: Option<HttpDate>,
47
48 pub is_json: (bool, bool),
50
51 pub renderer: Renderer,
53
54 pub templates: &'own Templates,
56
57 pub configuration: &'own CredenceConfiguration,
59}
60
61impl<'own> RenderContext<'own> {
62 pub fn new(
64 rendered_page: &'own RenderedPage,
65 variables: FastHashMap<ByteString, Value>,
66 socket: Option<Socket>,
67 uri_path: ByteString,
68 original_uri_path: Option<ByteString>,
69 query: Option<QueryMap>,
70 last_modified: Option<HttpDate>,
71 is_json: (bool, bool),
72 renderer: Renderer,
73 templates: &'own Templates,
74 configuration: &'own CredenceConfiguration,
75 ) -> Self {
76 Self {
77 rendered_page,
78 variables,
79 socket,
80 uri_path,
81 original_uri_path,
82 query,
83 last_modified,
84 is_json,
85 renderer,
86 templates,
87 configuration,
88 }
89 }
90
91 pub async fn prepare<PreparerT>(&mut self, preparer: PreparerT) -> Result<(), StatusCode>
93 where
94 PreparerT: RenderPreparer,
95 {
96 preparer.prepare(self).await
97 }
98
99 pub async fn prepare_default(&mut self) -> Result<(), StatusCode> {
101 self.prepare(DefaultRenderedPageHandler).await
102 }
103
104 pub async fn into_response(self) -> Result<Response, StatusCode> {
106 let template = self.rendered_page.annotations.template(&self.configuration.render);
107 let html = self.templates.render(template, &self.variables).await?;
108 let mut headers = self.rendered_page.merged_headers()?;
109
110 if let Some(last_modified) = &self.last_modified {
111 headers
112 .set_string_value(LAST_MODIFIED, &last_modified.to_string())
113 .map_err_internal_server("set Last-Modified")?;
114 }
115
116 if self.is_json.0 {
117 let json = self.into_json()?;
118 response_from_bytes(json.into_bytes(), JSON_MEDIA_TYPE_STRING, headers)
119 } else {
120 response_from_bytes(html.into_bytes(), HTML_MEDIA_TYPE_STRING, headers)
121 }
122 }
123
124 fn into_json(self) -> Result<ByteString, StatusCode> {
125 Serializer::new(Format::JSON)
126 .with_pretty(self.is_json.1)
127 .stringify_modal(&self.variables_into_value(), &SerializationMode::for_json())
128 .map_err_internal_server("serialize JSON")
129 }
130
131 fn variables_into_value(self) -> Value {
132 self.variables.into_iter().map(|(key, value)| (key.into(), value.clone())).collect()
133 }
134}