8. REST as a data source
5m

Overview

The data that our retrieve can come from all kinds of places: a database, a third-party API, webhooks, and so on. These are called data sources. The beauty of is that you can mix any number of to create an API that serves the needs of your client applications and graph consumers.

In this lesson, we will:

  • Examine the existing Spotify REST API, the perfect for MusicMatcher
  • Generate a Python client using an OpenAPI specification to handle our HTTP requests, responses and types

The Spotify Web API

MusicMatcher needs music, and for this course, we're going to be using a lite, pared-down version of the official Spotify Web API. We can access that version here: https://spotify-demo-api-fe224840a08c.herokuapp.com/v1/docs/

https://spotify-demo-api-fe224840a08c.herokuapp.com/v1/docs/

Spotify REST API docs

Let's explore the documentation. We've got a few endpoints available for us centered around playlists– in fact, it's all we need to implement the features we covered earlier!

Diving into the /browse/featured-playlists endpoint, let's click "Try it out", then "Execute" a request.

https://spotify-demo-api-fe224840a08c.herokuapp.com/v1/docs/

Spotify REST API featured playlists endpoint

https://spotify-demo-api-fe224840a08c.herokuapp.com/v1/docs/

Spotify REST API featured playlists endpoint

We get a JSON object back with two top-level properties: message and playlists. Inside the playlists property, we have an items property, which contains a list, as well as a few other properties that seem to be related to pagination (like limit, next, previous, offset). And then the items list contains objects with its own properties. These objects represent a playlist!

That's a lot of nested properties just to get to what we want – the list of featured playlists!

The shape of the response from our HTTP endpoints often doesn't exactly match what we want to return from our 's types and . And that's okay! One of the benefits of GraphQL is that we only expose what the client may need. In this iteration of the schema for example, we only need to expose the name, description and ID of a playlist.

The HTTP responses also come back in JSON (JavaScript Object Notation) format, whereas in Python we're dealing with classes. For these reasons, we'll need to do some conversions, serializing, and deserializing our HTTP response types to our Python types.

A common way to make HTTP requests and handle responses is with the httpx library.

In this course, we want to focus on the concepts, not fiddling around manually writing types from a REST API. To help make our work go faster, we're going to auto-generate the code to fetch the data from our API.

Auto-generating an HTTP Client

We'll use a OpenAPI Python client to generate a Python client based on an OpenAPI specification.

We've already included a openapi.json file in your project inside the data folder. This OpenAPI file defines the endpoints, expected responses, and schemas for response objects.

We'll use openapi-python-client from the command line so let's install it! We'll be using pipx to install the package and its dependencies.

Open a new terminal and run the following command.

pipx install openapi-python-client --include-deps

We should get this message as a result:

Output
Installed package openapi-python-client 0.19.0, installed using Python 3.12.2

Finally, we'll run the command to use openapi-python-client to generate:

openapi-python-client generate --meta none --path data/openapi.json

This command performs the following steps:

  1. Takes the openapi.json file as an input
  2. Generates a Python module called mock_spotify_rest_api_client
  3. Generates a Client class inside that module

The terminal output should look something like this:

Output
Generating mock_spotify_rest_api_client

The generated package will have a structure similar to this:

πŸ“¦ mock_spotify_rest_api_client
┣ πŸ“„ __init__.py
┣ πŸ“‚ api
┃ ┣ πŸ“„ __init__.py
┃ β”— πŸ“‚ playlists
┃ ┃ ┣ πŸ“„ __init__.py
┃ ┃ ┣ πŸ“„ add_tracks_to_playlist.py
┃ ┃ ┣ πŸ“„ get_featured_playlists.py
┃ ┃ ┣ πŸ“„ get_playlist.py
┃ ┃ ┣ πŸ“„ get_playlists_tracks.py
┃ ┃ β”— πŸ“„ search.py
┣ πŸ“‚ models
┃ ┃ ┣ πŸ“„ __init__.py
┃ ┃ ┣ ...
┃ ┃ β”— πŸ“„ spotify_response_post_playlistsidtracks.py
┣ πŸ“„ client.py
┣ πŸ“„ errors.py
β”— πŸ“„ types.py

The api folder contains the endpoints we can use to interact with the Spotify REST API. For example, the get_featured_playlists.py file contains functions that map to the GET /browse/featured-playlists endpoint (it has both sync and async functions).

The models folder contains the classes that represent the responses from the Spotify REST API.

Finally, the client.py file contains the Client class that we will use to make requests to the Spotify REST API.

We're almost ready to make use of this ; one last thing! We need to install the dependencies of the auto-generated HTTP Client: httpx and attrs.

Let's activate our virtual environment.

source .venv/bin/activate

And install the dependencies:

pip install httpx attrs

Practice

What is the purpose of the Client class generated by openapi-python-client?

Key takeaways

  • allows the use of various , such as databases, REST APIs, and webhooks, to create a flexible API that caters to client application needs.
  • A does not need to follow the shape, pattern, or naming of the it uses.
  • We can use the openapi-python-client tool to auto-generate a Python HTTP Client based on an OpenAPI specification, simplifying the handling of HTTP requests and responses.

Up next

In the next lesson, we'll connect the pieces to make this available to our , using Strawberry's context feature.

Previous

Share your questions and comments about this lesson

This course is currently in

beta
. Your feedback helps us improve! If you're stuck or confused, let us know and we'll help you out. All comments are public and must follow the Apollo Code of Conduct. Note that comments that have been resolved or addressed may be removed.

You'll need a GitHub account to post below. Don't have one? Post in our Odyssey forum instead.