Search code examples
pythonwindowspython-requestsfastapiasgi

FastAPI responding slowly when calling through other Python app, but fast in cURL


I have an issue that I can't wrap my head around. I have an API service built using FastAPI, and when I try to call any endpoint from another Python script on my local machine, the response takes 2+ seconds. When I send the same request through cURL or the built-in Swagger docs, the response is nearly instant.

The entire server script is this:

from fastapi import FastAPI
import uvicorn

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Hello World"}

if __name__ == '__main__':
    uvicorn.run(app, host='0.0.0.0', port=8000)

I then call it from a test script using HTTPX. I also tried with the requests package, and it is the same result.

import httpx
r = httpx.get('http://localhost:8000/')
print(r.elapsed)

This prints something like: 0:00:02.069705

I then do the same thing using cURL:

curl -w "@curl-format.txt" -o /dev/null -X 'GET' 'http://localhost:8000/'

This prints:

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    32  100    32    0     0    941      0 --:--:-- --:--:-- --:--:--   969
     time_namelookup:  0.006436s
        time_connect:  0.006747s
     time_appconnect:  0.000000s
    time_pretransfer:  0.006788s
       time_redirect:  0.000000s
  time_starttransfer:  0.034037s
                     ----------
          time_total:  0.034093s

The issue isn't what the endpoint does, but rather that it doesn't even start executing for 2 seconds. I have a debugger running on the endpoint, and the first line only gets executed after those 2 seconds.

I tried to inspect the request to see whether there are any headers or similar in the request that could slow it down, but nothing. When I try again with the headers generated by HTTPX, it still executes fast:

curl -w "@curl-format.txt" -o /dev/null -X 'GET' \
  'http://localhost:8000/events' \
  -H 'accept: */*' \
  -H 'host: localhost:8000' \
  -H 'accept-encoding: gzip, deflate' \
  -H 'connection: keep-alive' \
  -H 'user-agent: python-httpx/0.20.0'

Here is a screenshot of the request in PyCharm, it unfortunately can't be dumped to JSON directly. enter image description here

I'm starting to think that it has something to do with Uvicorn and how it runs the app, but I can't figure out why.


Solution

  • Try using „127.0.0.1“ instead of „localhost“ to refer to your machine. I once had a similar issue, where the DNS lookup for localhost on windows was taking half a second or longer. I don‘t have an explanation for that behaviour, but at least one other person on SO seems to have struggled with it as well…