Thursday, January 11, 2024
So, why choose FastAPI over other frameworks? 🤔 Here are a few compelling reasons:
🛠️ Setting Up FastAPI: Installing and Creating a Basic API
Here is a basic diagram of how our applications it's going to look like
Getting started with FastAPI is straightforward. Here's a step-by-step guide:
You can install FastAPI using pip:
pip install fastapi
Create a new file called main.py and add the following code:
from fastapi import FastAPI app = FastAPI() @app.get("/") def read_root(): return {"Hello": "World"}
Run the application using:
uvicorn main:app --reload
Open your web browser and navigate to http://127.0.0.1:8000/ to see the API in action. 🎉
One of the coolest things about FastAPI is its built-in async support. It’s perfect for handling things like database queries, external API calls, and any other tasks that don’t need to block the main thread.
Using Async Functions for Non-Blocking Execution:
You can use async and await to make sure your app doesn’t get stuck waiting for slow tasks. Here's a simple example:
@app.get("/items/{item_id}") async def read_item(item_id: int): return {"item": item_id}
Connecting to Databases:
FastAPI works great with databases! Whether you’re using SQLAlchemy (PostgreSQL, MySQL) or MongoDB, it’s super easy to set up.
SQLAlchemy (PostgreSQL, MySQL):
from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker DATABASE_URL = "postgresql://user:password@localhost/dbname" engine = create_engine(DATABASE_URL) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
MongoDB with Motor (MongoDB’s async driver):
from motor.motor_asyncio import AsyncIOMotorClient client = AsyncIOMotorClient("mongodb://localhost:27017") db = client.mydatabase
Security is super important, and FastAPI makes it easy to add authentication and protect your APIs. 🛡️
JWT Authentication:
JSON Web Tokens (JWT) are a popular way to securely transmit information between the client and server.
from fastapi.security import OAuth2PasswordBearer oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") @app.get("/users/me") async def read_users_me(token: str = Depends(oauth2_scheme)): return {"token": token}
OAuth2 Authentication (Github Example):
FastAPI lets you integrate OAuth2 with third-party providers like Google, GitHub, and more. Easy peasy!
from fastapi import FastAPI, Depends, HTTPException from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm from pydantic import BaseModel import requests import json app = FastAPI() oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") class User(BaseModel): username: str email: str class Token(BaseModel): access_token: str token_type: str @app.post("/token") async def login(form_data: OAuth2PasswordRequestForm = Depends()): # Change it for your credentials client_id = "your_client_id" client_secret = "your_client_secret" code = form_data.password # Exchange authorization code for access token token_url = "https://github.com/login/oauth/access_token" headers = {"Accept": "application/json"} data = {"client_id": client_id, "client_secret": client_secret, "code": code} response = requests.post(token_url, headers=headers, data=data) if response.status_code != 200: raise HTTPException(status_code=401, detail="Invalid credentials") # get the access token from the response access_token = response.json()["access_token"] # use the access token to get the user's information user_url = "https://api.github.com/user" headers = {"Authorization": f"Bearer {access_token}"} response = requests.get(user_url, headers=headers) # check if the response was successful if response.status_code != 200: raise HTTPException(status_code=401, detail="Invalid credentials") # get the user's information from the response user_data = response.json() username = user_data["login"] email = user_data["email"] # return the access token and user information return {"access_token": access_token, "token_type": "bearer", "username": username, "email": email}
Rate Limiting
You can use rate limiting to prevent abuse:
# Simple rate limiter rate_limiter: Dict[str, int] = {} def is_rate_limited(ip_address: str) -> bool: if ip_address in rate_limiter: if rate_limiter[ip_address] >= 5: return True else: rate_limiter[ip_address] += 1 else: rate_limiter[ip_address] = 1 return False # use case if is_rate_limited(ip_address): raise HTTPException(status_code=429, detail="Too many requests")
You can deploy FastAPI using docker:
FROM python:3.9-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY . . CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
docker build -t fastapi-app . docker run -p 8000:8000 fastapi-app
Want to go serverless? FastAPI works perfectly with AWS Lambda. You can use Mangum, a lightweight adapter to run FastAPI with Lambda.
First, let's install Mangum
pip install mangum
And here's how you can use it:
from fastapi import FastAPI, Request from mangum import Mangum app = FastAPI() @app.get("/") def read_root(): return {"Hello": "World"} handler = Mangum(app) def lambda_handler(event, context): return handler(event, context)
And that's it, remember to add create your requirements.txt file!