Skip to content

Latest commit

 

History

History
123 lines (92 loc) · 4.37 KB

README.md

File metadata and controls

123 lines (92 loc) · 4.37 KB

GraphQL Requests

While standard GraphQL does not include a type for uploading files, the proposed Multipart Request Spec adds an Upload type. Various implementations exist for this spec. For example, the graphene-file-upload package implements the spec for Flask and Django.

The GraphQL Requests package provides a thin wrapper around a Requests session for facilitating GraphQL queries with and without a file upload.

Installing

graphql_requests can be installed with pip:

pip install graphql_requests

Usage

The following code can be used with the test server from https://github.com/saltastro/graphql_requests_test_server.git.

You instantiate a graphql_requests session by calling its constructor with the URI to use for the GraphQL queries.

from graphql_requests import GraphQLSession

session = GraphQLSession('http://localhost:4000/')

The session exposes all the functionality of a Requests session. However, contrary to their counterparts in a Requests session, methods corresponding to an HTTP verb (i.e. get, post etc.) do not accept a URI as their first argument, as they use the one passed when creating the session instance. So the following would be valid.

query_string = query = '''query {
    user(id: "0cc32455-b51e-4930-8b49-398d87576af6") {
        name
    }
}'''
session.post(json={'query': query_string})

Usually there should be no need for using these methods, though, as graphql_requests has its own query method specifically for making GraphQL requests. The previous example can be rewritten to use this method.

session.query(query_string)

The query method returns a Requests Response instance. Here is how you could get the JSON object returned by the server.

res = session.query(query_string)
print(res.json())

If your query contains variables, you need to pass these as a dictionary of variable names and values.

query_string = '''query user($id: ID!) {
    user(id: $id) {
        name
    }
}'''
variables = {
    'id': '0cc32455-b51e-4930-8b49-398d87576af6'
}
session.query(query_string=query_string, variables=variables)

In case you want to upload files, a file map and a files dictionary are required as well. The map links unique identifiers to variables of type Upload. The files dictionary links the same identifiers to 3-tuples with the following items:

  • The filename.
  • The file content. You can pass this in any form that is handled by the files attribute of the post method in the Requests library.]
  • The content type. This should be a valid MIME type such as 'text.plain' or 'application.zip'.

For example, the creation of a user with a CV might look as follows.

filepath = '/path/to/cv.pdf'
with open(filepath, 'rb') as f:
    query_string = '''mutation createUser($name: String!, $cv: Upload!) {
        createUser(name: $name, cv: $cv) {
            id
        }
    }'''
    variables = {
       'name': 'John Doe',
       'cv': None
    }
    file_map = {
        '0': ['variables.cv']
    }
    files = {
        '0': ('cv.pdf', f, 'application/pdf')
    }
    session.query(
        query_string=query_string,
        variables=variables,
        file_map=file_map,
        files=files
    )

Authentication

You can add support for authentication in the same way you would add it to a Requests session.

As an example, let us add token based authentication to our GraphQL queries. For this we need a class implementing the authentication logic.

from requests.auth import AuthBase

class TokenAuth(AuthBase):
    def __init__(self, token):
        self._token = token
    
    def __call__(self, r):
        r.headers['Authorization'] = 'Token ' + self._token
        return r

An instance of this class can then be assigned to the session's auth property.

session.auth =  TokenAuth('4c7b223d-ca67-4fd7-809f-f0fae71fb6d6')

Any further queries will then have an Authorization header with the token.