how do you properly reuse an httpx.AsyncClient wihtin a FastAPI application?

Viewed 825

I have a FastAPI application which, in several different occasions, needs to call external APIs. I use httpx.AsyncClient for these calls. The point is that I don't fully understand how I shoud use it.

From httpx' documentation I should use context managers,

async def foo():
    """"
    I need to call foo quite often from different 
    parts of my application
    """
    async with httpx.AsyncClient() as aclient:
        # make some http requests, e.g.,
        await aclient.get("http://example.it")

However, I understand that in this way a new client is spawned each time I call foo(), and is precisely what we want to avoid by using a client in the first place.

I suppose an alternative would be to have some global client defined somewhere, and just import it whenever I need it like so

aclient = httpx.AsyncClient()

async def bar():
    # make some http requests using the global aclient, e.g.,
    await aclient.get("http://example.it")

This second option looks somewhat fishy, though, as nobody is taking care of closing the session and the like.

So the question is: how do I properly (re)use httpx.AsyncClient() within a FastAPI application?

1 Answers

Well your alternative look good to me, you spawn a client and reuse it every time you need it but you are right nobody close the session.

from httpx doc: (in your case import BackgroundTask and StreamingResponse from fastApi)

import httpx
from starlette.background import BackgroundTask
from starlette.responses import StreamingResponse

client = httpx.AsyncClient()

async def home(request):
    req = client.build_request("GET", "https://www.example.com/")
    r = await client.send(req, stream=True)
    return StreamingResponse(r.aiter_text(), background=BackgroundTask(r.aclose))
Related