The curl -I
option (which is used in the example you provided) is the same as using curl --head
and performrs an HTTP HEAD
request, in order to fetch the headers only (not the body/content of the resource):
The HTTP HEAD
method requests the headers that would be
returned if the HEAD
request's URL was instead requested with the
HTTP GET
method. For example, if a URL might produce a large
download, a HEAD
request could read its Content-Length
header
to check the filesize without actually downloading the file.
The requested resource/endpoint you are trying to call supports only GET
requests; hence, the 405 Method Not Allowed
response status code, which indicates that the server knows the request method, but the target resource doesn't support this method.
To demonstrate this, have a look at the example below:
from fastapi import FastAPI
app = FastAPI()
@app.get('/')
async def main():
return {'Hello': 'World'}
Test using Python requests (similar result is obtained using curl -I http://127.0.0.1:8000
)
import requests
# Making a GET request
# r = requests.get('http://127.0.0.1:8000')
# Making a HEAD request
r = requests.head('http://127.0.0.1:8000')
# check status code for response received
print(r.status_code, r.reason)
# print headers of request
print(r.headers)
# checking if request contains any content
print(r.content)
Output (indicating by the allow
response header which request methods are supported by the requested resource):
405 Method Not Allowed
{'date': 'Sun, 12 Mar 2023', 'server': 'uvicorn', 'allow': 'GET', 'content-length': '31', 'content-type': 'application/json'}
b''
If, instead, you performed a GET
request (in order to issue a GET
request in the example above, uncomment the line for GET
request and comment the one for HEAD
request, or in curl
use curl http://127.0.0.1:8000
), the response would be as follows:
200 OK
{'date': 'Sun, 12 Mar 2023', 'server': 'uvicorn', 'content-length': '17', 'content-type': 'application/json'}
b'{"Hello":"World"}'
Solutions
To make a FastAPI endpoint supporting more than one HTTP request methods (e.g., both GET
and HEAD
requests), the following solutions are available.
Solution 1
Add a decorator for each request method that you would like the endpoint to support. For instance:
from fastapi import FastAPI
app = FastAPI()
@app.head('/')
@app.get('/')
async def main():
return {'Hello': 'World'}
Solution 2
Use the @app.api_route()
decorator, which allows you to define the set of supported request methods for the endpoint. For example:
from fastapi import FastAPI
app = FastAPI()
@app.api_route('/', methods=['GET', 'HEAD'])
async def main():
return {'Hello': 'World'}
Output
Both solutions above would respond as follows (when a HEAD
request is issued by a client):
200 OK
{'date': 'Sun, 12 Mar 2023', 'server': 'uvicorn', 'content-length': '17', 'content-type': 'application/json'}
b''
Note that 405 Method Not Allowed
response may also be caused by other reasons—see related answers here and here, as well as here and here.