Skip to content
This repository was archived by the owner on Feb 19, 2023. It is now read-only.

Commit 8002ce2

Browse files
committed
feat: add redis and rate limiter; docs: update readme; ops: add black step
1 parent 32f4e9f commit 8002ce2

File tree

10 files changed

+72
-12
lines changed

10 files changed

+72
-12
lines changed

.env_example

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,5 @@ MONGO_INITDB_DATABASE=fastapibackendbase
1414

1515
NGINX_HOST=localhost
1616
UPSTREAMS=/:backend:8000
17+
18+
REDIS_HOST=redis://redis:6379

.github/workflows/main.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,19 @@ jobs:
1515
- name: Start linter
1616
run: |
1717
docker run --rm -w="/code/backend" -v $(pwd):/code alpine/flake8:3.9.2 .
18+
19+
black:
20+
runs-on: ubuntu-20.04
21+
name: Black code formatting
22+
steps:
23+
- name: Checkout
24+
uses: actions/checkout@v2
25+
- name: Set up Python
26+
uses: actions/setup-python@v1
27+
with:
28+
python-version: '3.9'
29+
- name: run black
30+
working-directory: ./backend
31+
run: |
32+
pip install black==21.5b1
33+
black --check .

README.md

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,33 @@
1+
<p align="center">
2+
<a href="https://github.com/nickatnight/fastapi-backend-base/actions">
3+
<img alt="GitHub Actions status" src="https://github.com/nickatnight/fastapi-backend-base/actions/workflows/main.yml/badge.svg">
4+
</a>
5+
</p>
6+
7+
18
# fastapi-backend-base
29

310
Small base project to build and deploy a fastapi backend..batteries included.
411

