Patternite Logo

Easily building an API in Python using FastAPI

0

FastAPI provides a very powerful, straightforward approach to building application programming interfaces (APIs) in Python. Here we build an API which grabs a NASA Mars rover photo and resizes it for use as a wallpaper.

Loading...

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, MANIFEST_URL and 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 (n_photos).

FastAPI Routes

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 @app.<HTTP_METHOD>(ROUTE), where <HTTP_METHOD> is a valid HTTP method (i.e. get, post, put, 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:

/wallpaper/5?height=720

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 /docs route.

This pattern only scratches the surface of what's possible with FastAPI, so I encourage you to read the official docs here.

Profile picture for duncster

| edited

Patternite © 2021

Patternite Logo