1pub type Result = std::result::Result<ft_sdk::chr::CHR<Output>, ft_sdk::Error>;
2
3#[derive(Debug)]
4pub enum Output {
5 Json(serde_json::Value),
6 Binary(Binary),
7 Redirect(String, http::HeaderValue),
9}
10
11#[derive(Debug)]
12pub struct Binary {
13 pub file_name: Option<String>,
14 pub content: bytes::Bytes,
15 pub content_type: String,
16}
17
18pub(crate) fn binary_response(
19 binary: Binary,
20) -> std::result::Result<::http::Response<bytes::Bytes>, ft_sdk::Error> {
21 let mut response_builder = http::Response::builder()
22 .status(200)
23 .header("Content-Type", binary.content_type.as_str());
24
25 if let Some(filename) = binary.file_name {
27 response_builder = response_builder.header(
28 "Content-Disposition",
29 format!("attachment; filename=\"{filename}\"").as_str(),
30 )
31 }
32
33 Ok(response_builder.body(binary.content)?)
34}
35
36impl From<ft_sdk::chr::CHR<Output>>
37 for std::result::Result<http::Response<bytes::Bytes>, ft_sdk::Error>
38{
39 fn from(
40 ft_sdk::chr::CHR {
41 cookies,
42 headers,
43 response,
44 }: ft_sdk::chr::CHR<Output>,
45 ) -> Self {
46 let response = match response {
47 Output::Json(json_value) => ft_sdk::json(json_value),
48 Output::Binary(binary) => binary_response(binary),
49 Output::Redirect(url, cookie) => Ok(http::Response::builder()
50 .status(200)
51 .header(http::header::SET_COOKIE, cookie)
52 .header(http::header::CONTENT_TYPE, "text/html; charset=utf-8")
53 .body(format!("<meta http-equiv='refresh' content='0; url={url}' />").into())?),
54 }?;
55 ft_sdk::chr::chr(cookies, headers, response)
56 }
57}
58
59pub fn download<S1: AsRef<str>, S2: AsRef<str>>(
77 file_name: S1,
78 content: bytes::Bytes,
79 content_type: S2,
80) -> Result {
81 Ok(ft_sdk::chr::CHR::new(Output::Binary(Binary {
82 file_name: Some(file_name.as_ref().to_string()),
83 content,
84 content_type: content_type.as_ref().to_string(),
85 })))
86}
87
88pub fn binary<S: AsRef<str>>(content: bytes::Bytes, content_type: S) -> Result {
103 Ok(ft_sdk::chr::CHR::new(Output::Binary(Binary {
104 file_name: None,
105 content,
106 content_type: content_type.as_ref().to_string(),
107 })))
108}
109
110pub fn browser_redirect_with_cookie<S: AsRef<str>>(url: S, c: http::HeaderValue) -> Result {
125 Ok(ft_sdk::chr::CHR::new(Output::Redirect(
126 url.as_ref().to_string(),
127 c,
128 )))
129}
130
131pub fn json<T: serde::Serialize>(t: T) -> Result {
132 Ok(ft_sdk::chr::CHR::new(Output::Json(serde_json::to_value(
133 t,
134 )?)))
135}
136
137pub fn api_ok<T: serde::Serialize>(t: T) -> Result {
138 Ok(ft_sdk::chr::CHR::new(Output::Json(
139 serde_json::json!({"data": serde_json::to_value(t)?, "success": true }),
140 )))
141}
142
143pub fn api_error(errors: std::collections::HashMap<String, String>) -> Result {
144 Ok(ft_sdk::chr::CHR::new(Output::Json(
145 serde_json::json!({"errors": serde_json::to_value(errors)?, "success": false }),
146 )))
147}