Skip to content

Commit 081480a

Browse files
committed
graphql: Make sure that undefined arguments are ignored
1 parent 95ee91a commit 081480a

File tree

2 files changed

+53
-0
lines changed

2 files changed

+53
-0
lines changed

graphql/src/execution/query.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,12 @@ impl<'a> std::fmt::Display for SelectedFields<'a> {
106106
/// A GraphQL query that has been preprocessed and checked and is ready
107107
/// for execution. Checking includes validating all query fields and, if
108108
/// desired, checking the query's complexity
109+
//
110+
// The implementation contains various workarounds to make it compatible
111+
// with the previous implementation when it comes to queries that are not
112+
// fully spec compliant and should be rejected through rigorous validation
113+
// against the GraphQL spec. Once we do validate queries, code that is
114+
// marked with `graphql-bug-compat` can be deleted.
109115
pub struct Query {
110116
/// The schema against which to execute the query
111117
pub schema: Arc<ApiSchema>,
@@ -791,6 +797,7 @@ impl Transform {
791797

792798
let resolver = |name: &str| self.schema.get_named_type(name);
793799

800+
let mut defined_args: usize = 0;
794801
for argument_def in sast::get_argument_definitions(ty, field_name)
795802
.into_iter()
796803
.flatten()
@@ -799,6 +806,9 @@ impl Transform {
799806
.iter_mut()
800807
.find(|arg| &arg.0 == &argument_def.name)
801808
.map(|arg| &mut arg.1);
809+
if arg_value.is_some() {
810+
defined_args += 1;
811+
}
802812
match coercion::coerce_input_value(
803813
arg_value.as_deref().cloned(),
804814
&argument_def,
@@ -820,6 +830,18 @@ impl Transform {
820830
}
821831
}
822832

833+
// see: graphql-bug-compat
834+
// avoids error 'unknown argument on field'
835+
if defined_args < arguments.len() {
836+
// `arguments` contains undefined arguments, remove them
837+
match sast::get_argument_definitions(ty, field_name) {
838+
None => arguments.clear(),
839+
Some(arg_defs) => {
840+
arguments.retain(|(name, _)| arg_defs.iter().any(|def| &def.name == name))
841+
}
842+
}
843+
}
844+
823845
if errors.is_empty() {
824846
Ok(())
825847
} else {

graphql/tests/query.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1421,6 +1421,37 @@ fn can_use_nested_filter() {
14211421
})
14221422
}
14231423

1424+
// see: graphql-bug-compat
1425+
#[test]
1426+
fn ignores_invalid_field_arguments() {
1427+
run_test_sequentially(|store| async move {
1428+
let deployment = setup(store.as_ref());
1429+
// This query has to return all the musicians since `id` is not a
1430+
// valid argument for the `musicians` field and must therefore be
1431+
// ignored
1432+
let result = execute_query_document(
1433+
&deployment.hash,
1434+
graphql_parser::parse_query("query { musicians(id: \"m1\") { id } } ")
1435+
.expect("invalid test query")
1436+
.into_static(),
1437+
)
1438+
.await;
1439+
1440+
let data = extract_data!(result).unwrap();
1441+
match data {
1442+
r::Value::Object(obj) => match obj.get("musicians").unwrap() {
1443+
r::Value::List(lst) => {
1444+
assert_eq!(4, lst.len());
1445+
}
1446+
_ => panic!("expected a list of values"),
1447+
},
1448+
_ => {
1449+
panic!("expected an object")
1450+
}
1451+
}
1452+
})
1453+
}
1454+
14241455
async fn check_musicians_at(
14251456
id: &DeploymentHash,
14261457
query: &str,

0 commit comments

Comments
 (0)