Skip to main content

wwsvc_rs/
requests.rs

1use std::collections::HashMap;
2use std::fmt::Write;
3
4use serde::{Deserialize, Serialize};
5
6use crate::{WWSVCError, params::Parameters};
7
8/// Trait for converting a `reqwest::Request` to a HTTP string.
9pub trait RequestToHttpString {
10    /// Converts the `reqwest::Request` to a HTTP string.
11    fn to_http_string(&self) -> Result<String, WWSVCError>;
12}
13
14impl RequestToHttpString for reqwest::Request {
15    fn to_http_string(&self) -> Result<String, WWSVCError> {
16        let mut result = String::new();
17
18        writeln!(
19            result,
20            "{} {}{} HTTP/1.1",
21            self.method(),
22            self.url().path(),
23            self.url().query().unwrap_or("")
24        )?;
25
26        if let Some(host) = self.url().host_str() {
27            if let Some(port) = self.url().port() {
28                writeln!(result, "host: {}:{}", host, port)?;
29            } else {
30                writeln!(result, "host: {}", host)?;
31            }
32        }
33
34        for (name, value) in self.headers() {
35            writeln!(result, "{}: {}", name, value.to_str()?)?;
36        }
37
38        writeln!(result)?;
39
40        if let Some(body) = self.body() {
41            if let Some(bytes) = body.as_bytes() {
42                result.push_str(&String::from_utf8_lossy(bytes));
43            } else {
44                result.push_str("[streaming body - cannot display]");
45            }
46        }
47
48        Ok(result)
49    }
50}
51
52/// The request body for the `EXECJSON` endpoint.
53#[derive(Serialize, Deserialize, Clone, Debug)]
54pub struct ExecJsonRequest {
55    /// The service function to be executed.
56    #[serde(rename = "WWSVC_FUNCTION")]
57    pub function: ServiceFunction,
58    /// The authentication info for this request.
59    #[serde(rename = "WWSVC_PASSINFO")]
60    pub pass_info: ServicePassInfo,
61}
62
63impl ExecJsonRequest {
64    /// Creates a new `ExecJsonRequest` to be passed as a request body to the `EXECJSON` endpoint.
65    pub fn new(
66        function_name: &str,
67        parameters: Vec<ServiceFunctionParameter>,
68        version: u32,
69        service_pass: &str,
70        app_hash: &str,
71        timestamp: &str,
72        request_id: u32,
73    ) -> Self {
74        Self {
75            function: ServiceFunction {
76                function_name: function_name.to_string(),
77                parameters,
78                revision: version,
79            },
80            pass_info: ServicePassInfo {
81                service_pass: service_pass.to_string(),
82                app_hash: app_hash.to_string(),
83                timestamp: timestamp.to_string(),
84                request_id,
85                execute_mode: "SYNCHRON".to_string(),
86            },
87        }
88    }
89}
90
91/// The function to be executed.
92#[derive(Serialize, Deserialize, Clone, Debug)]
93pub struct ServiceFunction {
94    /// The name of the function.
95    #[serde(rename = "FUNCTIONNAME")]
96    pub function_name: String,
97    /// The parameters of the function.
98    #[serde(rename = "PARAMETER")]
99    pub parameters: Vec<ServiceFunctionParameter>,
100    /// The revision of the function.
101    #[serde(rename = "REVISION")]
102    pub revision: u32,
103}
104
105/// The parameters of the function.
106#[derive(Serialize, Deserialize, Clone, Debug)]
107pub struct ServiceFunctionParameter {
108    /// The name of the parameter.
109    #[serde(rename = "PNAME")]
110    pub name: String,
111    /// The value of the parameter.
112    #[serde(rename = "PCONTENT")]
113    pub content: String,
114}
115
116/// Trait for converting a type to a vector of `ServiceFunctionParameter`.
117pub trait ToServiceFunctionParameters {
118    /// Converts the type to a vector of `ServiceFunctionParameter`.
119    fn to_service_function_parameters(&self) -> Vec<ServiceFunctionParameter>;
120}
121
122impl ToServiceFunctionParameters for HashMap<String, String> {
123    /// Converts the `HashMap` to a vector of `ServiceFunctionParameter`.
124    fn to_service_function_parameters(&self) -> Vec<ServiceFunctionParameter> {
125        self.iter()
126            .map(|(name, content)| ServiceFunctionParameter {
127                name: name.clone(),
128                content: content.clone(),
129            })
130            .collect()
131    }
132}
133
134impl ToServiceFunctionParameters for HashMap<&str, &str> {
135    /// Converts the `HashMap` to a vector of `ServiceFunctionParameter`.
136    fn to_service_function_parameters(&self) -> Vec<ServiceFunctionParameter> {
137        self.iter()
138            .map(|(name, content)| ServiceFunctionParameter {
139                name: name.to_string(),
140                content: content.to_string(),
141            })
142            .collect()
143    }
144}
145
146impl ToServiceFunctionParameters for Parameters {
147    /// Converts the `Parameters` to a vector of `ServiceFunctionParameter`.
148    fn to_service_function_parameters(&self) -> Vec<ServiceFunctionParameter> {
149        self.as_inner().iter()
150            .map(|(name, content): (&String, &String)| ServiceFunctionParameter {
151                name: name.clone(),
152                content: content.clone(),
153            })
154            .collect()
155    }
156}
157
158/// The authentication info for a request.
159#[derive(Serialize, Deserialize, Clone, Debug)]
160pub struct ServicePassInfo {
161    /// The service pass.
162    #[serde(rename = "SERVICEPASS")]
163    pub service_pass: String,
164    /// The application hash.
165    #[serde(rename = "APPHASH")]
166    pub app_hash: String,
167    /// The timestamp of the request.
168    #[serde(rename = "TIMESTAMP")]
169    pub timestamp: String,
170    /// The request ID.
171    #[serde(rename = "REQUESTID")]
172    pub request_id: u32,
173    /// The execute mode.
174    #[serde(rename = "EXECUTE_MODE")]
175    pub execute_mode: String,
176}