@@ -4,14 +4,14 @@ use crate::executable::OperationType;
4
4
use crate :: execution:: engine:: execute_selection_set;
5
5
use crate :: execution:: engine:: ExecutionMode ;
6
6
use crate :: execution:: resolver:: ResolvedValue ;
7
+ use crate :: execution:: GraphQLError ;
7
8
use crate :: execution:: JsonMap ;
8
9
use crate :: execution:: Response ;
9
10
use crate :: execution:: SchemaIntrospectionError ;
10
11
use crate :: execution:: SchemaIntrospectionSplit ;
11
12
use crate :: schema;
12
13
use crate :: schema:: Implementers ;
13
14
use crate :: schema:: Name ;
14
- use crate :: validation:: SuspectedValidationBug ;
15
15
use crate :: validation:: Valid ;
16
16
use crate :: ExecutableDocument ;
17
17
use crate :: Node ;
@@ -47,13 +47,12 @@ impl SchemaIntrospectionQuery {
47
47
/// Generally [`split`][SchemaIntrospectionSplit::split] should be used instead.
48
48
///
49
49
/// [schema introspection]: https://spec.graphql.org/October2021/#sec-Schema-Introspection
50
- #[ doc( hidden) ]
51
- // Hidden to discourage usage, but pub to allow Router "both" mode to use legacy code
52
- // for deciding what is or isn’t an introspection query.
53
- pub fn assume_only_intropsection_fields (
50
+ pub ( crate ) fn assume_only_intropsection_fields (
54
51
document : Valid < ExecutableDocument > ,
55
52
) -> Result < Self , SchemaIntrospectionError > {
56
- super :: introspection_max_depth:: check_document ( & document) ?;
53
+ let operation = document. operations . get ( None ) . unwrap ( ) ;
54
+ super :: introspection_max_depth:: check_introspection_max_depth ( & document, operation)
55
+ . map_err ( SchemaIntrospectionError :: DeeplyNestedIntrospectionList ) ?;
57
56
Ok ( Self ( document) )
58
57
}
59
58
@@ -72,19 +71,17 @@ impl SchemaIntrospectionQuery {
72
71
execute_non_introspection_parts : impl FnOnce ( & Valid < ExecutableDocument > ) -> Response ,
73
72
) -> Response {
74
73
match SchemaIntrospectionSplit :: split ( schema, document, operation) {
75
- Ok ( SchemaIntrospectionSplit :: Only ( introspection_query) ) => introspection_query
76
- . execute ( schema, variable_values)
77
- . unwrap_or_else ( |err| err . into_response ( & document . sources ) ) ,
74
+ Ok ( SchemaIntrospectionSplit :: Only ( introspection_query) ) => {
75
+ introspection_query . execute ( schema, variable_values)
76
+ }
78
77
Ok ( SchemaIntrospectionSplit :: None ) => execute_non_introspection_parts ( document) ,
79
78
Ok ( SchemaIntrospectionSplit :: Both {
80
79
introspection_query,
81
80
filtered_document : filtered_operation,
82
81
} ) => {
83
82
let non_introspection_response =
84
83
execute_non_introspection_parts ( & filtered_operation) ;
85
- let introspection_response = introspection_query
86
- . execute ( schema, variable_values)
87
- . unwrap_or_else ( |err| err. into_response ( & document. sources ) ) ;
84
+ let introspection_response = introspection_query. execute ( schema, variable_values) ;
88
85
non_introspection_response. merge ( introspection_response)
89
86
}
90
87
Err ( err) => err. into_response ( & document. sources ) ,
@@ -95,49 +92,65 @@ impl SchemaIntrospectionQuery {
95
92
/// that can also be converted with [`into_response`][SuspectedValidationBug::into_response].
96
93
///
97
94
/// [request error]: https://spec.graphql.org/October2021/#sec-Errors.Request-errors
98
- pub fn execute (
99
- & self ,
100
- schema : & Valid < Schema > ,
101
- variable_values : & Valid < JsonMap > ,
102
- ) -> Result < Response , SuspectedValidationBug > {
95
+ pub fn execute ( & self , schema : & Valid < Schema > , variable_values : & Valid < JsonMap > ) -> Response {
103
96
let operation = self . 0 . operations . get ( None ) . unwrap ( ) ;
104
- debug_assert_eq ! ( operation. operation_type, OperationType :: Query ) ;
105
-
106
- // https://spec.graphql.org/October2021/#sec-Query
107
- let object_type_name = operation. object_type ( ) ;
108
- let object_type_def =
109
- schema
110
- . get_object ( object_type_name)
111
- . ok_or_else ( || SuspectedValidationBug {
112
- message : format ! (
113
- "Root operation type {object_type_name} is undefined or not an object type."
114
- ) ,
115
- location : None ,
116
- } ) ?;
117
- let implementers_map = & OnceLock :: new ( ) ;
118
- let initial_value = & IntrospectionRootResolver ( SchemaWithCache {
119
- schema,
120
- implementers_map,
121
- } ) ;
97
+ execute_introspection_only_query ( schema, & self . 0 , operation, variable_values)
98
+ }
99
+ }
122
100
123
- let mut errors = Vec :: new ( ) ;
124
- let path = None ;
125
- let data = execute_selection_set (
126
- schema,
127
- & self . 0 ,
128
- variable_values,
129
- & mut errors,
130
- path,
131
- ExecutionMode :: Normal ,
132
- object_type_def,
133
- initial_value,
134
- & operation. selection_set . selections ,
135
- ) ;
136
- Ok ( Response {
137
- data : data. into ( ) ,
138
- errors,
139
- extensions : Default :: default ( ) ,
140
- } )
101
+ /// Execute a query whose [root fields][Operation::root_fields] are all intropsection meta-fields:
102
+ /// `__schema`, `__type`, or `__typename`.
103
+ ///
104
+ /// Returns an error if `operation_name` does not [correspond to a an operation definition](https://spec.graphql.org/October2021/#GetOperation())
105
+ pub fn execute_introspection_only_query (
106
+ schema : & Valid < Schema > ,
107
+ document : & Valid < ExecutableDocument > ,
108
+ operation : & Node < Operation > ,
109
+ variable_values : & Valid < JsonMap > ,
110
+ ) -> Response {
111
+ if operation. operation_type != OperationType :: Query {
112
+ return Response :: from_request_error ( GraphQLError :: new (
113
+ format ! (
114
+ "execute_introspection_only_query called with a {}" ,
115
+ operation. operation_type. name( )
116
+ ) ,
117
+ operation. location ( ) ,
118
+ & document. sources ,
119
+ ) ) ;
120
+ }
121
+
122
+ // https://spec.graphql.org/October2021/#sec-Query
123
+ let object_type_name = operation. object_type ( ) ;
124
+ let Some ( object_type_def) = schema. get_object ( object_type_name) else {
125
+ return Response :: from_request_error ( GraphQLError :: new (
126
+ "Undefined root operation type" ,
127
+ object_type_name. location ( ) ,
128
+ & document. sources ,
129
+ ) ) ;
130
+ } ;
131
+ let implementers_map = & OnceLock :: new ( ) ;
132
+ let initial_value = & IntrospectionRootResolver ( SchemaWithCache {
133
+ schema,
134
+ implementers_map,
135
+ } ) ;
136
+
137
+ let mut errors = Vec :: new ( ) ;
138
+ let path = None ;
139
+ let data = execute_selection_set (
140
+ schema,
141
+ document,
142
+ variable_values,
143
+ & mut errors,
144
+ path,
145
+ ExecutionMode :: Normal ,
146
+ object_type_def,
147
+ initial_value,
148
+ & operation. selection_set . selections ,
149
+ ) ;
150
+ Response {
151
+ data : data. into ( ) ,
152
+ errors,
153
+ extensions : Default :: default ( ) ,
141
154
}
142
155
}
143
156
0 commit comments