graphql-python / graphene-gae

GraphQL Support for Google AppEngine [DEPRECATED - Looking for maintainers]

Home Page:http://docs.graphene-python.org/projects/gae/en/latest/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Passing query as JSON (for variables, etc.) seems broken

uebayasi opened this issue · comments

I'm very new to this GraphQL world but my understanding of GraphQL is that, in order to pass variables or operation_name in addition to query, the body of POST has to be encoded in JSON. A GraphQL query HTML body, with a pair of query and variables, would look like:

{ "query": "...", "variables": "..." }

This does not seem to work with graphene-gae. I put many logging.warn()'s in _get_grapl_params() but could not understand the intent. If the said assumption that GraphQL query body is either raw GraphQL or JSON, this _get_grapl_params() would look like:

    def _get_grapl_params(self):
        try:
            (read body as JSON)
        except:
            (read body as raw GraphQL)

(I even have no idea why this handler has to be implemented in graphene-gae, not graphene.)

I'm trying to fix this myself, but I'm slow; new to Python, new to GraphQL, new to Web world. Feel free to beat me. ;)

Probably checking Content-Type (either application/graphql or application/json) would be saner.

hey @uebayasi ,
do _get_graphql_params starts with this code:

        try:
            request_data = self.request.json_body
            if isinstance(request_data, basestring):
                request_data = dict(query=request_data)
        except:
            request_data = {}

Meaning, if you send a JSON object ({ "query": "...", "variables": "..." }) it'll use that, and if you send a JSON string it'll treat is as the query.

The code that follows reads operation_name and variables from request_data.
So if you send a POST request that looks like { "query": "...", "variables": "..." } GraphQLHandler should handle it properly.
Are you having problems with such a request?

The reason this handler is implemented in graphene-gae and not graphene is that its written specifically for the Google AppEngine environment - using webapp2 which is GAE's web framework.
The main graphene library should not depend on GAE specific code thats of no use to people on other platforms.

Thanks for the quick reply!

Now I see the problem; self.request.json_body is failing for me. I grep -r'ed json_body under google-cloud-sdk/platform/google_appengine/lib/webapp2-* and got no result. There are references under other subdirectories but I have no idea of relevance.

json.loads(self.request.body) surely works and that's I'm using it for now.

This is google-cloud-sdk 132.0.0 (2016/10/19).

In requests.py there's this code:

    def _json_body__get(self):
        """Access the body of the request as JSON"""
        return json.loads(self.body.decode(self.charset))

    def _json_body__set(self, value):
        self.body = json.dumps(value, separators=(',', ':')).encode(self.charset)

    def _json_body__del(self):
        del self.body

    json = json_body = property(_json_body__get, _json_body__set, _json_body__del)

So basically self.request.json_body is the same as doing json.loads(self.request.body.decode(self.charset))

This is part of the webob 1.2.3 library that webapp2 depends on

I see that webapp2-2.5.1 and webob-1.2.3 are used (imported) here. I can't figure out why those inherited methods are called.

I'll try to investigate this later, but I can't promise. Feeling like Python not being my friend. :(

For some reasons the request object inherits class BaseRequest in webob-1.1.1/webob/request.py, where _json_body__get is not defined. webob-1.2.3's class BaseRequest does define it.

Obviously this problem is not relevant to graphene-gae. It is either google-gcloud-sdk or python2.7 or my local environment causing the oddity. Feel free to close this issue.

Fortunately my project is not really started yet. I'm considering to switch to something and stay away from Python if possible... :(

I just ran into this issue on a fresh install of Google Cloud SDK. It seems that webob version 1.1 gets loaded even though 1.2 is available. I fixed it by specifying the newer webob in my app.yaml:

libraries:
- name: webob
  version: 1.2.3
- name: webapp2
  version: 2.5.2