Merge pull request #20 from Orange-OpenSource/feature/log_serialize_deserialize

Serialize/Deserialize new http request/response
This commit is contained in:
Fabrice Reix 2020-09-15 08:56:59 +02:00 committed by GitHub
commit 1daf83dc99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 766 additions and 183 deletions

View File

@ -34,7 +34,7 @@ use hurl::http;
use hurl::parser;
use hurl::runner;
use hurl::runner::core::*;
use hurl::runner::log;
use hurl::runner::{log_deserialize};
use hurl::format;
@ -207,7 +207,7 @@ fn json_file(matches: ArgMatches, logger: format::logger::Logger) -> (Vec<HurlRe
std::process::exit(127);
}
};
match log::parse_results(v) {
match log_deserialize::parse_results(v) {
Err(msg) => {
logger.error_message(format!("Existing Hurl json can not be parsed! - {}", msg));
std::process::exit(127);

View File

@ -52,6 +52,23 @@ pub enum Method {
Patch,
}
impl fmt::Display for Method {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let value = match self {
Method::Get => "GET",
Method::Head => "HEAD",
Method::Post => "POST",
Method::Put => "PUT",
Method::Delete => "DELETE",
Method::Connect => "CONNECT",
Method::Options => "OPTIONS",
Method::Trace => "TRACE",
Method::Patch => "PATCH"
};
write!(f, "{}", value)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Version {
Http10,
@ -171,4 +188,45 @@ pub mod tests {
form: vec![],
}
}
pub fn custom_http_request() -> Request {
Request {
method: Method::Get,
url: "http://localhost/custom".to_string(),
querystring: vec![],
headers: vec![
Header { name: String::from("User-Agent"), value: String::from("iPhone") },
Header { name: String::from("Foo"), value: String::from("Bar") },
],
cookies: vec![
RequestCookie {
name: String::from("theme"),
value: String::from("light"),
},
RequestCookie {
name: String::from("sessionToken"),
value: String::from("abc123"),
}
],
body: vec![],
multipart: vec![],
form: vec![],
}
}
pub fn form_http_request() -> Request {
Request {
method: Method::Post,
url: "http://localhost/form-params".to_string(),
querystring: vec![],
headers: vec![
Header { name: String::from("Content-Type"), value: String::from("application/x-www-form-urlencoded") },
],
cookies: vec![],
body: "param1=value1&param2=&param3=a%3db&param4=a%253db".to_string().into_bytes(),
multipart: vec![],
form: vec![]
}
}
}

View File

@ -25,6 +25,18 @@
/// and not by the http client.
///
use crate::http::libcurl::core::Response;
impl Response {
pub fn cookies(&self) -> Vec<ResponseCookie> {
self.headers
.iter()
.filter(|&h| h.name.to_lowercase() == "set-cookie")
.filter_map(|h| ResponseCookie::parse(h.value.clone()))
.collect()
}
}
///
/// Cookie return from HTTP Response
/// It contains arbitrary attributes.

View File

@ -1,180 +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::{Serializer, SerializeStruct};
use serde::Serialize;
use crate::http;
use super::core::*;
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 { source_info, 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())?;
//let (_type, value) = self.value.to_json_value();
//state.serialize_field("type", &_type)?;
state.serialize_field("value", &self.value)?;
state.end()
}
}
// http-specific
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 = match value.get("cookies") {
None => vec![],
Some(serde_json::Value::Array(values)) => {
let mut cookies: Vec<http::cookie::Cookie> = vec![];
for value in values {
let cookie = http::import::parse_cookie(value.clone())?;
cookies.push(cookie);
}
cookies
}
Some(_) => return Err("expecting list for cookies".to_string()),
};
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 = http::import::parse_request(v.clone())?;
Some(r)
}
};
let response = match value.get("response") {
None => None,
Some(v) => {
let r = http::import::parse_response(v.clone())?;
Some(r)
}
};
Ok(EntryResult {
request,
response,
captures: vec![],
asserts: vec![],
errors: vec![],
time_in_ms: 0,
})
}

View File

@ -0,0 +1,455 @@
/*
* 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 crate::http::libcurl::core::*;
use super::cookie::*;
use super::core::*;
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 = http::import::parse_request(v.clone())?;
Some(r)
}
};
let response = match value.get("response") {
None => None,
Some(v) => {
let r = http::import::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 = vec![];
Ok(Request {
method,
url,
querystring,
headers,
cookies,
body,
multipart,
form,
})
} 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![],
};
Ok(Response {
version,
status,
headers,
body: vec![],
})
} 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())
}
}
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 crate::http::libcurl::core::tests::*;
use super::*;
#[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&param2=a%20b",
"headers": []
}"#).unwrap();
assert_eq!(parse_request(v).unwrap(), Request {
method: Method::Get,
url: "http://localhost:8000/querystring-params?param1=value1&param2=a%20b".to_string(),
querystring: vec![],
headers: vec![],
cookies: vec![],
body: vec![],
form: vec![],
multipart: vec![],
});
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![],
});
}
#[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);
}
}

237
src/runner/log_serialize.rs Normal file
View File

@ -0,0 +1,237 @@
/*
* 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::{Serializer, SerializeStruct};
use serde::Serialize;
use crate::http::libcurl::core::*;
use super::cookie::*;
use super::core::*;
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 { source_info, 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,
{
// 3 is the number of fields in the struct.
let mut state = serializer.serialize_struct("??", 3)?;
state.serialize_field("method", &self.clone().method.to_string())?;
state.serialize_field("url", &self.clone().url)?;
state.serialize_field("queryString", &self.clone().querystring)?;
state.serialize_field("headers", &self.clone().headers)?;
state.serialize_field("cookies", &self.clone().cookies)?;
if !self.clone().form.is_empty() {
state.serialize_field("form", &self.clone().form)?;
}
state.serialize_field("body", &base64::encode(&self.body))?;
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("??", 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
// let content_type = self.get_header("content_type", true);
// if let Some(value) = content_type.first() {
// if value.as_str() == "application/json; charset=UTF-8" {
// let s = String::from_utf8(self.body.clone()).expect("Found invalid UTF-8");
// let result: Result<serde_json::Value, serde_json::Error> = serde_json::from_str(s.as_str());
// if let Ok(v) = result {
// state.serialize_field("json", &v)?;
// }
// }
// }
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 Cookie {
// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
// where
// S: Serializer,
// {
// let mut state = serializer.serialize_struct("InternalCookie", 3)?;
// state.serialize_field("name", &self.clone().name)?;
// state.serialize_field("value", &self.clone().value)?;
// state.serialize_field("domain", &self.clone().domain)?;
// state.serialize_field("path", &self.clone().path)?;
// state.serialize_field("include_subdomain", &self.clone().subdomains)?;
// 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()
}
}

View File

@ -32,7 +32,8 @@ mod entry;
pub mod file;
mod http_response;
mod json;
pub mod log;
pub mod log_serialize;
pub mod log_deserialize;
mod predicate;
mod query;
pub mod request;