FastAPI

Strawberry provides support for FastAPI with a custom APIRouter called GraphQLRouter .

Before using Strawberry’s FastAPI support make sure you install all the required dependencies by running:

pip install 'strawberry-graphql[fastapi]'

See the example below for integrating FastAPI with Strawberry:

import strawberry
 
from fastapi import FastAPI
from strawberry.fastapi import GraphQLRouter
 
 
@strawberry.type
class Query:
    @strawberry.field
    def hello(self) -> str:
        return "Hello World"
 
 
schema = strawberry.Schema(Query)
 
graphql_app = GraphQLRouter(schema)
 
app = FastAPI()
app.include_router(graphql_app, prefix="/graphql")

Options

The GraphQLRouter accepts the following options:

context_getter

The context_getter option allows you to provide a custom context object that can be used in your resolver. context_getter is a FastAPI dependency and can inject other dependencies if you so wish.

There are two options at your disposal here:

  1. Define your custom context as a dictionary,
  2. Define your custom context as a class.

If no context is supplied, then the default context returned is a dictionary containing the request, the response, and any background tasks.

However, you can define a class-based custom context inline with FastAPI practice . If you choose to do this, you must ensure that your custom context class inherits from BaseContext or an InvalidCustomContext exception is raised.

For dictionary-based custom contexts, an example might look like the following.

import strawberry
 
from fastapi import FastAPI, Depends, Request, WebSocket, BackgroundTasks
from strawberry.fastapi import GraphQLRouter
 
 
def custom_context_dependency() -> str:
    return "John"
 
 
async def get_context(
    custom_value=Depends(custom_context_dependency),
):
    return {
        "custom_value": custom_value,
    }
 
 
@strawberry.type
class Query:
    @strawberry.field
    def example(self, info: strawberry.Info) -> str:
        return f"Hello {info.context['custom_value']}"
 
 
schema = strawberry.Schema(Query)
 
graphql_app = GraphQLRouter(
    schema,
    context_getter=get_context,
)
 
app = FastAPI()
app.include_router(graphql_app, prefix="/graphql")

Here we are returning a custom context dictionary that contains one extra item called "customvalue", which is injected from custom_context_dependency . This value exists alongside request , response , and background_tasks in the info.context _dictionary and so it requires ['request'] indexing.

Then we use the context in a resolver. The resolver will return “Hello John” in this case.

For class-based custom contexts, an example might look like the following.

import strawberry
 
from fastapi import FastAPI, Depends, Request, WebSocket, BackgroundTasks
from strawberry.fastapi import BaseContext, GraphQLRouter
 
 
class CustomContext(BaseContext):
    def __init__(self, greeting: str, name: str):
        self.greeting = greeting
        self.name = name
 
 
def custom_context_dependency() -> CustomContext:
    return CustomContext(greeting="you rock!", name="John")
 
 
async def get_context(
    custom_context=Depends(custom_context_dependency),
):
    return custom_context
 
 
@strawberry.type
class Query:
    @strawberry.field
    def example(self, info: strawberry.Info) -> str:
        return f"Hello {info.context.name}, {info.context.greeting}"
 
 
schema = strawberry.Schema(Query)
 
graphql_app = GraphQLRouter(
    schema,
    context_getter=get_context,
)
 
app = FastAPI()
app.include_router(graphql_app, prefix="/graphql")

In this case, we are returning a custom context class that inherits from BaseContext with fields name and greeting , which is also injected by custom_context_dependency . These custom values exist alongside request , response , and background_tasks in the info.context class and so it requires .request indexing.

Then we use the context in a resolver. The resolver will return β€œHello John, you rock!” in this case.

Setting background tasks

Similarly, background tasks can be added via the context:

import strawberry
 
from fastapi import FastAPI, BackgroundTasks
from strawberry.fastapi import GraphQLRouter
 
 
async def notify_new_flavour(name: str):
    print(name)
 
 
@strawberry.type
class Query:
    @strawberry.field
    def hello(self) -> str:
        return "Hello World"
 
 
@strawberry.type
class Mutation:
    @strawberry.mutation
    def create_flavour(self, name: str, info: strawberry.Info) -> bool:
        info.context["background_tasks"].add_task(notify_new_flavour, name)
        return True
 
 
schema = strawberry.Schema(Query, Mutation)
 
graphql_app = GraphQLRouter(schema)
 
app = FastAPI()
app.include_router(graphql_app, prefix="/graphql")

If using a custom context class, then background tasks should be stored within the class object as .background_tasks .

root_value_getter

The root_value_getter option allows you to provide a custom root value for your schema. This is most likely a rare usecase but might be useful in certain situations.

Here’s an example:

import strawberry
 
from fastapi import FastAPI
from strawberry.fastapi import GraphQLRouter
 
 
async def get_root_value():
    return Query(name="Patrick")
 
 
@strawberry.type
class Query:
    name: str
 
 
schema = strawberry.Schema(Query)
 
graphql_app = GraphQLRouter(
    schema,
    root_value_getter=get_root_value,
)
 
app = FastAPI()
app.include_router(graphql_app, prefix="/graphql")

Here we are returning a Query where the name is "Patrick", so when we request the field name we'll return "Patrick".

process_result

The process_result option allows you to customize and/or process results before they are sent to the clients. This can be useful for logging errors or hiding them (for example to hide internal exceptions).

It needs to return a GraphQLHTTPResponse object and accepts the request and execution results.

from fastapi import Request
from strawberry.fastapi import GraphQLRouter
from strawberry.http import GraphQLHTTPResponse
from strawberry.types import ExecutionResult
 
 
class MyGraphQLRouter(GraphQLRouter):
    async def process_result(
        self, request: Request, result: ExecutionResult
    ) -> GraphQLHTTPResponse:
        data: GraphQLHTTPResponse = {"data": result.data}
 
        if result.errors:
            data["errors"] = [err.formatted for err in result.errors]
 
        return data

In this case we are doing the default processing of the result, but it can be tweaked based on your needs.

encode_json

encode_json allows to customize the encoding of the JSON response. By default we use json.dumps but you can override this method to use a different encoder. For example, the orjson library from pypi has blazing fast speeds.

class MyGraphQLRouter(GraphQLRouter):
    def encode_json(self, data: GraphQLHTTPResponse) -> bytes:
        return orjson.dumps(data)

render_graphql_ide

In case you need more control over the rendering of the GraphQL IDE than the graphql_ide option provides, you can override the render_graphql_ide method.

from strawberry.fastapi import GraphQLRouter
from starlette.responses import HTMLResponse, Response
 
 
class MyGraphQLRouter(GraphQLRouter):
    async def render_graphql_ide(self, request: Request) -> HTMLResponse:
        custom_html = """<html><body><h1>Custom GraphQL IDE</h1></body></html>"""
 
        return HTMLResponse(custom_html)
Edit this page on GitHub