Skip to content

Commit d751c03

Browse files
Add shape validation for request variable
1 parent 5dbba1d commit d751c03

File tree

4 files changed

+81
-5
lines changed

4 files changed

+81
-5
lines changed

apollo-federation/src/sources/connect/validation/expression.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
44
use std::ops::Range;
55
use std::str::FromStr;
6+
use std::sync::LazyLock;
67

78
use apollo_compiler::collections::IndexMap;
89
use apollo_compiler::parser::LineColumn;
@@ -24,6 +25,17 @@ use crate::sources::connect::validation::coordinates::ConnectDirectiveCoordinate
2425
use crate::sources::connect::validation::graphql::GraphQLString;
2526
use crate::sources::connect::validation::graphql::SchemaInfo;
2627

28+
static REQUEST_SHAPE: LazyLock<Shape> = LazyLock::new(|| {
29+
Shape::record(
30+
[(
31+
"headers".to_string(),
32+
Shape::dict(Shape::list(Shape::string([]), []), []),
33+
)]
34+
.into(),
35+
[],
36+
)
37+
});
38+
2739
/// Details about the available variables and shapes for the current expression.
2840
/// These should be consistent for all pieces of a connector in the request phase.
2941
pub(super) struct Context<'schema> {
@@ -53,7 +65,7 @@ impl<'schema> Context<'schema> {
5365
(Namespace::Args, shape_for_arguments(field_def)),
5466
(Namespace::Config, Shape::unknown([])),
5567
(Namespace::Context, Shape::unknown([])),
56-
(Namespace::Request, Shape::unknown([])),
68+
(Namespace::Request, REQUEST_SHAPE.clone()),
5769
]
5870
.into_iter()
5971
.collect();
@@ -75,7 +87,7 @@ impl<'schema> Context<'schema> {
7587
(Namespace::Batch, Shape::list(Shape::from(type_def), [])),
7688
(Namespace::Config, Shape::unknown([])),
7789
(Namespace::Context, Shape::unknown([])),
78-
(Namespace::Request, Shape::unknown([])),
90+
(Namespace::Request, REQUEST_SHAPE.clone()),
7991
]
8092
.into_iter()
8193
.collect();
@@ -99,6 +111,7 @@ impl<'schema> Context<'schema> {
99111
let var_lookup: IndexMap<Namespace, Shape> = [
100112
(Namespace::Config, Shape::unknown([])),
101113
(Namespace::Context, Shape::unknown([])),
114+
(Namespace::Request, REQUEST_SHAPE.clone()),
102115
]
103116
.into_iter()
104117
.collect();

apollo-federation/src/sources/connect/validation/snapshots/validation_tests@headers__invalid_namespace_in_header_variables.graphql.snap

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,21 @@ input_file: apollo-federation/src/sources/connect/validation/test_data/headers/i
66
[
77
Message {
88
code: InvalidHeader,
9-
message: "In `@source(http.headers:)`: unknown variable `$foo`, must be one of $config, $context",
9+
message: "In `@source(http.headers:)`: unknown variable `$foo`, must be one of $config, $context, $request",
1010
locations: [
1111
11:49..11:53,
1212
],
1313
},
1414
Message {
1515
code: InvalidHeader,
16-
message: "In `@source(http.headers:)`: $this is not valid here, must be one of $config, $context",
16+
message: "In `@source(http.headers:)`: $this is not valid here, must be one of $config, $context, $request",
1717
locations: [
1818
12:62..12:67,
1919
],
2020
},
2121
Message {
2222
code: InvalidHeader,
23-
message: "In `@source(http.headers:)`: `config.bar` must start with one of $config, $context",
23+
message: "In `@source(http.headers:)`: `config.bar` must start with one of $config, $context, $request",
2424
locations: [
2525
13:56..13:62,
2626
],
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
---
2+
source: apollo-federation/src/sources/connect/validation/mod.rs
3+
expression: "format!(\"{:#?}\", result.errors)"
4+
input_file: apollo-federation/src/sources/connect/validation/test_data/request_headers.graphql
5+
---
6+
[
7+
Message {
8+
code: InvalidHeader,
9+
message: "In `@source(http.headers:)`: array values aren't valid here",
10+
locations: [
11+
5:101..5:111,
12+
5:101..5:111,
13+
],
14+
},
15+
Message {
16+
code: InvalidHeader,
17+
message: "In `@connect(http.headers:)` on `Query.failOnArray`: array values aren't valid here",
18+
locations: [
19+
28:68..28:78,
20+
28:68..28:78,
21+
],
22+
},
23+
Message {
24+
code: InvalidUrl,
25+
message: "In `GET` in `@connect(http:)` on `Query.failOnArray`: array values aren't valid here",
26+
locations: [
27+
27:61..27:71,
28+
27:61..27:71,
29+
],
30+
},
31+
]
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
extend schema
2+
@link(url: "https://specs.apollo.dev/connect/v0.1", import: ["@connect", "@source"])
3+
@source(
4+
name: "invalid_api"
5+
http: { baseURL: "http://127.0.0.1", headers: [{ name: "x-my-header", value: "{$request.headers.someheader}" }] }
6+
)
7+
@source(
8+
name: "awesome_api"
9+
http: {
10+
baseURL: "http://127.0.0.1"
11+
headers: [{ name: "x-my-header", value: "{$request.headers.someheader->first}" }]
12+
}
13+
)
14+
15+
type Query {
16+
pass: [String!]!
17+
@connect(
18+
http: {
19+
GET: "http://127.0.0.1/?something={$request.headers.someheader->first}"
20+
headers: [{ name: "x-my-header", value: "{$request.headers.someheader->first}" }]
21+
}
22+
selection: "$"
23+
)
24+
failOnArray: [String!]!
25+
@connect(
26+
http: {
27+
GET: "http://127.0.0.1/?something={$request.headers.someheader}"
28+
headers: [{ name: "x-my-header", value: "{$request.headers.someheader}" }]
29+
}
30+
selection: "$"
31+
)
32+
}

0 commit comments

Comments
 (0)