server/remote-schema: Include OperationName in the request sent to remote schemas

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/3581
Co-authored-by: Puru Gupta <32328846+purugupta99@users.noreply.github.com>
GitOrigin-RevId: 2db21d0df158a5a3229b883ee426b2f38f864f80
This commit is contained in:
Naveen Naidu 2022-02-16 13:24:21 +05:30 committed by hasura-bot
parent 1ff3723ed8
commit 2e823234f9
7 changed files with 59 additions and 6 deletions

View File

@ -24,7 +24,7 @@ The optimization can be enabled using the
### Bug fixes and improvements
(Add entries below in the order of server, console, cli, docs, others)
- server: add operation name in the request sent to remote schemas
- server: add support for scalar response types for actions (issue #7805)
- server: fix nullable action response (issue #4405)
- console: add support for remote database relationships

View File

@ -128,7 +128,7 @@ convertMutationSelectionSet
pure $ ExecStepDB [] (AB.mkAnyBackend dbStepInfo) remoteJoins
RFRemote remoteField -> do
RemoteFieldG remoteSchemaInfo resultCustomizer resolvedRemoteField <- runVariableCache $ resolveRemoteField userInfo remoteField
pure $ buildExecStepRemote remoteSchemaInfo resultCustomizer G.OperationTypeMutation [G.SelectionField resolvedRemoteField]
pure $ buildExecStepRemote remoteSchemaInfo resultCustomizer G.OperationTypeMutation [G.SelectionField resolvedRemoteField] (GH._grOperationName gqlUnparsed)
RFAction action -> do
let (noRelsDBAST, remoteJoins) = RJ.getRemoteJoinsActionMutation action
(actionName, _fch) <- pure $ case noRelsDBAST of

View File

@ -114,7 +114,7 @@ convertQuerySelSet
pure $ ExecStepDB [] (AB.mkAnyBackend dbStepInfo) remoteJoins
RFRemote rf -> do
RemoteFieldG remoteSchemaInfo resultCustomizer remoteField <- runVariableCache $ for rf $ resolveRemoteVariable userInfo
pure $ buildExecStepRemote remoteSchemaInfo resultCustomizer G.OperationTypeQuery [G.SelectionField remoteField]
pure $ buildExecStepRemote remoteSchemaInfo resultCustomizer G.OperationTypeQuery [G.SelectionField remoteField] (GH._grOperationName gqlUnparsed)
RFAction action -> do
let (noRelsDBAST, remoteJoins) = RJ.getRemoteJoinsActionQuery action
(actionExecution, actionName, fch) <- pure $ case noRelsDBAST of

View File

@ -70,16 +70,18 @@ buildExecStepRemote ::
ResultCustomizer ->
G.OperationType ->
G.SelectionSet G.NoFragments Variable ->
Maybe OperationName ->
ExecutionStep
buildExecStepRemote remoteSchemaInfo resultCustomizer tp selSet =
buildExecStepRemote remoteSchemaInfo resultCustomizer tp selSet operationName =
let unresolvedSelSet = unresolveVariables selSet
allVars = map mkVariableDefinitionAndValue $ Set.toList $ collectVariables selSet
varValues = Map.fromList $ map snd allVars
varValsM = bool (Just varValues) Nothing $ Map.null varValues
varDefs = map fst allVars
_grQuery = G.TypedOperationDefinition tp Nothing varDefs [] unresolvedSelSet
_grQuery = G.TypedOperationDefinition tp (_unOperationName <$> operationName) varDefs [] unresolvedSelSet
_grVariables = varValsM
in ExecStepRemote remoteSchemaInfo resultCustomizer GH.GQLReq {_grOperationName = Nothing, ..}
_grOperationName = operationName
in ExecStepRemote remoteSchemaInfo resultCustomizer GH.GQLReq {..}
-- | Association between keys uniquely identifying some remote JSON variable and
-- an 'Int' identifier that will be used to construct a valid variable name to

View File

@ -48,6 +48,26 @@ class HelloGraphQL(RequestHandler):
res = hello_schema.execute(request.json['query'])
return mkJSONResp(res)
class HelloGraphQLEchoRequest(RequestHandler):
def get(self, request):
return Response(HTTPStatus.METHOD_NOT_ALLOWED)
def post(self, request):
if not request.json:
return Response(HTTPStatus.BAD_REQUEST)
res = hello_schema.execute(request.json['query'])
respDict = res.to_dict()
# Return the result as it is, when we send an introspection query
if respDict.get('data',{}).get('__schema',{}):
return mkJSONResp(res)
# Edit the result to contain, the 'request payload' as part of the response.
# We can then use this to assert the request payload with the expected response.
else:
respDict.get('data', {})['hello'] = request.json
return Response(HTTPStatus.OK, res.to_dict(),
{'Content-Type': 'application/json'})
class HelloGraphQLExtensions(RequestHandler):
def get(self, request):
return Response(HTTPStatus.METHOD_NOT_ALLOWED)
@ -808,6 +828,7 @@ class MessagesGraphQL(RequestHandler):
handlers = MkHandlers({
'/hello': HelloWorldHandler,
'/hello-graphql': HelloGraphQL,
'/hello-echo-request-graphql': HelloGraphQLEchoRequest,
'/hello-graphql-extensions': HelloGraphQLExtensions,
'/user-graphql': UserGraphQL,
'/country-graphql': CountryGraphQL,

View File

@ -0,0 +1,9 @@
description: Simple GraphQL query with Operation Name
url: /v1/graphql
status: 200
query:
query: |
query HelloMe {
hello
}
operationName: HelloMe

View File

@ -884,3 +884,24 @@ class TestValidateRemoteSchemaCustomizeAllTheThings:
def test_remote_schema_customize_all_the_things(self, hge_ctx):
check_query_f(hge_ctx, self.dir() + '/customize_all_the_things.yaml')
class TestRemoteSchemaRequestPayload:
dir = 'queries/remote_schemas'
teardown = {"type": "clear_metadata", "args": {}}
@pytest.fixture(autouse=True)
def transact(self, hge_ctx):
q = mk_add_remote_q('echo request', 'http://localhost:5000/hello-echo-request-graphql')
st_code, resp = hge_ctx.v1q(q)
assert st_code == 200, resp
yield
hge_ctx.v1q(self.teardown)
@pytest.mark.allow_server_upgrade_test
def test_remote_schema_operation_name_in_response(self, hge_ctx):
with open('queries/remote_schemas/basic_query_with_op_name.yaml') as f:
query = yaml.load(f)
resp, _ = check_query(hge_ctx, query)
assert resp['data']['hello']['operationName'] == "HelloMe"