5-
## Services
6-
* high performance [FastAPI](https://fastapi.tiangolo.com/) backend
7-
* asynchronous access to key/value [database](https://motor.readthedocs.io/en/stable/)
8-
* [nginx](https://www.nginx.com/blog/lets-encrypt-tls-nginx/) webserver/proxy with automatic ssl cert renewal
12+
## Features
13+
* **Docker Compose** integration and optimization for local development.
14+
* **Production ready** Python web server using Uvicorn
15+
* Python <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">**FastAPI**</a> backend:
16+
* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic).
17+
* **Intuitive**: Great editor support. <abbr title="also known as auto-complete, autocompletion, IntelliSense">Completion</abbr> everywhere. Less time debugging.
18+
* **Easy**: Designed to be easy to use and learn. Less time reading docs.
19+
* **Short**: Minimize code duplication. Multiple features from each parameter declaration.
20+
* **Robust**: Get production-ready code. With automatic interactive documentation.
21+
* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> and <a href="http://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
22+
* <a href="https://fastapi.tiangolo.com/features/" class="external-link" target="_blank">**Many other features**</a> including automatic validation, serialization, interactive documentation, authentication with OAuth2 JWT tokens, etc.
23+
* **SQLAlchemy** models
24+
* **CORS** (Cross Origin Resource Sharing).
25+
* **NGINX** High Performance Load Balancer, Web Server, & Reverse Proxy
26+
* **Let's Encrypt** A free, automated, and open certificate authority (CA), provided by the Internet Security Research Group (ISRG)...with automatic cert renewal.
27+
* **MongoDB** General purpose, document-based, distributed database built for modern application developers.
28+
* **Motor** Coroutine-based API for non-blocking access to MongoDB
29+
* Request rate limiting for api routes.
30+
931

1032
## Usage
1133
1. `git clone https://github.com/nickatnight/fastapi-backend-base.git`

backend/requirements/base.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ motor==2.4.0
99

1010
# utils
1111
PyYAML==5.4.1
12+
fastapi-limiter==0.1.4

backend/src/api/v1/health.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
from fastapi import APIRouter
1+
from fastapi import APIRouter, Depends
2+
from fastapi_limiter.depends import RateLimiter
23

34

45
router = APIRouter()
56

67

7-
@router.get("/ping", tags=["health"])
8+
@router.get("/ping", tags=["health"], dependencies=[Depends(RateLimiter(times=2, seconds=5))])
89
async def pong():
910
# some async operation could happen here
1011
# example: `data = await get_all_datas()`

backend/src/config.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ class Settings(BaseSettings):
1919
MONGODB_PASS: str = Field(..., env="MONGODB_PASS")
2020
MONGODB_DATABASE: str = Field(..., env="MONGODB_DATABASE")
2121

22+
REDIS_HOST: str = Field(..., env="REDIS_HOST")
23+
2224
VERSION: str = Field(..., env="VERSION")
2325

2426

backend/src/db.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
import aioredis
2+
from fastapi_limiter import FastAPILimiter
3+
14
from motor.motor_asyncio import AsyncIOMotorClient
25
from src.config import settings
36

47

5-
MONGODB_URL = f"mongodb://{settings.MONGODB_USER}:{settings.MONGODB_PASS}@mongodb:27017/{settings.MONGODB_DATABASE}" # noqa
8+
MONGODB_URL = f"mongodb://{settings.MONGODB_USER}:{settings.MONGODB_PASS}@{settings.MONGODB_HOST}:27017/{settings.MONGODB_DATABASE}" # noqa
69

710

811
class DataBase:
@@ -18,6 +21,9 @@ async def get_database() -> AsyncIOMotorClient:
1821

1922
async def connect_to_mongo():
2023
db.client = AsyncIOMotorClient(MONGODB_URL, maxPoolSize=3, minPoolSize=0)
24+
redis = await aioredis.create_redis_pool(settings.REDIS_HOST)
25+
26+
await FastAPILimiter.init(redis)
2127

2228

2329
async def close_mongo_connection():

docker-compose.yml

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ volumes:
44
base-data:
55
mongodb-data:
66
proxy-data:
7+
redis-data:
78

89
services:
910
mongodb:
@@ -28,9 +29,11 @@ services:
2829
args:
2930
env: ${ENV}
3031
ports:
31-
- '8000:8000'
32+
- "8000:8000"
3233
command: |
33-
bash -c "while !</dev/tcp/mongodb/27017; do sleep 1; done; uvicorn src.main:app --reload --workers 1 --host 0.0.0.0 --port 8000 --log-config=logconfig.yml"
34+
bash -c "
35+
while !</dev/tcp/mongodb/27017; do sleep 1; done;
36+
uvicorn src.main:app --reload --workers 1 --host 0.0.0.0 --port 8000 --log-config=logconfig.yml"
3437
depends_on:
3538
- mongodb
3639
environment:
@@ -42,11 +45,19 @@ services:
4245
proxy:
4346
restart: always
4447
ports:
45-
- '0.0.0.0:80:80'
48+
- "0.0.0.0:80:80"
4649
env_file:
4750
- .env
4851
build:
4952
context: ./proxy
5053
dockerfile: ./Dockerfile
5154
volumes:
5255
- proxy-data:/etc/letsencrypt
56+
57+
redis:
58+
restart: always
59+
image: redis:latest
60+
ports:
61+
- "6479:6379"
62+
volumes:
63+
- redis-data:/data

ops/docker-compose.staging.yml

Whitespace-only changes.

proxy/Dockerfile

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ RUN apk add --no-cache\
77
py3-pip \
88
curl &&\
99
pip3 install --no-cache-dir \
10-
j2cli==0.3.10 \
11-
boto3==1.12.26 &&\
10+
j2cli==0.3.10 &&\
1211
curl -o /usr/local/bin/waitforit -sSL https://github.com/maxcnunes/waitforit/releases/download/v2.4.1/waitforit-linux_amd64 && \
1312
chmod +x /usr/local/bin/waitforit &&\
1413
rm -rf /etc/nginx/nginx.conf /etc/nginx/conf.d/*

0 commit comments

Comments
 (0)