fhttp_core/postprocessing/
response_handler.rs1use 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}