Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not able to get Spring GraphQL adhere to GraphQL Over Http Spec #783

Closed
JayGhiya opened this issue Aug 28, 2023 · 12 comments
Closed

Not able to get Spring GraphQL adhere to GraphQL Over Http Spec #783

JayGhiya opened this issue Aug 28, 2023 · 12 comments
Labels
for: external-project Needs a change in external project status: invalid An issue that we don't feel is valid

Comments

@JayGhiya
Copy link

JayGhiya commented Aug 28, 2023

As per GraphQL over HTTP spec when using the application/graphql-response+json(https://graphql.github.io/graphql-over-http/draft/#sec-application-graphql-response-json) during a situation when the graphQL response does not contain the data entry then the server must reply with a 4xx or 5xx as appropriate.

Here is the poc : https://github.com/JayGhiya/Spring-Graphql-Experiments where we have a graphql query fetching data from sql db. During fetch if the database is unavailable then the operation itself has failed and we have to return 5xx. So The code uses a custom web interceptor (https://github.com/JayGhiya/Spring-Graphql-Experiments/blob/main/src/main/java/com/graphql/demo/CustomGraphQLWebInterceptor.java) to modify the response to remove data as it holds no significance. Still post modifying the response using webinterceptor the spring graphql http servlet returns 2xx which is wrong.

Post intercepting spring graphql servlet should have made 5xx response as there is no data field. Could anybody point me to a example of using spring graphql http servet to modify http status code as this results in a observability nightmare. As we are using HTTP as the transport protocol we would want to adhere to RFC7231 - HTTP semantics and content.

@JayGhiya JayGhiya changed the title Spring GraphQL not compliant with GraphQL Over Http Spec Not able to get Spring GraphQL adhere to GraphQL Over Http Spec Aug 28, 2023
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Aug 28, 2023
@bclozel
Copy link
Member

bclozel commented Aug 28, 2023

Thanks but your sample project is not using spring graphql but graphql kickstart which is a different project. I'm closing this issue as a result.

@bclozel bclozel closed this as not planned Won't fix, can't repro, duplicate, stale Aug 28, 2023
@bclozel bclozel added status: invalid An issue that we don't feel is valid for: external-project Needs a change in external project and removed status: waiting-for-triage An issue we've not yet triaged labels Aug 28, 2023
@JayGhiya
Copy link
Author

@bclozel i might have added those dependencies but using only spring graphql . i might have not pushed the latest pom. let me do that in some time. request you to open the issue post that.

@JayGhiya
Copy link
Author

@bclozel i looked at the code the code makes use of only spring graphql. the pom is just old. will update.

@bclozel
Copy link
Member

bclozel commented Aug 28, 2023

The sample is using and registering a "graphql.kickstart.servlet.GraphQLHttpServlet".

@JayGhiya
Copy link
Author

yes that is correct. but the result is same . apologies for inconvenience. i will remove the graphql-java lib code completely and update the readme with result @bclozel :)

@JayGhiya
Copy link
Author

@bclozel https://github.com/JayGhiya/Spring-Graphql-Experiments/blob/main/README.md . It is updated. Right now the project only uses spring-graphql only and readme is updated with steps to reproduce. please have a look and reopen the issue thanks in advance

@rstoyanchev
Copy link
Contributor

I believe this is the same discussion, or at least related to #568 where we decided to hold off on making these changes for now.

@JayGhiya
Copy link
Author

@rstoyanchev @bclozel sure even if due to some reasons the team has decided to hold off on making these changes but why does the custom web interceptor or even the controller advise with graphql exception handler not allow to modify http response codes. in a increasingly cloud native world api gateways/service meshes all of it get affected by this non compliance with http rfc when you have a failure in connecting to downstream services. Is there any other way to modify the http response through a custom config that you are aware of ?

@bclozel
Copy link
Member

bclozel commented Aug 29, 2023

The current draft version of the spec says the following.

This response should have a 4xx or 5xx response status.

{
  "errors": [
    {
      "message": "Could not connect to database",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "books"
      ]
    }
  ]
}

This response should have a 200 response status.

{
  "data": null,
  "errors": [
    {
      "message": "Could not connect to database",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "books"
      ]
    }
  ]
}

As far as I understand the only difference is about when the error happen (before or during the request execution, and this doesn't seem really required by the original GraphQL spec).

In a increasingly cloud native world, HTTP is not the only transport out there and I think that the transport-agnostic nature of GraphQL is one of its strength. How should this behavior be mapped to RSocket, WebSocket, other messaging protocols and other transports? This is why so far we chose to decouple transports and the actual request execution. This allows us to support multiple transports and variants (Servlet-based, Reactive Streams based) without leaking abstractions.

As for the observability angle you've shared, I believe our observability story is quite compelling so far. Relying on HTTP statuses for that would be a mistake since the behavior you're sharing in the spec also depends on the response content-type (you would not get the same behavior if clients request the popular "application/json" media type).

@JayGhiya
Copy link
Author

JayGhiya commented Aug 29, 2023

@bclozel I do understand if data is null it shud be 2xx but as you could see we are intercepting and modifying the response as it does not make sense if the connection to downstream service such as db failed then making the parameter null itself makes no sense. It is a straight server error. we are in agreement that graphql is transport agnostic . What I am saying -> the framework should be flexible to allow the users to modify the response code based on their underlying transport chosen. Why that is not the case. And also you cannot bend the world of service mesh observability / golden signals pattern / api gateways through spring observability . You just can't. Things that do centralised monitoring rely on status codes. What is the way out ? do we have a roadmap where we allow users to modify status codes in cases of real server errors and graphql json only containing errors. There is no partial data to share. it does not make sense. Also leme know if there is a better forum to share and discuss the same. if you have a working group or weekly open source calls on the same. @rstoyanchev your thoughts?

@bclozel
Copy link
Member

bclozel commented Aug 29, 2023

I guess we could consider extending the WebGraphQlResponse to include the response status. At this point I'm still not convinced this is the right call for the project. I don't really understand the purpose of that custom interceptor (in the repro project) since it turns a valid graphql response (according to the spec) into an invalid one.

And also you cannot bend the world of service mesh observability / golden signals pattern / api gateways through spring observability . You just can't. Things that do centralised monitoring rely on status codes.

Sorry I don't understand this last paragraph. Can you share which service mesh or product are you using? How is it enforcing the graphql over http spec?

According to the graphql over http draft spec, these http status changes only apply to the new media type which is far from being the norm right now. We are in touch with several companies using a lot of graphql, monitoring and observability and this point never came up. How are you monitoring graphql services right now in production? Are they only relying on http status codes? How does this work when most error responses are http 200?

@JayGhiya
Copy link
Author

JayGhiya commented Sep 3, 2023

hey @bclozel apologies for delayed response. yea so lot of commercial companies use service meshes like istio , consul etc to do error reporting across enterprise automatically. And they rely on transport protocols. They work through a kubernetes sidecar pattern. same applies for products using api gateway to monitor http requests/responses. This all does not work. Companies that do platform engineering will prefer to observe traffic across enterprise through transport protocols. The spec has to evolve for usecases where entire operation fails and still it is populating 2xx. I might not understand coming from kubernetes any value add it brings. So that is the reason.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
for: external-project Needs a change in external project status: invalid An issue that we don't feel is valid
Projects
None yet
Development

No branches or pull requests

4 participants