1616from typing_extensions import Literal , TypeGuard
1717
1818from graphql import ExecutionResult , GraphQLError
19- from graphql .language import OperationType
19+ from graphql .language import OperationType , DocumentNode
2020from graphql .type import GraphQLSchema
2121
2222from graphql_server import execute , subscribe
@@ -171,7 +171,9 @@ def create_response(
171171 ) -> Response : ...
172172
173173 @abc .abstractmethod
174- async def render_graphql_ide (self , request : Request ) -> Response : ...
174+ async def render_graphql_ide (
175+ self , request : Request , request_data : GraphQLRequestData
176+ ) -> Response : ...
175177
176178 async def create_streaming_response (
177179 self ,
@@ -198,18 +200,14 @@ async def create_websocket_response(
198200 ) -> WebSocketResponse : ...
199201
200202 async def execute_operation (
201- self , request : Request , context : Context , root_value : Optional [RootValue ]
203+ self ,
204+ request : Request ,
205+ request_data : GraphQLRequestData ,
206+ context : Context ,
207+ root_value : Optional [RootValue ],
202208 ) -> ExecutionResult :
203209 request_adapter = self .request_adapter_class (request )
204210
205- try :
206- request_data = await self .parse_http_body (request_adapter )
207- except json .decoder .JSONDecodeError as e :
208- raise HTTPException (400 , "Unable to parse request body as JSON" ) from e
209- # DO this only when doing files
210- except KeyError as e :
211- raise HTTPException (400 , "File(s) missing in form data" ) from e
212-
213211 allowed_operation_types = operation_type_from_http (request_adapter .method )
214212
215213 if not self .allow_queries_via_get and request_adapter .method == "GET" :
@@ -343,14 +341,25 @@ async def run(
343341 if not self .is_request_allowed (request_adapter ):
344342 raise HTTPException (405 , "GraphQL only supports GET and POST requests." )
345343
344+ try :
345+ request_data = await self .parse_http_body (request_adapter )
346+ except json .decoder .JSONDecodeError as e :
347+ raise HTTPException (400 , "Unable to parse request body as JSON" ) from e
348+ # DO this only when doing files
349+ except KeyError as e :
350+ raise HTTPException (400 , "File(s) missing in form data" ) from e
351+
346352 if self .should_render_graphql_ide (request_adapter ):
347353 if self .graphql_ide :
348- return await self .render_graphql_ide (request )
354+ return await self .render_graphql_ide (request , request_data )
349355 raise HTTPException (404 , "Not Found" )
350356
351357 try :
352358 result = await self .execute_operation (
353- request = request , context = context , root_value = root_value
359+ request = request ,
360+ request_data = request_data ,
361+ context = context ,
362+ root_value = root_value ,
354363 )
355364 except GraphQLValidationError as e :
356365 result = ExecutionResult (data = None , errors = e .errors )
@@ -529,6 +538,17 @@ async def parse_multipart_subscriptions(
529538
530539 return self .parse_json (await request .get_body ())
531540
541+ async def get_graphql_request_data (
542+ self , data : dict [str , Any ], protocol : Literal ["http" , "multipart-subscription" ]
543+ ) -> GraphQLRequestData :
544+ return GraphQLRequestData (
545+ query = data .get ("query" ),
546+ variables = data .get ("variables" ),
547+ operation_name = data .get ("operationName" ),
548+ extensions = data .get ("extensions" ),
549+ protocol = protocol ,
550+ )
551+
532552 async def parse_http_body (
533553 self , request : AsyncHTTPRequestAdapter
534554 ) -> GraphQLRequestData :
@@ -550,13 +570,7 @@ async def parse_http_body(
550570 else :
551571 raise HTTPException (400 , "Unsupported content type" )
552572
553- return GraphQLRequestData (
554- query = data .get ("query" ),
555- variables = data .get ("variables" ),
556- operation_name = data .get ("operationName" ),
557- extensions = data .get ("extensions" ),
558- protocol = protocol ,
559- )
573+ return await self .get_graphql_request_data (data , protocol )
560574
561575 async def process_result (
562576 self , request : Request , result : ExecutionResult
0 commit comments