Skip to content

0.8.0

Compare
Choose a tag to compare
@igorbenav igorbenav released this 25 Nov 03:59
· 211 commits to main since this release
10e05f9

0.8.0 Summary

 🚀Features

  • NGINX deployment🎉
  • Better Custom Exceptions
  • Core Folder Restructured

📝Docs


0. 🚀Core Folder Restructured

Old core folder structure:

├── core                       # Core utilities and configurations for the application.
│   │   ├── __init__.py
│   │   ├── cache.py               # Utilities related to caching.
│   │   ├── config.py              # Application configuration settings.
│   │   ├── database.py            # Database connectivity and session management.
│   │   ├── exceptions.py          # Contains core custom exceptions for the application.
│   │   ├── logger.py              # Logging utilities.
│   │   ├── models.py              # Base models for the application.
│   │   ├── queue.py               # Utilities related to task queues.
│   │   ├── rate_limit.py          # Rate limiting utilities and configurations.
│   │   ├── security.py            # Security utilities like password hashing and token generation.
│   │   └── setup.py               # File defining settings and FastAPI application instance definition.

New structure:

├── core                      # Core utilities and configurations for the application.
│   ├── __init__.py
│   ├── config.py             # Configuration settings for the application.
│   ├── logger.py             # Configuration for application logging.
│   ├── schemas.py            # Pydantic schemas for data validation.
│   ├── security.py           # Security utilities, such as password hashing.
│   ├── setup.py              # Setup file for the FastAPI app instance.
│   │
│   ├── db                    # Core Database related modules.
│   │   ├── __init__.py
│   │   ├── crud_token_blacklist.py  # CRUD operations for token blacklist.
│   │   ├── database.py       # Database connectivity and session management.
│   │   ├── models.py         # Core Database models.
│   │   └── token_blacklist.py  # Model for token blacklist functionality.
│   │
│   ├── exceptions            # Custom exception classes.
│   │   ├── __init__.py
│   │   └── ...
│   │
│   └── utils                 # Utility functions and helpers.
│       ├── __init__.py
│       ├── cache.py          # Cache-related utilities.
│       ├── queue.py          # Utilities for task queue management.
│       └── rate_limit.py     # Rate limiting utilities.

A few relevant notes:

  • Token_blacklist model, schemas and crud were were moved to the core folder.
  • Mixins are now defined as both pydantic schemas and sqlalchemy models

1. ⚡️Better Custom Exceptions

Exception handling was restructured.

Old exceptions structure:

├── app                          # Main application directory.
   ├── ...
   │
   ├── api                       # Folder containing API-related logic.
   │   ├── ...
   │   ├── exceptions.py         # Custom exceptions for the API.
   │
   ├── core                      # Core utilities and configurations for the application.
   │   ├── ...
   │   │
   │   ├── exceptions            # Custom exception classes.
   │   │   ├── __init__.py
   │   │   └── exceptions.py     # Definitions of custom exceptions.

New structure:

├── app                              # Main application directory.
   ├── ...
   │
   ├── core                          # Core utilities and configurations for the application.
   │   ├── ...
   │   │
   │   ├── exceptions                # Custom exception classes.
   │   │   ├── __init__.py
   │   │   ├── cache_exceptions.py   # Exceptions related to cache operations.
   │   │   └── http_exceptions.py    # HTTP-related exceptions.

Now to use http exceptions you may just import from app/core/exceptions/http_exceptions and optionally add a detail:

from app.core.exceptions.http_exceptions import NotFoundException

# If you want to specify the detail, just add the message
if not user:
  raise NotFoundException("User not found")

# Or you may just use the default message
if not post:
  raise NotFoundException()

The predefined possibilities in http_exceptions are the following:

  • CustomException: 500 internal error
  • BadRequestException: 400 bad request
  • NotFoundException: 404 not found
  • ForbiddenException: 403 forbidden
  • UnauthorizedException: 401 unauthorized
  • UnprocessableEntityException: 422 unprocessable entity
  • DuplicateValueException: 422 unprocessable entity
  • RateLimitException: 429 too many requests

2. 🎉NGINX deployment

NGINX is a high-performance web server, known for its stability, rich feature set, simple configuration, and low resource consumption. NGINX acts as a reverse proxy, that is, it receives client requests, forwards them to the FastAPI server (running via Uvicorn or Gunicorn), and then passes the responses back to the clients.

To run with NGINX, you start by uncommenting the following part in your docker-compose.yml:

# docker-compose.yml

...
  # #-------- uncomment to run with nginx --------
  # nginx:
  #   image: nginx:latest
  #   ports:
  #     - "80:80"
  #   volumes:
  #     - ./default.conf:/etc/nginx/conf.d/default.conf
  #   depends_on:
  #     - web
...

Which should be changed to:

# docker-compose.yml

...
  #-------- uncomment to run with nginx --------
  nginx:
    image: nginx:latest
    ports:
      - "80:80"
    volumes:
      - ./default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - web
...

Then comment the following part:

# docker-compose.yml

services:
  web:
    ...
    # -------- Both of the following should be commented to run with nginx --------
    command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
    # command: gunicorn app.main:app -w 4 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8000

Which becomes:

# docker-compose.yml

services:
  web:
    ...
    # -------- Both of the following should be commented to run with nginx --------
    # command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
    # command: gunicorn app.main:app -w 4 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8000

Then pick the way you want to run (uvicorn or gunicorn managing uvicorn workers) in Dockerfile.
The one you want should be uncommented, comment the other one.

# Dockerfile

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
# CMD ["gunicorn", "app.main:app", "-w", "4", "-k", "uvicorn.workers.UvicornWorker". "-b", "0.0.0.0:8000"]
1. One Server

If you want to run with one server only, your setup should be ready. Just make sure the only part that is not a comment in deafult.conf is:

# default.conf

# ---------------- Running With One Server ----------------
server {
    listen 80;

    location / {
        proxy_pass http://web:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
2. Multiple Servers

NGINX can distribute incoming network traffic across multiple servers, improving the efficiency and capacity utilization of your application.

To run with multiple servers, just comment the Running With One Server part in default.conf and Uncomment the other one:

# default.conf

# ---------------- Running With One Server ----------------
...

# ---------------- To Run with Multiple Servers, Uncomment below ----------------
upstream fastapi_app {
    server fastapi1:8000;  # Replace with actual server names or IP addresses
    server fastapi2:8000;
    # Add more servers as needed
}

server {
    listen 80;

    location / {
        proxy_pass http://fastapi_app; 
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Warning

Note that we are using fastapi1:8000 and fastapi2:8000 as examples, you should replace it with the actual name of your service and the port it's running on.

What's Changed

Full Changelog: v0.7.0...v0.8.0