Skip to content

Commit a67fa11

Browse files
stackjayjaygaha
authored andcommitted
day #48 fastapi #5 http status code & error handling
1 parent 06e07bc commit a67fa11

15 files changed

Lines changed: 983 additions & 0 deletions

File tree

workspace/7_framework/fastapi/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ uvicorn main:app --reload
8181
Learn how to handle JSON request bodies, work with form data and file uploads, and combine different types of parameters in your API endpoints.
8282
_Includes: request body examples, form and file upload handling, mixed parameter endpoints, and test coverage._
8383

84+
- [Day 05: HTTP Status Codes and Error Handling](day05/README.md)
85+
Learn how to use and return appropriate HTTP status codes, create custom exception classes, handle validation and business logic errors, and implement global exception handlers for consistent error responses.
86+
_Includes: custom error classes, exception handlers, validation and business logic error handling, logging, and test coverage._
87+
8488
---
8589

8690
## Recommended Project Structure
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# FastAPI Day 05: HTTP Status Codes and Error Handling
2+
3+
Welcome to **Day 05** of the FastAPI tutorial! Today you'll learn how to handle HTTP status codes, create custom error responses, and manage exceptions in your API endpoints.
4+
5+
---
6+
7+
## What You'll Learn
8+
9+
- How to use and return appropriate HTTP status codes
10+
- How to create and use custom exception classes
11+
- How to handle validation and business logic errors gracefully
12+
- How to implement global exception handlers for consistent error responses
13+
- How to write automated tests for error handling
14+
15+
---
16+
17+
## Key Concepts
18+
19+
### 1. HTTP Status Codes
20+
21+
- **HTTP status codes** communicate the result of an API request.
22+
- Use codes like `200 OK`, `201 Created`, `404 Not Found`, `409 Conflict`, `422 Unprocessable Entity`, and `500 Internal Server Error` to indicate different outcomes.
23+
24+
Example status codes:
25+
```
26+
201 Created - When a new item or order is successfully created
27+
404 Not Found - When a requested resource does not exist
28+
409 Conflict - When there is a duplicate or business logic conflict
29+
422 Unprocessable Entity - When validation fails
30+
500 Internal Server Error - For unexpected errors
31+
```
32+
33+
### 2. Custom Exception Classes
34+
35+
- Define custom exception classes for common error scenarios (e.g., not found, insufficient stock, duplicate item).
36+
- Inherit from FastAPI's `HTTPException` for easy integration.
37+
38+
Example custom exception:
39+
```
40+
class ItemNotFoundError(HTTPException):
41+
def __init__(self, item_id: int):
42+
super().__init__(
43+
status_code=status.HTTP_404_NOT_FOUND,
44+
detail=f"Item with ID {item_id} not found",
45+
)
46+
```
47+
48+
### 3. Exception Handlers
49+
50+
- Use FastAPI's `@app.exception_handler` to create global handlers for your custom exceptions.
51+
- Return structured error responses with details, error type, and timestamps.
52+
53+
Example handler:
54+
```
55+
@app.exception_handler(ItemNotFoundError)
56+
async def item_not_found_handler(request: Request, exc: ItemNotFoundError):
57+
return JSONResponse(
58+
status_code=exc.status_code,
59+
content={
60+
"error": "Item Not Found",
61+
"message": exc.detail,
62+
"timestamp": datetime.now().isoformat(),
63+
"path": str(request.url.path)
64+
}
65+
)
66+
```
67+
68+
### 4. Validation and Business Logic Errors
69+
70+
- Use Pydantic for request validation and raise custom errors for business logic issues (e.g., insufficient stock, invalid transitions).
71+
- Customize error responses for better client experience.
72+
73+
Example validation error:
74+
```
75+
@app.exception_handler(RequestValidationError)
76+
async def request_validation_error_handler(request: Request, exc: RequestValidationError):
77+
return JSONResponse(
78+
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
79+
content={
80+
"error": "Validation Error",
81+
"message": "Invalid request data",
82+
"details": exc.errors(),
83+
"timestamp": datetime.now().isoformat(),
84+
"path": str(request.url.path)
85+
}
86+
)
87+
```
88+
89+
### 5. Logging and Monitoring
90+
91+
- Use Python's `logging` module to log errors and important events.
92+
- Logging helps with debugging and monitoring your API in production.
93+
94+
---
95+
96+
## Next Steps
97+
98+
- Try sending requests that trigger different error scenarios (e.g., not found, duplicate, validation errors).
99+
- Explore the code to see how exceptions and handlers are implemented.
100+
- Run the tests to ensure error handling works as expected!
101+
102+
---
103+
104+
**Tip:** FastAPI’s automatic docs are available at `/api/docs` when you run your app.
105+
106+
---
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[pytest]
2+
asyncio_default_fixture_loop_scope = function
3+
pythonpath = . src
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
fastapi>=0.115.0
2+
uvicorn>=0.30.0
3+
python-multipart>=0.0.20
4+
pytest>=7.0.0
5+
pytest-asyncio>=0.20.0
6+
pytest-cov>=4.0.0
7+
httpx>=0.24.0
8+
flake8>=5.0.0

workspace/7_framework/fastapi/day05/src/__init__.py

Whitespace-only changes.

workspace/7_framework/fastapi/day05/src/enums/__init__.py

Whitespace-only changes.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from enum import Enum
2+
3+
class OrderStatus(str, Enum):
4+
pending = "pending"
5+
processing = "processing"
6+
shipped = "shipped"
7+
delivered = "delivered"
8+
cancelled = "cancelled"
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
"""
2+
Global exceptions for the FastAPI application.
3+
"""
4+
5+
from fastapi import HTTPException, status
6+
7+
class ItemNotFoundError(HTTPException):
8+
def __init__(self, item_id: int):
9+
super().__init__(
10+
status_code=status.HTTP_404_NOT_FOUND,
11+
detail=f"Item with ID {item_id} not found",
12+
)
13+
14+
class InsufficientStockError(HTTPException):
15+
def __init__(self, item_id: int, requested: int, available: int):
16+
super().__init__(
17+
status_code=status.HTTP_409_CONFLICT,
18+
detail=f"Insufficient stock for item {item_id}. Requested: {requested}, Available: {available}"
19+
)
20+
21+
class DuplicateItemError(HTTPException):
22+
def __init__(self, field: str, value: str):
23+
super().__init__(
24+
status_code=status.HTTP_409_CONFLICT,
25+
detail=f"Item with ID {field} '{value}' already exists",
26+
)
27+
28+
class ValidationFailedError(HTTPException):
29+
def __init__(self, errors: list):
30+
super().__init__(
31+
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
32+
detail=errors,
33+
)
34+
35+
class UnauthorizedError(HTTPException):
36+
def __init__(self):
37+
super().__init__(
38+
status_code=status.HTTP_401_UNAUTHORIZED,
39+
detail="Unauthorized",
40+
)
41+
42+
class ForbiddenError(HTTPException):
43+
def __init__(self):
44+
super().__init__(
45+
status_code=status.HTTP_403_FORBIDDEN,
46+
detail="Forbidden",
47+
)
48+
49+
class InternalServerError(HTTPException):
50+
def __init__(self):
51+
super().__init__(
52+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
53+
detail="Internal Server Error",
54+
)

0 commit comments

Comments
 (0)