Skip to content

Commit

Permalink
Pre-parse JSONPath in collection
Browse files Browse the repository at this point in the history
  • Loading branch information
LucasPickering committed Oct 25, 2023
1 parent 1929bb0 commit a36a9d6
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 33 deletions.
4 changes: 2 additions & 2 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use anyhow::{anyhow, Context};
use derive_more::{Deref, Display, From};
use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
use serde_json_path::JsonPath;
use std::{
future::Future,
path::{Path, PathBuf},
Expand Down Expand Up @@ -106,8 +107,7 @@ pub struct Chain {
#[serde(default)]
pub sensitive: bool,
/// JSONpath to extract a value from the response. For JSON data only.
// TODO strong typing on this
pub selector: Option<String>,
pub selector: Option<JsonPath>,
}

/// The source of data for a chain
Expand Down
37 changes: 6 additions & 31 deletions src/template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,23 +356,16 @@ impl<'a> ChainTemplateSource<'a> {
fn apply_selector(
&self,
value: Cow<'_, str>,
selector: &'a str,
selector: &JsonPath,
) -> Result<Cow<'a, str>, ChainError> {
// Parse the JSON path
let path =
JsonPath::parse(selector).map_err(|err| ChainError::JsonPath {
selector: selector.to_owned(),
error: err,
})?;

// Parse the response as JSON. Intentionally ignore the
// content-type. If the user wants to treat it as JSON, we
// should allow that even if the server is wrong.
let json_value = Json::parse(&value)
.map_err(|err| ChainError::ParseResponse { error: err })?;

// Apply the path to the json
let found_value = path
let found_value = selector
.query(&json_value)
.exactly_one()
.map_err(|err| ChainError::InvalidResult { error: err })?;
Expand Down Expand Up @@ -451,12 +444,6 @@ pub enum ChainError {
/// response
#[error("No response available")]
NoResponse,
#[error("Error parsing JSON path {selector:?}")]
JsonPath {
selector: String,
#[source]
error: serde_json_path::ParseError,
},
/// Failed to parse the response body before applying a selector
#[error("Error parsing response")]
ParseResponse {
Expand Down Expand Up @@ -561,11 +548,12 @@ mod tests {
)
.await
.unwrap();
let selector = selector.map(|s| s.parse().unwrap());
let chains = vec![create!(
Chain,
id: "chain1".into(),
source: ChainSource::Request(recipe_id),
selector: selector.map(String::from),
selector: selector,
)];
let context = create!(
TemplateContext, repository: repository, chains: chains,
Expand All @@ -591,20 +579,7 @@ mod tests {
Chain,
id: "chain1".into(),
source: ChainSource::Request("recipe1".into()),
selector: Some("$.".into()),
),
Some((
create!(Request, recipe_id: "recipe1".into()),
create!(Response, body: "{}".into()),
)),
"Error parsing JSON path \"$.\"",
)]
#[case(
create!(
Chain,
id: "chain1".into(),
source: ChainSource::Request("recipe1".into()),
selector: Some("$.message".into()),
selector: Some("$.message".parse().unwrap()),
),
Some((
create!(Request, recipe_id: "recipe1".into()),
Expand All @@ -617,7 +592,7 @@ mod tests {
Chain,
id: "chain1".into(),
source: ChainSource::Request("recipe1".into()),
selector: Some("$.*".into()),
selector: Some("$.*".parse().unwrap()),
),
Some((
create!(Request, recipe_id: "recipe1".into()),
Expand Down

0 comments on commit a36a9d6

Please sign in to comment.