use std::collections::HashMap;
use std::fmt::Write;
use serde::{Deserialize, Serialize};
use crate::{WWSVCError, params::Parameters};
pub trait RequestToHttpString {
fn to_http_string(&self) -> Result<String, WWSVCError>;
}
impl RequestToHttpString for reqwest::Request {
fn to_http_string(&self) -> Result<String, WWSVCError> {
let mut result = String::new();
writeln!(
result,
"{} {}{} HTTP/1.1",
self.method(),
self.url().path(),
self.url().query().unwrap_or("")
)?;
if let Some(host) = self.url().host_str() {
if let Some(port) = self.url().port() {
writeln!(result, "host: {}:{}", host, port)?;
} else {
writeln!(result, "host: {}", host)?;
}
}
for (name, value) in self.headers() {
writeln!(result, "{}: {}", name, value.to_str()?)?;
}
writeln!(result)?;
if let Some(body) = self.body() {
if let Some(bytes) = body.as_bytes() {
result.push_str(&String::from_utf8_lossy(bytes));
} else {
result.push_str("[streaming body - cannot display]");
}
}
Ok(result)
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ExecJsonRequest {
#[serde(rename = "WWSVC_FUNCTION")]
pub function: ServiceFunction,
#[serde(rename = "WWSVC_PASSINFO")]
pub pass_info: ServicePassInfo,
}
impl ExecJsonRequest {
pub fn new(
function_name: &str,
parameters: Vec<ServiceFunctionParameter>,
version: u32,
service_pass: &str,
app_hash: &str,
timestamp: &str,
request_id: u32,
) -> Self {
Self {
function: ServiceFunction {
function_name: function_name.to_string(),
parameters,
revision: version,
},
pass_info: ServicePassInfo {
service_pass: service_pass.to_string(),
app_hash: app_hash.to_string(),
timestamp: timestamp.to_string(),
request_id,
execute_mode: "SYNCHRON".to_string(),
},
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ServiceFunction {
#[serde(rename = "FUNCTIONNAME")]
pub function_name: String,
#[serde(rename = "PARAMETER")]
pub parameters: Vec<ServiceFunctionParameter>,
#[serde(rename = "REVISION")]
pub revision: u32,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ServiceFunctionParameter {
#[serde(rename = "PNAME")]
pub name: String,
#[serde(rename = "PCONTENT")]
pub content: String,
}
pub trait ToServiceFunctionParameters {
fn to_service_function_parameters(&self) -> Vec<ServiceFunctionParameter>;
}
impl ToServiceFunctionParameters for HashMap<String, String> {
fn to_service_function_parameters(&self) -> Vec<ServiceFunctionParameter> {
self.iter()
.map(|(name, content)| ServiceFunctionParameter {
name: name.clone(),
content: content.clone(),
})
.collect()
}
}
impl ToServiceFunctionParameters for HashMap<&str, &str> {
fn to_service_function_parameters(&self) -> Vec<ServiceFunctionParameter> {
self.iter()
.map(|(name, content)| ServiceFunctionParameter {
name: name.to_string(),
content: content.to_string(),
})
.collect()
}
}
impl ToServiceFunctionParameters for Parameters {
fn to_service_function_parameters(&self) -> Vec<ServiceFunctionParameter> {
self.as_inner().iter()
.map(|(name, content): (&String, &String)| ServiceFunctionParameter {
name: name.clone(),
content: content.clone(),
})
.collect()
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ServicePassInfo {
#[serde(rename = "SERVICEPASS")]
pub service_pass: String,
#[serde(rename = "APPHASH")]
pub app_hash: String,
#[serde(rename = "TIMESTAMP")]
pub timestamp: String,
#[serde(rename = "REQUESTID")]
pub request_id: u32,
#[serde(rename = "EXECUTE_MODE")]
pub execute_mode: String,
}