FastAPI Response Cookies
Introduction
Cookies are small pieces of data stored in the client's web browser. They're commonly used for maintaining user sessions, storing user preferences, or tracking user behaviors across multiple requests. In web development, cookies are essential for creating stateful applications on the otherwise stateless HTTP protocol.
In this tutorial, we'll learn how to work with cookies in FastAPI responses. We'll cover setting cookies, reading them from requests, modifying existing cookies, and deleting cookies. By the end, you'll be able to effectively manage cookies in your FastAPI applications.
Prerequisites
Before diving in, make sure you have:
- Basic knowledge of FastAPI
- FastAPI installed in your environment (
pip install fastapi
) - An ASGI server like Uvicorn (
pip install uvicorn
)
Understanding HTTP Cookies
Cookies are sent with HTTP responses using the Set-Cookie
header. Once set, the browser will include these cookies in subsequent requests to the same domain using the Cookie
header.
A typical cookie contains:
- Name
- Value
- Expiration date/time
- Path
- Domain
- Security flags (HttpOnly, Secure, SameSite)
Setting Cookies in FastAPI
FastAPI makes it easy to set cookies through the Response
object. Let's start with a basic example:
from fastapi import FastAPI, Response
app = FastAPI()
@app.get("/set-cookie")
def set_cookie(response: Response):
response.set_cookie(key="cookie_name", value="cookie_value")
return {"message": "Cookie set successfully"}
When you access the /set-cookie
endpoint, a cookie named cookie_name
with value cookie_value
will be set in your browser.
Cookie Parameters
The set_cookie
method accepts several parameters to customize how your cookie behaves:
@app.get("/set-advanced-cookie")
def set_advanced_cookie(response: Response):
response.set_cookie(
key="user_preferences",
value="dark_mode",
max_age=3600, # 1 hour in seconds
expires=None, # Alternative to max_age
path="/",
domain=None,
secure=False,
httponly=True,
samesite="lax"
)
return {"message": "Advanced cookie set successfully"}
Let's break down these parameters:
max_age
: The cookie's lifespan in secondsexpires
: Explicit expiration date (a datetime object)path
: The URL path the cookie is valid fordomain
: The domain the cookie is valid forsecure
: Whether the cookie should only be sent over HTTPShttponly
: Prevents JavaScript from accessing the cookie (security measure)samesite
: Controls cookie behavior in cross-site requests (options: "lax", "strict", or "none")
Reading Cookies from Requests
To read cookies sent by the client, use the Request
object:
from fastapi import FastAPI, Request, Response
app = FastAPI()
@app.get("/read-cookie")
def read_cookie(request: Request):
user_preferences = request.cookies.get("user_preferences")
return {
"cookie_value": user_preferences,
"message": "Cookie read successfully"
}
The output will look something like:
{
"cookie_value": "dark_mode",
"message": "Cookie read successfully"
}
If the cookie doesn't exist, get()
will return None
by default.
Updating Existing Cookies
To update a cookie, simply set a new cookie with the same name:
@app.get("/update-cookie")
def update_cookie(request: Request, response: Response):
# Read current value
current_value = request.cookies.get("user_preferences")
# Set new value
new_value = "light_mode" if current_value == "dark_mode" else "dark_mode"
response.set_cookie(key="user_preferences", value=new_value)
return {
"previous_value": current_value,
"new_value": new_value,
"message": "Cookie updated successfully"
}
Deleting Cookies
To delete a cookie, use the delete_cookie
method:
@app.get("/delete-cookie")
def delete_cookie(response: Response):
response.delete_cookie(key="user_preferences")
return {"message": "Cookie deleted successfully"}
This sets the cookie's expiry date to a time in the past, instructing the browser to remove it.
Practical Example: User Session Management
Let's implement a simple session management system using cookies:
from fastapi import FastAPI, Request, Response, Depends
from fastapi.responses import RedirectResponse
import uuid
from typing import Optional
app = FastAPI()
# In-memory session store (use a database in production)
sessions = {}
def get_current_user(request: Request) -> Optional[str]:
session_id = request.cookies.get("session_id")
if session_id and session_id in sessions:
return sessions[session_id]
return None
@app.get("/login")
def login(username: str, response: Response):
# Generate a new session ID
session_id = str(uuid.uuid4())
# Store the session
sessions[session_id] = username
# Set the session cookie
response.set_cookie(
key="session_id",
value=session_id,
httponly=True,
max_age=1800, # 30 minutes
samesite="lax"
)
return {"message": f"Welcome, {username}! You are now logged in."}
@app.get("/profile")
def profile(user: str = Depends(get_current_user)):
if not user:
return RedirectResponse(url="/login-page")
return {"message": f"Hello, {user}! This is your profile page."}
@app.get("/logout")
def logout(response: Response, user: str = Depends(get_current_user)):
if not user:
return {"message": "You're not logged in"}
# Clear the session cookie
response.delete_cookie(key="session_id")
# Remove the session from our store
session_id = request.cookies.get("session_id")
if session_id in sessions:
del sessions[session_id]
return {"message": "You have been logged out successfully"}
This example demonstrates:
- Setting a session cookie when a user logs in
- Reading the cookie to identify the user
- Using a dependency to check authentication
- Deleting the cookie when the user logs out
Security Considerations
When working with cookies, keep these security practices in mind:
- Use HttpOnly flag for sensitive cookies to prevent JavaScript access
- Use Secure flag to ensure cookies are only transmitted over HTTPS
- Set appropriate SameSite policies to prevent CSRF attacks
- Don't store sensitive data in cookies - use them for session IDs only
- Set appropriate expiration times to limit exposure
- Consider using refresh tokens for long-lived sessions
Using JSONResponse with Cookies
You can also set cookies when using specific response types:
from fastapi import FastAPI
from fastapi.responses import JSONResponse
app = FastAPI()
@app.get("/json-with-cookie")
def json_with_cookie():
content = {"message": "This response has a cookie"}
response = JSONResponse(content=content)
response.set_cookie(key="my_cookie", value="cookie_from_json_response")
return response
Summary
In this tutorial, you've learned:
- How to set cookies with various parameters in FastAPI
- How to read cookies from incoming requests
- How to update and delete cookies
- A practical example of session management with cookies
- Security considerations when working with cookies
Cookies are a powerful tool for maintaining state in web applications, but they should be used responsibly and with security in mind.
Additional Resources
Exercises
- Create an endpoint that sets a cookie with the current timestamp and displays when the user last visited.
- Implement a simple theme switcher that remembers the user's preference (dark/light mode) using cookies.
- Build a "remember me" feature that sets a long-lived cookie when checked and a session cookie otherwise.
- Create a cookie consent banner that sets a cookie once the user accepts cookies on your site.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)