Welcome back! In our previous lesson, you started to see how Dependency Injection (DI) is used in FastAPI through the use of the Depends
function, particularly in the login endpoint. We didn't dive deeply into the concept at that time, but now it's time to explore it in detail.
In this lesson, we will explain what Dependency Injection is and why it's important in software development. By the end of this lesson, you'll understand how it helps to keep code clean and allows us to secure an endpoint using in FastAPI.
Dependency Injection might sound complicated, but it's a simple and powerful concept. Think of it like this: instead of a function creating everything it needs by itself, it receives those things from the outside. This way, the function doesn't worry about how to get what it needs; it just uses it. This leads to cleaner, more manageable code.
In FastAPI, we use the Depends
function to handle Dependency Injection. Imagine having a function that needs certain pieces of information to work. Using Depends
, we can provide those pieces of information from outside the function, making our code more organized and easier to test.
Let's quickly recap what we covered last time. We created a FastAPI app, set up a mock database, and implemented a user authentication function along with a login endpoint.
Here is a quick summary of the code:
Python1from fastapi import FastAPI, HTTPException, Depends 2from fastapi.security import OAuth2PasswordRequestForm 3 4app = FastAPI() 5 6# Mock database with usernames and passwords 7users_db = {"user1": "pass1", "user2": "pass2"} 8 9 10# Function to check if user exists in the database 11def authenticate_user(username: str, password: str): 12 if users_db.get(username) == password: 13 return {"username": username} 14 raise HTTPException(status_code=401, detail="Incorrect username or password") 15 16 17# Login endpoint 18@app.post("/login") 19async def login(form_data: OAuth2PasswordRequestForm = Depends()): 20 return authenticate_user(form_data.username, form_data.password)
In our login endpoint, we briefly used Dependency Injection with the Depends
function. Here's how we did it:
Python1from fastapi import Depends 2from fastapi.security import OAuth2PasswordRequestForm 3 4@app.post("/login") 5async def login(form_data: OAuth2PasswordRequestForm = Depends()): 6 return authenticate_user(form_data.username, form_data.password)
-
Depends()
: In the login endpoint, we usedDepends()
to get an instance ofOAuth2PasswordRequestForm
, which contains the username and password. -
Parameter Injection: Instead of manually extracting username and password from the request,
Depends
automatically handled it for us and injectedform_data
directly into the endpoint function. -
Cleaner Code: This allowed our
login
function to focus on authenticating the user without worrying about how to extract the credentials from the request.
This initial use of Depends
made our endpoint simpler and more declarative. Now, we'll build on this concept to secure our endpoints further.
Now, let's translate the use of Dependency Injection from our login form data to securing an endpoint. We'll use Depends
to ensure only authenticated users can access a certain endpoint.
Python1# Secure endpoint that requires user authentication 2@app.get("/secure-message") 3async def read_secure_message(username: str, password: str, user: dict = Depends(authenticate_user)): 4 return {"message": "This is a secured message"}
The endpoint function read_secure_message
takes three parameters:
- username: The username provided by the user as a query parameter
- password: The password provided by the user as a query parameter
- user: A dictionary that holds the result of the
authenticate_user
function
In this endpoint, we use Depends(authenticate_user)
for Dependency Injection:
- Explicit Dependency: By using
Depends(authenticate_user)
, we ensure FastAPI will callauthenticate_user
using theusername
andpassword
from the query parameters. - Parameter Passing: When a request is made, FastAPI extracts
username
andpassword
from the query parameters and passes them toauthenticate_user
. - Injection: The result of
authenticate_user
is then injected into theuser
parameter of theread_secure_message
function.
This approach ensures our secure endpoint's user
parameter contains the result of the authentication check, allowing only authenticated users access to the endpoint.
Here's the flow when a request is made to the /secure-message
endpoint:
-
Input Request: The client sends a request with
username
andpassword
as query parameters. -
Dependency Injection: FastAPI uses
Depends
to callauthenticate_user
with the provided credentials. -
Authentication Process in
authenticate_user
:- If the credentials match an entry in
users_db
, it returns{"username": username}
. - If not, it raises
HTTPException
with a 401 status code.
- If the credentials match an entry in
-
Response Handling: Once
authenticate_user
returns a value, it's injected into theuser
parameter of theread_secure_message
function. This confirms the user is authenticated, allowing the endpoint to return the secured message.
In this lesson, we introduced Dependency Injection and its benefits. You learned how to use FastAPI's Depends
function to secure an endpoint, ensuring only authenticated users can access it. We walked through the complete solution code and explained each part to make the concept clear.
Now, it's time to practice what you've learned! You will work on exercises designed to help you master securing endpoints using Dependency Injection. By now, you should feel confident in implementing basic user authentication and securing endpoints in FastAPI.