fhttp_core/postprocessing/
response_handler.rs

1use std::fmt::Debug;
2
3use anyhow::{bail, Context, Result};
4
5#[derive(Debug, Eq, PartialEq, Clone)]
6pub enum ResponseHandler {
7    Json { json_path: String },
8    Deno { program: String },
9}
10
11impl ResponseHandler {
12    pub fn process_body(&self, body: &str) -> Result<String> {
13        match self {
14            ResponseHandler::Json { json_path } => process_body_json(json_path, body),
15            ResponseHandler::Deno { .. } => {
16                bail!("deno response handlers are no longer supported.")
17            }
18        }
19    }
20}
21
22fn process_body_json(json_path: &str, body: &str) -> Result<String> {
23    use jsonpath_lib::Selector;
24    use serde_json::Value;
25
26    let value: Value = serde_json::from_str(body)
27        .with_context(|| format!("failed to parse response body as json\nBody was '{}'", body))?;
28
29    let mut selector = Selector::new();
30    let json_path_results = selector
31        .str_path(json_path)
32        .unwrap()
33        .value(&value)
34        .select()
35        .unwrap();
36    let result = match json_path_results.len() {
37        0 => Value::String("".into()),
38        _ => json_path_results[0].clone(),
39    };
40
41    match result {
42        Value::String(string) => Ok(string),
43        _ => Ok(serde_json::to_string(&result).unwrap()),
44    }
45}
46
47#[cfg(test)]
48mod json_tests {
49    use indoc::indoc;
50
51    use super::*;
52
53    #[test]
54    fn should_apply_the_jsonpath_expression() {
55        let body = indoc!(
56            "
57            {
58                \"a\": {
59                    \"b\": {
60                        \"c\": \"success\"
61                    },
62                    \"c\": \"failure\"
63                }
64            }
65        "
66        );
67        let handler = ResponseHandler::Json {
68            json_path: "$.a.b.c".into(),
69        };
70        let result = handler.process_body(body);
71
72        assert_ok!(result, String::from("success"));
73    }
74
75    #[test]
76    fn should_convert_numbers_to_string() {
77        let body = indoc!(
78            "
79            {
80                \"a\": {
81                    \"b\": {
82                        \"c\": 3.141
83                    }
84                }
85            }
86        "
87        );
88        let handler = ResponseHandler::Json {
89            json_path: "$.a.b.c".into(),
90        };
91        let result = handler.process_body(body);
92
93        assert_ok!(result, String::from("3.141"));
94    }
95}
96
97#[cfg(test)]
98mod deno_tests {
99    use super::*;
100
101    #[test]
102    fn should_not_support_deno_anymore() {
103        let body = "this is the response body";
104        let handler = ResponseHandler::Deno { program: "".into() };
105        let result = handler.process_body(body);
106
107        assert_err!(result, "deno response handlers are no longer supported.");
108    }
109}