use relay_protocol::{Annotated, Empty, FromValue, IntoValue, Object, Value};
use crate::processor::ProcessValue;
use crate::protocol::{Cookies, Headers};
#[derive(Clone, Debug, Default, PartialEq, Empty, FromValue, IntoValue, ProcessValue)]
pub struct ResponseContext {
#[metastructure(pii = "true", max_depth = 5, max_bytes = 2048)]
#[metastructure(skip_serialization = "empty")]
pub cookies: Annotated<Cookies>,
#[metastructure(pii = "true", max_depth = 7, max_bytes = 8192)]
#[metastructure(skip_serialization = "empty")]
pub headers: Annotated<Headers>,
pub status_code: Annotated<u64>,
pub body_size: Annotated<u64>,
#[metastructure(pii = "true", max_depth = 7, max_bytes = 8192)]
pub data: Annotated<Value>,
#[metastructure(skip_serialization = "empty")]
pub inferred_content_type: Annotated<String>,
#[metastructure(additional_properties, retain = "true", pii = "maybe")]
pub other: Object<Value>,
}
impl super::DefaultContext for ResponseContext {
fn default_key() -> &'static str {
"response"
}
fn from_context(context: super::Context) -> Option<Self> {
match context {
super::Context::Response(c) => Some(*c),
_ => None,
}
}
fn cast(context: &super::Context) -> Option<&Self> {
match context {
super::Context::Response(c) => Some(c),
_ => None,
}
}
fn cast_mut(context: &mut super::Context) -> Option<&mut Self> {
match context {
super::Context::Response(c) => Some(c),
_ => None,
}
}
fn into_context(self) -> super::Context {
super::Context::Response(Box::new(self))
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::protocol::{Context, PairList};
#[test]
fn test_response_context_roundtrip() {
let json = r#"{
"cookies": [
[
"PHPSESSID",
"298zf09hf012fh2"
],
[
"csrftoken",
"u32t4o3tb3gg43"
],
[
"_gat",
"1"
]
],
"headers": [
[
"Content-Type",
"text/html"
]
],
"status_code": 500,
"body_size": 1000,
"data": {
"some": 1
},
"inferred_content_type": "application/json",
"arbitrary_field": "arbitrary",
"type": "response"
}"#;
let cookies =
Cookies::parse("PHPSESSID=298zf09hf012fh2; csrftoken=u32t4o3tb3gg43; _gat=1;;")
.unwrap();
let headers = vec![Annotated::new((
Annotated::new("content-type".to_string().into()),
Annotated::new("text/html".to_string().into()),
))];
let context = Annotated::new(Context::Response(Box::new(ResponseContext {
cookies: Annotated::new(cookies),
headers: Annotated::new(Headers(PairList(headers))),
status_code: Annotated::new(500),
body_size: Annotated::new(1000),
data: {
let mut map = Object::new();
map.insert("some".to_string(), Annotated::new(Value::I64(1)));
Annotated::new(Value::Object(map))
},
inferred_content_type: Annotated::new("application/json".to_string()),
other: {
let mut map = Object::new();
map.insert(
"arbitrary_field".to_string(),
Annotated::new(Value::String("arbitrary".to_string())),
);
map
},
})));
assert_eq!(context, Annotated::from_json(json).unwrap());
assert_eq!(json, context.to_json_pretty().unwrap());
}
}