Overview
We've got a client ready to fetch data from the Spotify API. We could use this client directly in our resolvers, but that would lead to quite a bit of code duplication. Instead, we'll use the context feature of Strawberry to create the client once and share it across all resolvers.
In this lesson, we will:
- Learn about the
contextin Strawberry - Learn how to use the
infoargument to access thecontextin our resolvers
What is the context?
The context in Strawberry is an object that allows us to pass any kind of data to our resolvers. Usually, it's used for things like database connections or authentication information.
We'll be using context to share the Spotify client across all our resolvers.
Instantiating the client
To create an instance of the Spotify client, we'll make use of FastAPI's lifespan feature.
FastAPI's lifespan
FastAPI's lifespan feature enables us to run code when the application starts and stops. This is useful for setting up resources that need to be created once and shared across requests (just like our Spotify client!).
Open up the main.py file, where all the server code lives.
We'll import a few things at the top: the asynccontextmanager (which we'll need for the lifespan), the mock_spotify_rest_api_client.client, and Request from FastAPI.
from contextlib import asynccontextmanagerfrom mock_spotify_rest_api_client.client import Clientfrom fastapi import Request
Next, we can define the lifespan function, decorating it with @asynccontextmanager.
@asynccontextmanagerasync def lifespan(app):...
Inside, we'll instantiate the Client class, giving it the base_url parameter with the Spotify API endpoint as the value. We'll also name this instance as spotify_client.
@asynccontextmanagerasync def lifespan(app):async with Client(base_url="https://spotify-demo-api-fe224840a08c.herokuapp.com/v1") as spotify_client:...
To make spotify_client available in the FastAPI app, we can yield an object containing it. This object will be available on the request object under request.state later on.
yield {"spotify_client": spotify_client}
Note: Code before the yield function runs before the application starts. You can read more about FastAPI's lifespan in the docs.
Finally, let's pass the lifespan into the FastAPI constructor down below.
app = FastAPI(lifespan=lifespan)
Great! The FastAPI app has access to the Spotify client, but we still need to pass it along to the resolvers using context.
Creating the context object
Let's start by defining an async function called context_getter. It accepts an argument called request of type Request.
async def context_getter(request: Request):...
The request object represents the GraphQL request, which includes the GraphQL operation and any HTTP headers. Additionally, it contains the spotify_client object we set up in the lifespan function earlier!
We can now access the spotify_client object from the request.state object.
spotify_client = request.state.spotify_client
Then, we'll return an object, representing the context object. Inside, we'll include the spotify_client.
return {"spotify_client": spotify_client}
Finally, down below, we'll pass this context_getter function into the context_getter parameter of the GraphQLRouter class.
graphql_router = GraphQLRouter(schema, path="/", graphql_ide="apollo-sandbox", context_getter=context_getter)
Strawberry automatically calls the context_getter on every request and passes the result to the resolvers via the info argument, which we'll tackle in the next lesson.
Key takeaways
- The
contextin Strawberry allows us to pass data to our resolvers. We use thecontext_getterparameter inGraphQLRouterto return a customcontextobject. - FastAPI's lifespan allows us to create resources that need to be shared across requests.
Up next
It's time for the resolver function to start making real requests to the Spotify API.
Share your questions and comments about this lesson
This course is currently in
You'll need a GitHub account to post below. Don't have one? Post in our Odyssey forum instead.