FastAPI is great for building powerful Python APIs quickly (while auto-generating documentation!). In this example, we build an API which grabs a recent NASA Curiosity Mars rover photo, resizes it for use as a wallpaper, and returns the resized photo to the user.
First, we define two URL constants,
PHOTO_URL which allow us to access information about the available photos (i.e. photo manifest), and the actual photos themselves. You can read more about this API under the "Mars Rover Photos" section of the NASA API page.
Before we get into the specifics of FastAPI, we'll define a utility function called
get_photo_info which will get information about the latest photos from the Curiosity's mast camera - specifically the most recent Earth date a photo was taken (
latest_photo_date), and the number of photos taken on that date (
Now we can create our API. First we create the FastAPI
app on line #42. We'll define the root (
/) route by defining a function called
read_root, and decorating it with
@app.get("/"). This function simply returns the photo info as determined by the
get_photo_info function. Routes in FastAPI are functions decorated with
<HTTP_METHOD> is a valid HTTP method (i.e.
delete, etc.), and
ROUTE is a string corresponding to the API route.
Next we'll create a route to generate wallpapers from one of the latest Curiosity mast camera photos. First we define a function called
make_wallpaper and decorate it. Here, the user can specify an index (
photo_number) corresponding to the photo of interest. To specify a dynamic route, as in this case, we wrap the route argument in curly braces.
photo_number is now passed to the
make_wallpaper function as the
photo_number argument. By specifying the
int type, Typer will automatically validate the route to make sure the user is passing an integer and nothing else. We'll get the photo info from the
get_photo_info function and return an
HTTPException if the user requests a photo index that is negative or out of range of the available photos.
Then, we'll get the requested photo from the NASA API, and open it using the
Image object from the
PIL library on lines #64-67. Since we want to give the user the option to resize the chosen photo, we specify an optional
height argument in the
make_wallpaper function. This argument defaults to 1080 (in pixels). However, we don't want the user to be able to specify any size they want (a really large height could crash the server, as well as a negative height which makes no sense!) so we use the FastAPI
Query object, to specify minimum and maximum heights using the
ge (greater than or equal to) and
le (less than or equal to) keyword arguments respectively. Now, the image height can be passed to this route as a query parameter like so:
Finally, on lines #70-73 we'll resize the photo from the NASA API to have the specified
height. We assume a 16:9 aspect ratio, so we can compute the width directly from the height, as on line #70. The resized photo is then converted to a bytes object, and streamed back to the client using the FastAPI
StreamingResponse object. Navigating to the "wallpaper" route with valid parameters should return an appropriately resized image from the NASA Curiosity rover. We can also see the auto-generated documentation for the API by going to the
This pattern only scratches the surface of what's possible with FastAPI, so I encourage you to read the official docs here.