FastAPI is a modern, fast, web framework for building APIs with Python 3.7+ based on standard Python type hints. It is designed to be easy to use, fast to run, and secure. In this blog post, we’ll explore the key features of FastAPI and walk through the process of creating a simple API using this powerful framework.
Table of Contents
- Why FastAPI?
- Installation
- Your First FastAPI Application
- Running the Application
- Request Parameters and Validation
- Query Parameters and Path Parameters
- Request and Response Models
- Dependency Injection
- Authentication and Authorization
- Testing
- Conclusion
Why FastAPI?
Before diving into the details, let’s understand why FastAPI is gaining popularity among developers:
Fast Execution: FastAPI is built on top of Starlette and Pydantic, making it one of the fastest Python frameworks for building APIs.
Automatic Documentation: FastAPI generates interactive API documentation (Swagger UI and ReDoc) automatically from your code, making it easy for developers to understand and test the API.
Type Checking: Leveraging Python type hints, FastAPI provides automatic data validation, serialization, and documentation generation, reducing the chances of runtime errors.
Async Support: FastAPI supports asynchronous programming, allowing you to write asynchronous code for handling multiple requests concurrently, leading to better performance.
Dependency Injection: FastAPI uses a powerful dependency injection system, making it easy to organize and reuse code while keeping it maintainable and testable.
Installation
Before diving into FastAPI, you need to install it. You can do this using pip:
pip install fastapi uvicorn
uvicorn
is an ASGI server that is recommended for running FastAPI applications.
Your First FastAPI Application
Let’s start by creating a simple FastAPI application. Create a file named main.py
and add the following code:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, query_param: str = None):
return {"item_id": item_id, "query_param": query_param}
This example defines two routes: /
and /items/{item_id}
. The @app.get
decorator defines the HTTP method to handle, and the function underneath is the implementation of that endpoint.
Running the Application
To run your FastAPI application, use the following command:
uvicorn main:app --reload
This starts the development server, and the --reload
flag enables automatic code reloading during development.
Visit http://127.0.0.1:8000 in your browser or a tool like Swagger UI to explore the automatically generated API documentation.
Request Parameters and Validation
FastAPI leverages Python type hints for request parameter validation. In the example above, item_id
is expected to be an integer, and query_param
is an optional string. FastAPI automatically validates these parameters based on their types.
Query Parameters and Path Parameters
FastAPI supports query parameters, path parameters, and request bodies. Query parameters are specified in the URL, while path parameters are part of the URL path. In the example, query_param
is a query parameter, and item_id
is a path parameter.
Request and Response Models
FastAPI makes use of Pydantic models to define the structure of request and response data. This helps in automatic data validation and generation of OpenAPI documentation.
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str = None
price: float
tax: float = None
You can then use this model in your path operation function:
@app.post("/items/")
def create_item(item: Item):
return item
FastAPI will validate the incoming request against the Item
model and generate appropriate error responses if the data does not match the expected structure.
Dependency Injection
FastAPI supports dependency injection for reusable components. You can use dependencies to manage authentication, database connections, and other shared resources.
from fastapi import Depends, HTTPException, status
async def get_user_agent(user_agent: str = Header(None)):
return {"User-Agent": user_agent}
@app.get("/user-agent/")
async def read_user_agent(user_agent: dict = Depends(get_user_agent)):
return user_agent
In this example, get_user_agent
is a dependency function that extracts the user agent from the request headers. The read_user_agent
function then uses this dependency.
Authentication and Authorization
FastAPI supports various authentication mechanisms, such as OAuth2, API keys, and more. You can use these mechanisms to secure your API and control access.
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
@app.get("/users/me")
async def read_user_me(token: str = Depends(oauth2_scheme)):
return {"token": token}
In this example, the OAuth2PasswordBearer
class is used to create an OAuth2 password flow for token-based authentication. The read_user_me
function depends on the token
parameter, which is automatically extracted from the request.
Testing
FastAPI makes it easy to write tests for your API using tools like TestClient
from the fastapi.testclient
module.
from fastapi.testclient import TestClient
def test_read_item():
with TestClient(app) as client:
response = client.get("/items/42")
assert response.status_code == 200
assert response.json() == {"item_id": 42, "query_param": None}
Writing tests for your API ensures that it behaves as expected and helps catch regressions when making changes.
Conclusion
FastAPI provides a powerful and efficient way to build APIs in Python. Its use of Python type hints for automatic validation and OpenAPI documentation generation simplifies development and maintenance. Whether you are building a small project or a large-scale application, FastAPI’s performance and developer-friendly features make it an excellent choice for modern web APIs. Start exploring FastAPI and unlock the full potential of building high-performance APIs with Python.
Top comments (0)