relay_event_schema/protocol/contexts/
response.rs1use relay_protocol::{Annotated, Empty, FromValue, IntoValue, Object, Value};
2
3use crate::processor::ProcessValue;
4use crate::protocol::{Cookies, Headers};
5
6#[derive(Clone, Debug, Default, PartialEq, Empty, FromValue, IntoValue, ProcessValue)]
11pub struct ResponseContext {
12 #[metastructure(pii = "true", max_depth = 5, max_bytes = 2048)]
16 #[metastructure(skip_serialization = "empty")]
17 pub cookies: Annotated<Cookies>,
18
19 #[metastructure(pii = "true", max_depth = 7, max_bytes = 8192)]
24 #[metastructure(skip_serialization = "empty")]
25 pub headers: Annotated<Headers>,
26
27 pub status_code: Annotated<u64>,
29
30 pub body_size: Annotated<u64>,
32
33 #[metastructure(pii = "true", max_depth = 7, max_bytes = 8192)]
38 pub data: Annotated<Value>,
39
40 #[metastructure(skip_serialization = "empty")]
42 pub inferred_content_type: Annotated<String>,
43
44 #[metastructure(additional_properties, retain = true, pii = "maybe")]
48 pub other: Object<Value>,
49}
50
51impl super::DefaultContext for ResponseContext {
52 fn default_key() -> &'static str {
53 "response"
54 }
55
56 fn from_context(context: super::Context) -> Option<Self> {
57 match context {
58 super::Context::Response(c) => Some(*c),
59 _ => None,
60 }
61 }
62
63 fn cast(context: &super::Context) -> Option<&Self> {
64 match context {
65 super::Context::Response(c) => Some(c),
66 _ => None,
67 }
68 }
69
70 fn cast_mut(context: &mut super::Context) -> Option<&mut Self> {
71 match context {
72 super::Context::Response(c) => Some(c),
73 _ => None,
74 }
75 }
76
77 fn into_context(self) -> super::Context {
78 super::Context::Response(Box::new(self))
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85 use crate::protocol::{Context, PairList};
86
87 #[test]
88 fn test_response_context_roundtrip() {
89 let json = r#"{
90 "cookies": [
91 [
92 "PHPSESSID",
93 "298zf09hf012fh2"
94 ],
95 [
96 "csrftoken",
97 "u32t4o3tb3gg43"
98 ],
99 [
100 "_gat",
101 "1"
102 ]
103 ],
104 "headers": [
105 [
106 "Content-Type",
107 "text/html"
108 ]
109 ],
110 "status_code": 500,
111 "body_size": 1000,
112 "data": {
113 "some": 1
114 },
115 "inferred_content_type": "application/json",
116 "arbitrary_field": "arbitrary",
117 "type": "response"
118}"#;
119
120 let cookies =
121 Cookies::parse("PHPSESSID=298zf09hf012fh2; csrftoken=u32t4o3tb3gg43; _gat=1;;")
122 .unwrap();
123 let headers = vec![Annotated::new((
124 Annotated::new("content-type".to_string().into()),
125 Annotated::new("text/html".to_string().into()),
126 ))];
127 let context = Annotated::new(Context::Response(Box::new(ResponseContext {
128 cookies: Annotated::new(cookies),
129 headers: Annotated::new(Headers(PairList(headers))),
130 status_code: Annotated::new(500),
131 body_size: Annotated::new(1000),
132 data: {
133 let mut map = Object::new();
134 map.insert("some".to_string(), Annotated::new(Value::I64(1)));
135 Annotated::new(Value::Object(map))
136 },
137 inferred_content_type: Annotated::new("application/json".to_string()),
138 other: {
139 let mut map = Object::new();
140 map.insert(
141 "arbitrary_field".to_string(),
142 Annotated::new(Value::String("arbitrary".to_string())),
143 );
144 map
145 },
146 })));
147
148 assert_eq!(context, Annotated::from_json(json).unwrap());
149 assert_eq!(json, context.to_json_pretty().unwrap());
150 }
151}