mirror of
https://github.com/Orange-OpenSource/hurl.git
synced 2024-11-23 20:12:09 +03:00
Refacto JSON Serializer/Deserializer
This commit is contained in:
parent
852a9cb06e
commit
925a5c08a7
69
packages/hurl/src/json/mod.rs
Normal file
69
packages/hurl/src/json/mod.rs
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* hurl (https://hurl.dev)
|
||||
* Copyright (C) 2020 Orange
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
use crate::cli::CliError;
|
||||
use std::io::prelude::*;
|
||||
use std::path::PathBuf;
|
||||
|
||||
mod result;
|
||||
mod value;
|
||||
|
||||
pub fn write_json_report(
|
||||
file_path: PathBuf,
|
||||
results: Vec<serde_json::Value>,
|
||||
) -> Result<(), CliError> {
|
||||
let mut file = match std::fs::File::create(&file_path) {
|
||||
Err(why) => {
|
||||
return Err(CliError {
|
||||
message: format!("Issue writing to {}: {:?}", file_path.display(), why),
|
||||
})
|
||||
}
|
||||
Ok(file) => file,
|
||||
};
|
||||
let serialized = serde_json::to_string_pretty(&results).unwrap();
|
||||
if let Err(why) = file.write_all(serialized.as_bytes()) {
|
||||
Err(CliError {
|
||||
message: format!("Issue writing to {}: {:?}", file_path.display(), why),
|
||||
})
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_json(path: PathBuf) -> Result<Vec<serde_json::Value>, CliError> {
|
||||
if path.exists() {
|
||||
let s = match std::fs::read_to_string(path.clone()) {
|
||||
Ok(s) => s,
|
||||
Err(why) => {
|
||||
return Err(CliError {
|
||||
message: format!("Issue reading {} to string to {:?}", path.display(), why),
|
||||
});
|
||||
}
|
||||
};
|
||||
match serde_json::from_str(s.as_str()) {
|
||||
Ok(val) => Ok(val),
|
||||
Err(_) => {
|
||||
return Err(CliError {
|
||||
message: format!("The file {} is not a valid json file", path.display()),
|
||||
})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Ok(vec![])
|
||||
}
|
||||
}
|
302
packages/hurl/src/json/result.rs
Normal file
302
packages/hurl/src/json/result.rs
Normal file
@ -0,0 +1,302 @@
|
||||
/*
|
||||
* hurl (https://hurl.dev)
|
||||
* Copyright (C) 2020 Orange
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
use crate::http::{Cookie, Header, Param, Request, RequestCookie, Response, Version};
|
||||
use crate::runner::{AssertResult, CaptureResult, EntryResult, HurlResult, ResponseCookie};
|
||||
|
||||
impl HurlResult {
|
||||
pub fn to_json(&self, lines: &[String]) -> serde_json::Value {
|
||||
let mut map = serde_json::Map::new();
|
||||
map.insert(
|
||||
"filename".to_string(),
|
||||
serde_json::Value::String(self.filename.clone()),
|
||||
);
|
||||
let entries = self
|
||||
.entries
|
||||
.iter()
|
||||
.map(|e| e.clone().to_json(lines, self.filename.clone()))
|
||||
.collect();
|
||||
map.insert("entries".to_string(), serde_json::Value::Array(entries));
|
||||
map.insert(
|
||||
"success".to_string(),
|
||||
serde_json::Value::Bool(self.clone().success),
|
||||
);
|
||||
map.insert(
|
||||
"time".to_string(),
|
||||
serde_json::Value::Number(serde_json::Number::from(self.time_in_ms as u64)),
|
||||
);
|
||||
let cookies = self.cookies.iter().map(|e| e.clone().to_json()).collect();
|
||||
map.insert("cookies".to_string(), serde_json::Value::Array(cookies));
|
||||
serde_json::Value::Object(map)
|
||||
}
|
||||
}
|
||||
|
||||
impl EntryResult {
|
||||
fn to_json(&self, lines: &[String], filename: String) -> serde_json::Value {
|
||||
let mut map = serde_json::Map::new();
|
||||
if let Some(request) = &self.request {
|
||||
map.insert("request".to_string(), request.to_json());
|
||||
}
|
||||
if let Some(response) = &self.response {
|
||||
map.insert("response".to_string(), response.to_json());
|
||||
}
|
||||
let captures = self.captures.iter().map(|c| c.clone().to_json()).collect();
|
||||
map.insert("captures".to_string(), captures);
|
||||
let asserts = self
|
||||
.asserts
|
||||
.iter()
|
||||
.map(|a| a.clone().to_json(lines, filename.clone()))
|
||||
.collect();
|
||||
map.insert("asserts".to_string(), asserts);
|
||||
map.insert(
|
||||
"time".to_string(),
|
||||
serde_json::Value::Number(serde_json::Number::from(self.time_in_ms as u64)),
|
||||
);
|
||||
serde_json::Value::Object(map)
|
||||
}
|
||||
}
|
||||
|
||||
impl Request {
|
||||
fn to_json(&self) -> serde_json::Value {
|
||||
let mut map = serde_json::Map::new();
|
||||
map.insert(
|
||||
"method".to_string(),
|
||||
serde_json::Value::String(self.method.clone()),
|
||||
);
|
||||
map.insert(
|
||||
"url".to_string(),
|
||||
serde_json::Value::String(self.url.clone()),
|
||||
);
|
||||
let headers = self.headers.iter().map(|h| h.clone().to_json()).collect();
|
||||
map.insert("headers".to_string(), headers);
|
||||
let cookies = self
|
||||
.clone()
|
||||
.cookies()
|
||||
.iter()
|
||||
.map(|e| e.clone().to_json())
|
||||
.collect();
|
||||
map.insert("cookies".to_string(), serde_json::Value::Array(cookies));
|
||||
let query_string = self
|
||||
.clone()
|
||||
.query_string_params()
|
||||
.iter()
|
||||
.map(|e| e.clone().to_json())
|
||||
.collect();
|
||||
map.insert(
|
||||
"queryString".to_string(),
|
||||
serde_json::Value::Array(query_string),
|
||||
);
|
||||
serde_json::Value::Object(map)
|
||||
}
|
||||
}
|
||||
|
||||
impl Response {
|
||||
fn to_json(&self) -> serde_json::Value {
|
||||
let mut map = serde_json::Map::new();
|
||||
map.insert("httpVersion".to_string(), self.version.to_json());
|
||||
map.insert(
|
||||
"status".to_string(),
|
||||
serde_json::Value::Number(serde_json::Number::from(self.status)),
|
||||
);
|
||||
let headers = self.headers.iter().map(|h| h.clone().to_json()).collect();
|
||||
map.insert("headers".to_string(), headers);
|
||||
let cookies = self
|
||||
.clone()
|
||||
.cookies()
|
||||
.iter()
|
||||
.map(|e| e.clone().to_json())
|
||||
.collect();
|
||||
map.insert("cookies".to_string(), serde_json::Value::Array(cookies));
|
||||
serde_json::Value::Object(map)
|
||||
}
|
||||
}
|
||||
|
||||
impl Header {
|
||||
fn to_json(&self) -> serde_json::Value {
|
||||
let mut map = serde_json::Map::new();
|
||||
map.insert(
|
||||
"name".to_string(),
|
||||
serde_json::Value::String(self.name.clone()),
|
||||
);
|
||||
map.insert(
|
||||
"value".to_string(),
|
||||
serde_json::Value::String(self.value.clone()),
|
||||
);
|
||||
serde_json::Value::Object(map)
|
||||
}
|
||||
}
|
||||
|
||||
impl Version {
|
||||
fn to_json(&self) -> serde_json::Value {
|
||||
let value = match self {
|
||||
Version::Http10 => "HTTP/1.0",
|
||||
Version::Http11 => "HTTP/1.1",
|
||||
Version::Http2 => "HTTP/2",
|
||||
};
|
||||
serde_json::Value::String(value.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl Param {
|
||||
fn to_json(&self) -> serde_json::Value {
|
||||
let mut map = serde_json::Map::new();
|
||||
map.insert(
|
||||
"name".to_string(),
|
||||
serde_json::Value::String(self.name.clone()),
|
||||
);
|
||||
map.insert(
|
||||
"value".to_string(),
|
||||
serde_json::Value::String(self.value.clone()),
|
||||
);
|
||||
serde_json::Value::Object(map)
|
||||
}
|
||||
}
|
||||
|
||||
impl RequestCookie {
|
||||
fn to_json(&self) -> serde_json::Value {
|
||||
let mut map = serde_json::Map::new();
|
||||
map.insert(
|
||||
"name".to_string(),
|
||||
serde_json::Value::String(self.name.clone()),
|
||||
);
|
||||
map.insert(
|
||||
"value".to_string(),
|
||||
serde_json::Value::String(self.value.clone()),
|
||||
);
|
||||
serde_json::Value::Object(map)
|
||||
}
|
||||
}
|
||||
|
||||
impl ResponseCookie {
|
||||
fn to_json(&self) -> serde_json::Value {
|
||||
let mut map = serde_json::Map::new();
|
||||
map.insert(
|
||||
"name".to_string(),
|
||||
serde_json::Value::String(self.name.clone()),
|
||||
);
|
||||
map.insert(
|
||||
"value".to_string(),
|
||||
serde_json::Value::String(self.value.clone()),
|
||||
);
|
||||
|
||||
if let Some(expires) = &self.clone().expires() {
|
||||
map.insert(
|
||||
"expires".to_string(),
|
||||
serde_json::Value::String(expires.to_string()),
|
||||
);
|
||||
}
|
||||
if let Some(max_age) = &self.clone().max_age() {
|
||||
map.insert(
|
||||
"max_age".to_string(),
|
||||
serde_json::Value::String(max_age.to_string()),
|
||||
);
|
||||
}
|
||||
if let Some(domain) = &self.clone().domain() {
|
||||
map.insert(
|
||||
"domain".to_string(),
|
||||
serde_json::Value::String(domain.to_string()),
|
||||
);
|
||||
}
|
||||
if let Some(path) = &self.clone().path() {
|
||||
map.insert(
|
||||
"path".to_string(),
|
||||
serde_json::Value::String(path.to_string()),
|
||||
);
|
||||
}
|
||||
if self.clone().has_secure() {
|
||||
map.insert("secure".to_string(), serde_json::Value::Bool(true));
|
||||
}
|
||||
if self.clone().has_httponly() {
|
||||
map.insert("httponly".to_string(), serde_json::Value::Bool(true));
|
||||
}
|
||||
if let Some(samesite) = &self.clone().samesite() {
|
||||
map.insert(
|
||||
"samesite".to_string(),
|
||||
serde_json::Value::String(samesite.to_string()),
|
||||
);
|
||||
}
|
||||
serde_json::Value::Object(map)
|
||||
}
|
||||
}
|
||||
|
||||
impl CaptureResult {
|
||||
fn to_json(&self) -> serde_json::Value {
|
||||
let mut map = serde_json::Map::new();
|
||||
map.insert(
|
||||
"name".to_string(),
|
||||
serde_json::Value::String(self.name.clone()),
|
||||
);
|
||||
map.insert("value".to_string(), self.value.to_json());
|
||||
serde_json::Value::Object(map)
|
||||
}
|
||||
}
|
||||
|
||||
impl AssertResult {
|
||||
fn to_json(&self, _lines: &[String], _filename: String) -> serde_json::Value {
|
||||
let mut map = serde_json::Map::new();
|
||||
if let AssertResult::Version {
|
||||
actual, expected, ..
|
||||
} = self
|
||||
{
|
||||
map.insert(
|
||||
"actual".to_string(),
|
||||
serde_json::Value::String(actual.clone()),
|
||||
);
|
||||
map.insert(
|
||||
"expected".to_string(),
|
||||
serde_json::Value::String(expected.clone()),
|
||||
);
|
||||
};
|
||||
serde_json::Value::Object(map)
|
||||
}
|
||||
}
|
||||
|
||||
impl Cookie {
|
||||
fn to_json(&self) -> serde_json::Value {
|
||||
let mut map = serde_json::Map::new();
|
||||
map.insert(
|
||||
"domain".to_string(),
|
||||
serde_json::Value::String(self.domain.clone()),
|
||||
);
|
||||
map.insert(
|
||||
"include_subdomain".to_string(),
|
||||
serde_json::Value::String(self.include_subdomain.clone()),
|
||||
);
|
||||
map.insert(
|
||||
"path".to_string(),
|
||||
serde_json::Value::String(self.path.clone()),
|
||||
);
|
||||
map.insert(
|
||||
"https".to_string(),
|
||||
serde_json::Value::String(self.https.clone()),
|
||||
);
|
||||
map.insert(
|
||||
"expires".to_string(),
|
||||
serde_json::Value::String(self.expires.clone()),
|
||||
);
|
||||
map.insert(
|
||||
"name".to_string(),
|
||||
serde_json::Value::String(self.name.clone()),
|
||||
);
|
||||
map.insert(
|
||||
"value".to_string(),
|
||||
serde_json::Value::String(self.value.clone()),
|
||||
);
|
||||
serde_json::Value::Object(map)
|
||||
}
|
||||
}
|
60
packages/hurl/src/json/value.rs
Normal file
60
packages/hurl/src/json/value.rs
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* hurl (https://hurl.dev)
|
||||
* Copyright (C) 2020 Orange
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
use crate::runner::Value;
|
||||
|
||||
impl Value {
|
||||
pub fn to_json(&self) -> serde_json::Value {
|
||||
match self {
|
||||
Value::Bool(v) => serde_json::Value::Bool(*v),
|
||||
Value::Integer(v) => serde_json::Value::Number(serde_json::Number::from(*v)),
|
||||
Value::Float(i, d) => {
|
||||
let value = *i as f64 + (*d as f64) / 1_000_000_000_000_000_000.0;
|
||||
serde_json::Value::Number(serde_json::Number::from_f64(value).unwrap())
|
||||
}
|
||||
Value::String(s) => serde_json::Value::String(s.clone()),
|
||||
Value::List(values) => {
|
||||
let values = values.iter().map(|v| v.to_json()).collect();
|
||||
serde_json::Value::Array(values)
|
||||
}
|
||||
Value::Object(key_values) => {
|
||||
let mut map = serde_json::Map::new();
|
||||
for (key, value) in key_values {
|
||||
map.insert(key.to_string(), value.to_json());
|
||||
}
|
||||
serde_json::Value::Object(map)
|
||||
}
|
||||
Value::Nodeset(size) => {
|
||||
let mut map = serde_json::Map::new();
|
||||
let size = *size as i64;
|
||||
map.insert(
|
||||
"type".to_string(),
|
||||
serde_json::Value::String("nodeset".to_string()),
|
||||
);
|
||||
map.insert("size".to_string(), serde_json::Value::from(size));
|
||||
serde_json::Value::Object(map)
|
||||
}
|
||||
Value::Bytes(v) => {
|
||||
let encoded = base64::encode(v);
|
||||
serde_json::Value::String(encoded)
|
||||
}
|
||||
Value::Null => serde_json::Value::Null,
|
||||
Value::Unit => todo!("how to serialize that in json?"),
|
||||
}
|
||||
}
|
||||
}
|
@ -22,6 +22,7 @@ extern crate float_cmp;
|
||||
|
||||
pub mod cli;
|
||||
pub mod http;
|
||||
pub mod json;
|
||||
pub mod jsonpath;
|
||||
pub mod report;
|
||||
pub mod runner;
|
||||
|
@ -27,6 +27,7 @@ use colored::*;
|
||||
use hurl::cli;
|
||||
use hurl::cli::{CliError, CliOptions};
|
||||
use hurl::http;
|
||||
use hurl::json;
|
||||
use hurl::report;
|
||||
use hurl::runner;
|
||||
use hurl::runner::{HurlResult, RunnerOptions};
|
||||
@ -262,6 +263,12 @@ fn main() {
|
||||
};
|
||||
|
||||
let start = Instant::now();
|
||||
let mut json_results = vec![];
|
||||
|
||||
if let Some(file_path) = cli_options.json_file.clone() {
|
||||
json_results = unwrap_or_exit(&log_error_message, json::parse_json(file_path));
|
||||
}
|
||||
|
||||
for (current, filename) in filenames.iter().enumerate() {
|
||||
let contents = match cli::read_to_string(filename) {
|
||||
Ok(v) => v,
|
||||
@ -281,7 +288,7 @@ fn main() {
|
||||
};
|
||||
let hurl_result = execute(
|
||||
filename,
|
||||
contents,
|
||||
contents.clone(),
|
||||
current_dir,
|
||||
cli_options.clone(),
|
||||
&log_verbose,
|
||||
@ -353,14 +360,24 @@ fn main() {
|
||||
}
|
||||
|
||||
hurl_results.push(hurl_result.clone());
|
||||
|
||||
if cli_options.json_file.is_some() {
|
||||
let lines: Vec<String> = regex::Regex::new(r"\n|\r\n")
|
||||
.unwrap()
|
||||
.split(&contents)
|
||||
.map(|l| l.to_string())
|
||||
.collect();
|
||||
let json_result = hurl_result.to_json(&lines);
|
||||
json_results.push(json_result);
|
||||
}
|
||||
}
|
||||
let duration = start.elapsed().as_millis();
|
||||
|
||||
if let Some(file_path) = cli_options.json_file {
|
||||
if let Some(file_path) = cli_options.json_file.clone() {
|
||||
log_verbose(format!("Writing json report to {}", file_path.display()).as_str());
|
||||
unwrap_or_exit(
|
||||
&log_error_message,
|
||||
report::write_json_report(file_path, hurl_results.clone()),
|
||||
json::write_json_report(file_path, json_results),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -20,66 +20,10 @@ use std::io::prelude::*;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use super::cli::CliError;
|
||||
use super::runner;
|
||||
use super::runner::HurlResult;
|
||||
|
||||
mod html;
|
||||
|
||||
pub fn write_json_report(
|
||||
file_path: PathBuf,
|
||||
hurl_results: Vec<HurlResult>,
|
||||
) -> Result<(), CliError> {
|
||||
let mut results = parse_json(file_path.clone())?;
|
||||
for result in hurl_results {
|
||||
results.push(result);
|
||||
}
|
||||
let mut file = match std::fs::File::create(&file_path) {
|
||||
Err(why) => {
|
||||
return Err(CliError {
|
||||
message: format!("Issue writing to {}: {:?}", file_path.display(), why),
|
||||
})
|
||||
}
|
||||
Ok(file) => file,
|
||||
};
|
||||
let serialized = serde_json::to_string_pretty(&results).unwrap();
|
||||
if let Err(why) = file.write_all(serialized.as_bytes()) {
|
||||
Err(CliError {
|
||||
message: format!("Issue writing to {}: {:?}", file_path.display(), why),
|
||||
})
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_json(path: PathBuf) -> Result<Vec<HurlResult>, CliError> {
|
||||
if path.exists() {
|
||||
let s = match std::fs::read_to_string(path.clone()) {
|
||||
Ok(s) => s,
|
||||
Err(why) => {
|
||||
return Err(CliError {
|
||||
message: format!("Issue reading {} to string to {:?}", path.display(), why),
|
||||
});
|
||||
}
|
||||
};
|
||||
let v: serde_json::Value = match serde_json::from_str(s.as_str()) {
|
||||
Ok(val) => val,
|
||||
Err(_) => {
|
||||
return Err(CliError {
|
||||
message: format!("The file {} is not a valid json file", path.display()),
|
||||
})
|
||||
}
|
||||
};
|
||||
match runner::deserialize_results(v) {
|
||||
Ok(results) => Ok(results),
|
||||
Err(_) => Err(CliError {
|
||||
message: "Existing Hurl json can not be parsed!".to_string(),
|
||||
}),
|
||||
}
|
||||
} else {
|
||||
Ok(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_html(path: PathBuf) -> Result<Vec<HurlResult>, CliError> {
|
||||
if path.exists() {
|
||||
let s = match std::fs::read_to_string(path.clone()) {
|
||||
|
@ -1,578 +0,0 @@
|
||||
/*
|
||||
* hurl (https://hurl.dev)
|
||||
* Copyright (C) 2020 Orange
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
use crate::http::*;
|
||||
|
||||
use super::cookie::*;
|
||||
use super::core::*;
|
||||
use std::time::Duration;
|
||||
|
||||
type ParseError = String;
|
||||
|
||||
pub fn parse_results(value: serde_json::Value) -> Result<Vec<HurlResult>, ParseError> {
|
||||
if let serde_json::Value::Array(values) = value {
|
||||
let mut results = vec![];
|
||||
for value in values {
|
||||
let result = parse_result(value)?;
|
||||
results.push(result);
|
||||
}
|
||||
Ok(results)
|
||||
} else {
|
||||
Err("expecting an array of session".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_result(value: serde_json::Value) -> Result<HurlResult, ParseError> {
|
||||
if let serde_json::Value::Object(map) = value.clone() {
|
||||
let filename = map.get("filename").unwrap().as_str().unwrap().to_string();
|
||||
let mut entries = vec![];
|
||||
let entries = if let Some(serde_json::Value::Array(values)) = map.get("entries") {
|
||||
for value in values {
|
||||
let entry = parse_entry_result(value.clone())?;
|
||||
entries.push(entry);
|
||||
}
|
||||
entries
|
||||
} else {
|
||||
return Err("expecting an array of entries".to_string());
|
||||
};
|
||||
let time_in_ms = match value.get("time") {
|
||||
Some(serde_json::Value::Number(n)) => match n.as_u64() {
|
||||
Some(x) => x as u128,
|
||||
None => return Err("expecting an integer for the time".to_string()),
|
||||
},
|
||||
_ => return Err("expecting an integer for the time".to_string()),
|
||||
};
|
||||
let success = match value.get("success") {
|
||||
Some(serde_json::Value::Bool(v)) => *v,
|
||||
_ => return Err("expecting a bool for the status".to_string()),
|
||||
};
|
||||
let cookies = vec![];
|
||||
Ok(HurlResult {
|
||||
filename,
|
||||
entries,
|
||||
time_in_ms,
|
||||
success,
|
||||
cookies,
|
||||
})
|
||||
} else {
|
||||
Err("expecting an object for the result".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_entry_result(value: serde_json::Value) -> Result<EntryResult, String> {
|
||||
let request = match value.get("request") {
|
||||
None => None,
|
||||
Some(v) => {
|
||||
let r = parse_request(v.clone())?;
|
||||
Some(r)
|
||||
}
|
||||
};
|
||||
let response = match value.get("response") {
|
||||
None => None,
|
||||
Some(v) => {
|
||||
let r = parse_response(v.clone())?;
|
||||
Some(r)
|
||||
}
|
||||
};
|
||||
Ok(EntryResult {
|
||||
request,
|
||||
response,
|
||||
captures: vec![],
|
||||
asserts: vec![],
|
||||
errors: vec![],
|
||||
time_in_ms: 0,
|
||||
})
|
||||
}
|
||||
// pub fn _parse_request(value: serde_json::Value) -> Result<Request, ParseError> {
|
||||
// if let serde_json::Value::Object(map) = value {
|
||||
// let method = match map.get("method") {
|
||||
// Some(serde_json::Value::String(s)) => parse_method(s.clone())?,
|
||||
// _ => return Err("expecting a string for the method".to_string()),
|
||||
// };
|
||||
// let url = match map.get("url") {
|
||||
// Some(serde_json::Value::String(s)) => s.to_string(),
|
||||
// _ => return Err("expecting a string for the url".to_string()),
|
||||
// };
|
||||
//
|
||||
// let headers = match map.get("headers") {
|
||||
// Some(serde_json::Value::Array(values)) => {
|
||||
// let mut headers = vec![];
|
||||
// for value in values {
|
||||
// let header = parse_header(value.clone())?;
|
||||
// headers.push(header);
|
||||
// }
|
||||
// headers
|
||||
// }
|
||||
// _ => vec![],
|
||||
// };
|
||||
//
|
||||
// let querystring = match map.get("queryString") {
|
||||
// Some(serde_json::Value::Array(values)) => {
|
||||
// let mut params = vec![];
|
||||
// for value in values {
|
||||
// let param = parse_param(value.clone())?;
|
||||
// params.push(param);
|
||||
// }
|
||||
// params
|
||||
// }
|
||||
// _ => vec![],
|
||||
// };
|
||||
//
|
||||
// let form = match map.get("form") {
|
||||
// Some(serde_json::Value::Array(values)) => {
|
||||
// let mut params = vec![];
|
||||
// for value in values {
|
||||
// let param = parse_param(value.clone())?;
|
||||
// params.push(param);
|
||||
// }
|
||||
// params
|
||||
// }
|
||||
// _ => vec![],
|
||||
// };
|
||||
//
|
||||
// let cookies = match map.get("cookies") {
|
||||
// Some(serde_json::Value::Array(values)) => {
|
||||
// let mut headers = vec![];
|
||||
// for value in values {
|
||||
// let header = parse_request_cookie(value.clone())?;
|
||||
// headers.push(header);
|
||||
// }
|
||||
// headers
|
||||
// }
|
||||
// _ => vec![],
|
||||
// };
|
||||
//
|
||||
// // TODO
|
||||
// let multipart = vec![];
|
||||
// let body = http::Body::Binary(vec![]);
|
||||
// let content_type = None;
|
||||
//
|
||||
// Ok(Request {
|
||||
// method,
|
||||
// url,
|
||||
// headers,
|
||||
// querystring,
|
||||
// form,
|
||||
// multipart,
|
||||
// cookies,
|
||||
// body,
|
||||
// content_type,
|
||||
// })
|
||||
// } else {
|
||||
// Err("expecting an object for the request".to_string())
|
||||
// }
|
||||
// }
|
||||
|
||||
pub fn parse_request(value: serde_json::Value) -> Result<Request, ParseError> {
|
||||
if let serde_json::Value::Object(map) = value {
|
||||
let method = match map.get("method") {
|
||||
Some(serde_json::Value::String(s)) => parse_method(s.clone())?.to_string(),
|
||||
_ => return Err("expecting a string for the method".to_string()),
|
||||
};
|
||||
let url = match map.get("url") {
|
||||
Some(serde_json::Value::String(s)) => s.to_string(),
|
||||
_ => return Err("expecting a string for the url".to_string()),
|
||||
};
|
||||
|
||||
let headers = match map.get("headers") {
|
||||
Some(serde_json::Value::Array(values)) => {
|
||||
let mut headers = vec![];
|
||||
for value in values {
|
||||
let header = parse_header(value.clone())?;
|
||||
headers.push(header);
|
||||
}
|
||||
headers
|
||||
}
|
||||
_ => vec![],
|
||||
};
|
||||
|
||||
Ok(Request {
|
||||
url,
|
||||
method,
|
||||
headers,
|
||||
})
|
||||
} else {
|
||||
Err("expecting an object for the request".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_response(value: serde_json::Value) -> Result<Response, ParseError> {
|
||||
if let serde_json::Value::Object(map) = value {
|
||||
let status = match map.get("status") {
|
||||
Some(serde_json::Value::Number(x)) => {
|
||||
if let Some(x) = x.as_u64() {
|
||||
x as u32
|
||||
} else {
|
||||
return Err("expecting a integer for the status".to_string());
|
||||
}
|
||||
}
|
||||
_ => return Err("expecting a number for the status".to_string()),
|
||||
};
|
||||
|
||||
let version = match map.get("httpVersion") {
|
||||
Some(serde_json::Value::String(s)) => parse_version(s.clone())?,
|
||||
_ => return Err("expecting a string for the version".to_string()),
|
||||
};
|
||||
|
||||
let headers = match map.get("headers") {
|
||||
Some(serde_json::Value::Array(values)) => {
|
||||
let mut headers = vec![];
|
||||
for value in values {
|
||||
let header = parse_header(value.clone())?;
|
||||
headers.push(header);
|
||||
}
|
||||
headers
|
||||
}
|
||||
_ => vec![],
|
||||
};
|
||||
|
||||
// TODO: Check if you need it
|
||||
let duration = Duration::new(0, 0);
|
||||
|
||||
Ok(Response {
|
||||
version,
|
||||
status,
|
||||
headers,
|
||||
body: vec![],
|
||||
duration,
|
||||
})
|
||||
} else {
|
||||
Err("expecting an object for the response".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_method(s: String) -> Result<Method, ParseError> {
|
||||
match s.as_str() {
|
||||
"GET" => Ok(Method::Get),
|
||||
"HEAD" => Ok(Method::Head),
|
||||
"POST" => Ok(Method::Post),
|
||||
"PUT" => Ok(Method::Put),
|
||||
"DELETE" => Ok(Method::Delete),
|
||||
"CONNECT" => Ok(Method::Connect),
|
||||
"OPTIONS" => Ok(Method::Options),
|
||||
"TRACE" => Ok(Method::Trace),
|
||||
"PATCH" => Ok(Method::Patch),
|
||||
_ => Err(format!("Invalid method <{}>", s)),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_header(value: serde_json::Value) -> Result<Header, ParseError> {
|
||||
if let serde_json::Value::Object(map) = value {
|
||||
let name = match map.get("name") {
|
||||
Some(serde_json::Value::String(s)) => s.to_string(),
|
||||
_ => return Err("expecting a string for the header name".to_string()),
|
||||
};
|
||||
let value = match map.get("value") {
|
||||
Some(serde_json::Value::String(s)) => s.to_string(),
|
||||
_ => return Err("expecting a string for the header value".to_string()),
|
||||
};
|
||||
Ok(Header { name, value })
|
||||
} else {
|
||||
Err("Expecting object for one header".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
// pub fn parse_param(value: serde_json::Value) -> Result<Param, ParseError> {
|
||||
// if let serde_json::Value::Object(map) = value {
|
||||
// let name = match map.get("name") {
|
||||
// Some(serde_json::Value::String(s)) => s.to_string(),
|
||||
// _ => return Err("expecting a string for the cookie name".to_string()),
|
||||
// };
|
||||
// let value = match map.get("value") {
|
||||
// Some(serde_json::Value::String(s)) => s.to_string(),
|
||||
// _ => return Err("expecting a string for the cookie value".to_string()),
|
||||
// };
|
||||
// Ok(Param { name, value })
|
||||
// } else {
|
||||
// Err("Expecting object for the param".to_string())
|
||||
// }
|
||||
// }
|
||||
|
||||
// pub fn parse_request_cookie(value: serde_json::Value) -> Result<RequestCookie, ParseError> {
|
||||
// if let serde_json::Value::Object(map) = value {
|
||||
// let name = match map.get("name") {
|
||||
// Some(serde_json::Value::String(s)) => s.to_string(),
|
||||
// _ => return Err("expecting a string for the cookie name".to_string()),
|
||||
// };
|
||||
// let value = match map.get("value") {
|
||||
// Some(serde_json::Value::String(s)) => s.to_string(),
|
||||
// _ => return Err("expecting a string for the cookie value".to_string()),
|
||||
// };
|
||||
// Ok(RequestCookie { name, value })
|
||||
// } else {
|
||||
// Err("Expecting object for the request cookie".to_string())
|
||||
// }
|
||||
// }
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn parse_response_cookie(value: serde_json::Value) -> Result<ResponseCookie, ParseError> {
|
||||
if let serde_json::Value::Object(map) = value {
|
||||
let name = match map.get("name") {
|
||||
Some(serde_json::Value::String(s)) => s.to_string(),
|
||||
_ => return Err("expecting a string for the cookie name".to_string()),
|
||||
};
|
||||
let value = match map.get("value") {
|
||||
Some(serde_json::Value::String(s)) => s.to_string(),
|
||||
_ => return Err("expecting a string for the cookie value".to_string()),
|
||||
};
|
||||
let mut attributes = vec![];
|
||||
|
||||
match map.get("expires") {
|
||||
None => {}
|
||||
Some(serde_json::Value::String(s)) => attributes.push(CookieAttribute {
|
||||
name: "Expires".to_string(),
|
||||
value: Some(s.to_string()),
|
||||
}),
|
||||
_ => return Err("expecting a string for the cookie expires".to_string()),
|
||||
};
|
||||
match map.get("max_age") {
|
||||
None => {}
|
||||
Some(serde_json::Value::Number(n)) => attributes.push(CookieAttribute {
|
||||
name: "Max-Age".to_string(),
|
||||
value: Some(n.to_string()),
|
||||
}),
|
||||
_ => return Err("expecting an integer for the cookie max_age".to_string()),
|
||||
};
|
||||
match map.get("domain") {
|
||||
None => {}
|
||||
Some(serde_json::Value::String(s)) => attributes.push(CookieAttribute {
|
||||
name: "Domain".to_string(),
|
||||
value: Some(s.to_string()),
|
||||
}),
|
||||
_ => return Err("expecting a string for the cookie domain".to_string()),
|
||||
};
|
||||
match map.get("path") {
|
||||
None => {}
|
||||
Some(serde_json::Value::String(s)) => attributes.push(CookieAttribute {
|
||||
name: "Path".to_string(),
|
||||
value: Some(s.to_string()),
|
||||
}),
|
||||
_ => return Err("expecting a string for the cookie path".to_string()),
|
||||
};
|
||||
|
||||
match map.get("secure") {
|
||||
None => {}
|
||||
Some(serde_json::Value::Bool(true)) => attributes.push(CookieAttribute {
|
||||
name: "Secure".to_string(),
|
||||
value: None,
|
||||
}),
|
||||
_ => return Err("expecting a true for the cookie secure flag".to_string()),
|
||||
};
|
||||
match map.get("http_only") {
|
||||
None => {}
|
||||
Some(serde_json::Value::Bool(true)) => attributes.push(CookieAttribute {
|
||||
name: "HttpOnly".to_string(),
|
||||
value: None,
|
||||
}),
|
||||
_ => return Err("expecting a true for the cookie http_only flag".to_string()),
|
||||
};
|
||||
match map.get("same_site") {
|
||||
None => {}
|
||||
Some(serde_json::Value::String(s)) => attributes.push(CookieAttribute {
|
||||
name: "SameSite".to_string(),
|
||||
value: Some(s.to_string()),
|
||||
}),
|
||||
_ => return Err("expecting a string for the cookie same_site".to_string()),
|
||||
};
|
||||
|
||||
Ok(ResponseCookie {
|
||||
name,
|
||||
value,
|
||||
attributes,
|
||||
})
|
||||
} else {
|
||||
Err("Expecting object for one cookie".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_version(s: String) -> Result<Version, ParseError> {
|
||||
match s.as_str() {
|
||||
"HTTP/1.0" => Ok(Version::Http10),
|
||||
"HTTP/1.1" => Ok(Version::Http11),
|
||||
"HTTP/2" => Ok(Version::Http2),
|
||||
_ => Err("Expecting version HTTP/1.0, HTTP/1.2 or HTTP/2".to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::runner::value::Value;
|
||||
|
||||
// #[test]
|
||||
// fn test_parse_request() {
|
||||
// let v: serde_json::Value = serde_json::from_str(
|
||||
// r#"{
|
||||
// "method": "GET",
|
||||
// "url": "http://localhost:8000/hello",
|
||||
// "headers": []
|
||||
// }"#,
|
||||
// )
|
||||
// .unwrap();
|
||||
// assert_eq!(_parse_request(v).unwrap(), hello_http_request());
|
||||
//
|
||||
// let v: serde_json::Value = serde_json::from_str(
|
||||
// r#"{
|
||||
// "method": "GET",
|
||||
// "url": "http://localhost:8000/querystring-params?param1=value1¶m2=a%20b",
|
||||
// "headers": []
|
||||
// }"#,
|
||||
// )
|
||||
// .unwrap();
|
||||
// assert_eq!(
|
||||
// _parse_request(v).unwrap(),
|
||||
// http::Request {
|
||||
// method: http::Method::Get,
|
||||
// url: "http://localhost:8000/querystring-params?param1=value1¶m2=a%20b"
|
||||
// .to_string(),
|
||||
// querystring: vec![],
|
||||
// headers: vec![],
|
||||
// cookies: vec![],
|
||||
// body: http::Body::Binary(vec![]),
|
||||
// form: vec![],
|
||||
// multipart: vec![],
|
||||
// content_type: None,
|
||||
// }
|
||||
// );
|
||||
//
|
||||
// let v: serde_json::Value = serde_json::from_str(
|
||||
// r#"{
|
||||
// "method": "GET",
|
||||
// "url": "http://localhost/custom",
|
||||
// "headers": [
|
||||
// {"name": "User-Agent", "value": "iPhone"},
|
||||
// {"name": "Foo", "value": "Bar"}
|
||||
// ],
|
||||
// "cookies": [
|
||||
// {"name": "theme", "value": "light"},
|
||||
// {"name": "sessionToken", "value": "abc123"}
|
||||
// ]
|
||||
// }"#,
|
||||
// )
|
||||
// .unwrap();
|
||||
// assert_eq!(_parse_request(v).unwrap(), custom_http_request());
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn test_parse_response() {
|
||||
let v: serde_json::Value = serde_json::from_str(
|
||||
r#"{
|
||||
"status": 200,
|
||||
"httpVersion": "HTTP/1.0",
|
||||
"headers": [
|
||||
{"name": "Content-Type", "value": "text/html; charset=utf-8" },
|
||||
{"name": "Content-Length", "value": "12" }
|
||||
|
||||
]
|
||||
}"#,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
parse_response(v).unwrap(),
|
||||
Response {
|
||||
version: Version::Http10,
|
||||
status: 200,
|
||||
headers: vec![
|
||||
Header {
|
||||
name: String::from("Content-Type"),
|
||||
value: String::from("text/html; charset=utf-8")
|
||||
},
|
||||
Header {
|
||||
name: String::from("Content-Length"),
|
||||
value: String::from("12")
|
||||
},
|
||||
],
|
||||
body: vec![],
|
||||
duration: Default::default()
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_method() {
|
||||
assert_eq!(parse_method("GET".to_string()).unwrap(), Method::Get);
|
||||
|
||||
let error = parse_method("x".to_string()).err().unwrap();
|
||||
assert_eq!(error, "Invalid method <x>");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_header() {
|
||||
let v: serde_json::Value = serde_json::from_str(
|
||||
r#"{
|
||||
"name": "name1",
|
||||
"value": "value1"
|
||||
}"#,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
parse_header(v).unwrap(),
|
||||
Header {
|
||||
name: "name1".to_string(),
|
||||
value: "value1".to_string()
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_response_cookie() {
|
||||
let v: serde_json::Value = serde_json::from_str(
|
||||
r#"{
|
||||
"name": "name1",
|
||||
"value": "value1"
|
||||
}"#,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
parse_response_cookie(v).unwrap(),
|
||||
ResponseCookie {
|
||||
name: "name1".to_string(),
|
||||
value: "value1".to_string(),
|
||||
attributes: vec![],
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_version() {
|
||||
assert_eq!(
|
||||
parse_version("HTTP/1.0".to_string()).unwrap(),
|
||||
Version::Http10
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_value() {
|
||||
assert_eq!(
|
||||
Value::from_json(&serde_json::Value::String("hello".to_string())),
|
||||
Value::String("hello".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
Value::from_json(&serde_json::Value::Bool(true)),
|
||||
Value::Bool(true)
|
||||
);
|
||||
assert_eq!(
|
||||
Value::from_json(&serde_json::Value::from(1)),
|
||||
Value::Integer(1)
|
||||
);
|
||||
assert_eq!(
|
||||
Value::from_json(&serde_json::Value::from(1.5)),
|
||||
Value::Float(1, 500_000_000_000_000_000)
|
||||
);
|
||||
}
|
||||
}
|
@ -1,281 +0,0 @@
|
||||
/*
|
||||
* hurl (https://hurl.dev)
|
||||
* Copyright (C) 2020 Orange
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
use serde::ser::{SerializeStruct, Serializer};
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::http::*;
|
||||
|
||||
use super::cookie::*;
|
||||
use super::core::*;
|
||||
use super::value::Value;
|
||||
|
||||
impl Serialize for HurlResult {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut state = serializer.serialize_struct("??", 3)?;
|
||||
state.serialize_field("filename", &self.clone().filename)?;
|
||||
state.serialize_field("entries", &self.clone().entries)?;
|
||||
state.serialize_field("success", &self.clone().success)?;
|
||||
state.serialize_field("time", &self.time_in_ms)?;
|
||||
state.serialize_field("cookies", &self.cookies)?;
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for EntryResult {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut state = serializer.serialize_struct("EntryResult", 3)?;
|
||||
if let Some(request) = &self.request {
|
||||
state.serialize_field("request", request)?;
|
||||
}
|
||||
if let Some(response) = &self.response {
|
||||
state.serialize_field("response", response)?;
|
||||
}
|
||||
state.serialize_field("captures", &self.captures)?;
|
||||
state.serialize_field("asserts", &self.asserts)?;
|
||||
state.serialize_field("time", &self.time_in_ms)?;
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for AssertResult {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut state = serializer.serialize_struct("??", 3)?;
|
||||
if let AssertResult::Version {
|
||||
actual, expected, ..
|
||||
} = self
|
||||
{
|
||||
//state.serialize_field("source_info", source_info)?;
|
||||
state.serialize_field("actual", actual)?;
|
||||
state.serialize_field("expected", expected)?;
|
||||
};
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for CaptureResult {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut state = serializer.serialize_struct("CaptureResult", 3)?;
|
||||
state.serialize_field("name", self.name.as_str())?;
|
||||
state.serialize_field("value", &self.value)?;
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for Request {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut state = serializer.serialize_struct("Request", 5)?;
|
||||
state.serialize_field("method", &self.clone().method)?;
|
||||
state.serialize_field("url", &self.clone().url)?;
|
||||
state.serialize_field("headers", &self.clone().headers)?;
|
||||
state.serialize_field("cookies", &self.clone().cookies())?;
|
||||
state.serialize_field("queryString", &self.clone().query_string_params())?;
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for Response {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
// 3 is the number of fields in the struct.
|
||||
let mut state = serializer.serialize_struct("Response", 3)?;
|
||||
state.serialize_field("httpVersion", &self.clone().version)?;
|
||||
state.serialize_field("status", &self.clone().status)?;
|
||||
state.serialize_field("cookies", &self.clone().cookies())?;
|
||||
state.serialize_field("headers", &self.clone().headers)?;
|
||||
|
||||
// TODO Serialize body
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for Header {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut state = serializer.serialize_struct("??", 3)?;
|
||||
state.serialize_field("name", &self.name)?;
|
||||
state.serialize_field("value", &self.value)?;
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for Param {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut state = serializer.serialize_struct("??", 3)?;
|
||||
state.serialize_field("name", &self.name)?;
|
||||
state.serialize_field("value", &self.value)?;
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for RequestCookie {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut state = serializer.serialize_struct("??", 2)?;
|
||||
state.serialize_field("name", &self.name)?;
|
||||
state.serialize_field("value", &self.value)?;
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for Version {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
match self {
|
||||
Version::Http10 => serializer.serialize_str("HTTP/1.0"),
|
||||
Version::Http11 => serializer.serialize_str("HTTP/1.1"),
|
||||
Version::Http2 => serializer.serialize_str("HTTP/2"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for ResponseCookie {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut state = serializer.serialize_struct("ResponseCookie", 3)?;
|
||||
state.serialize_field("name", &self.clone().name)?;
|
||||
state.serialize_field("value", &self.clone().value)?;
|
||||
if let Some(expires) = &self.clone().expires() {
|
||||
state.serialize_field("expires", expires)?;
|
||||
}
|
||||
if let Some(max_age) = &self.clone().max_age() {
|
||||
state.serialize_field("max_age", max_age)?;
|
||||
}
|
||||
if let Some(domain) = &self.clone().domain() {
|
||||
state.serialize_field("domain", domain)?;
|
||||
}
|
||||
if let Some(path) = &self.clone().path() {
|
||||
state.serialize_field("path", path)?;
|
||||
}
|
||||
if self.clone().has_secure() {
|
||||
state.serialize_field("secure", &true)?;
|
||||
}
|
||||
if self.clone().has_httponly() {
|
||||
state.serialize_field("httponly", &true)?;
|
||||
}
|
||||
if let Some(samesite) = &self.clone().samesite() {
|
||||
state.serialize_field("samesite", samesite)?;
|
||||
}
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for Cookie {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut state = serializer.serialize_struct("Cookie", 3)?;
|
||||
state.serialize_field("domain", &self.clone().domain)?;
|
||||
state.serialize_field("include_subdomain", &self.clone().include_subdomain)?;
|
||||
state.serialize_field("path", &self.clone().path)?;
|
||||
state.serialize_field("https", &self.clone().https)?;
|
||||
state.serialize_field("expires", &self.clone().expires)?;
|
||||
state.serialize_field("name", &self.clone().name)?;
|
||||
state.serialize_field("value", &self.clone().value)?;
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for MultipartParam {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
match &self.clone() {
|
||||
MultipartParam::Param(param) => param.serialize(serializer),
|
||||
MultipartParam::FileParam(file_param) => file_param.serialize(serializer),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for FileParam {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut state = serializer.serialize_struct("FileParam", 4)?;
|
||||
state.serialize_field("name", &self.clone().name)?;
|
||||
if let Ok(s) = std::str::from_utf8(&self.clone().data) {
|
||||
state.serialize_field("value", s)?;
|
||||
}
|
||||
state.serialize_field("fileName", &self.clone().filename)?;
|
||||
state.serialize_field("contentType", &self.clone().content_type)?;
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for Value {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
match self {
|
||||
Value::Bool(v) => serializer.serialize_bool(*v),
|
||||
Value::Integer(v) => serializer.serialize_i64(*v),
|
||||
Value::Float(i, d) => {
|
||||
let value = *i as f64 + (*d as f64) / 1_000_000_000_000_000_000.0;
|
||||
serializer.serialize_f64(value)
|
||||
}
|
||||
Value::String(s) => serializer.serialize_str(s),
|
||||
Value::List(values) => serializer.collect_seq(values),
|
||||
Value::Object(values) => serializer.collect_map(values.iter().map(|(k, v)| (k, v))),
|
||||
Value::Nodeset(size) => {
|
||||
let size = *size as i64;
|
||||
serializer.collect_map(vec![
|
||||
("type", serde_json::Value::String("nodeset".to_string())),
|
||||
("size", serde_json::Value::from(size)),
|
||||
])
|
||||
}
|
||||
Value::Bytes(v) => {
|
||||
let encoded = base64::encode(v);
|
||||
serializer.serialize_str(&encoded)
|
||||
}
|
||||
Value::Null => serializer.serialize_none(),
|
||||
Value::Unit => todo!("how to serialize that in json?"),
|
||||
}
|
||||
}
|
||||
}
|
@ -23,9 +23,11 @@
|
||||
//!
|
||||
//!
|
||||
|
||||
pub use self::core::{Error, HurlResult, RunnerError, RunnerOptions};
|
||||
pub use self::cookie::ResponseCookie;
|
||||
pub use self::core::{
|
||||
AssertResult, CaptureResult, EntryResult, Error, HurlResult, RunnerError, RunnerOptions,
|
||||
};
|
||||
pub use self::hurl_file::run as run_hurl_file;
|
||||
pub use self::log_deserialize::parse_results as deserialize_results;
|
||||
pub use self::value::Value;
|
||||
|
||||
mod assert;
|
||||
@ -40,8 +42,6 @@ mod expr;
|
||||
mod http_response;
|
||||
mod hurl_file;
|
||||
mod json;
|
||||
mod log_deserialize;
|
||||
mod log_serialize;
|
||||
mod multipart;
|
||||
mod predicate;
|
||||
mod predicate_value;
|
||||
|
Loading…
Reference in New Issue
Block a user