Skip to content

Commit a7966d2

Browse files
committed
feature: middleware updated & fastapi server created & docker backend service added
1 parent 0e14ef2 commit a7966d2

File tree

9 files changed

+194
-12
lines changed

9 files changed

+194
-12
lines changed

.envs/.backend.env

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
POSTGRES_USER="postgres"
2+
POSTGRES_PASSWORD="postgres"
3+
POSTGRES_HOST="postgres"
4+
POSTGRES_PORT=5432
5+
POSTGRES_DB="bookly"
6+
7+
DATABASE_URL="postgresql://postgres:postgres@postgres:5432/bookly"

compose/backend/Dockerfile

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
FROM docker.io/python:3.12.3-slim-bookworm AS python
2+
3+
FROM python AS python-build-stage
4+
5+
RUN apt-get update && apt-get install --no-install-recommends -y \
6+
build-essential \
7+
libpq-dev
8+
9+
COPY ./requirements.txt .
10+
11+
RUN pip wheel --wheel-dir /usr/src/app/wheels -r requirements.txt
12+
13+
FROM python AS python-run-stage
14+
15+
ARG APP_HOME=/app
16+
17+
ENV PYTHONUNBUFFERED=1
18+
ENV PYTHONDONTWRITEBYTECODE=1
19+
20+
WORKDIR ${APP_HOME}
21+
22+
RUN apt-get update && apt-get install --no-install-recommends -y \
23+
libpq-dev \
24+
gettext \
25+
&& apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
26+
&& rm -rf /var/lib/apt/lists/*
27+
28+
COPY --from=python-build-stage /usr/src/app/wheels /wheels/
29+
30+
RUN pip install --no-cache-dir --no-index --find-links=/wheels/ /wheels/* \
31+
&& rm -rf /wheels/
32+
33+
COPY ./compose/backend/entrypoint /entrypoint
34+
RUN sed -i 's/\r$//g' /entrypoint
35+
RUN chmod +x /entrypoint
36+
37+
COPY ./compose/backend/start /start
38+
RUN sed -i 's/\r$//g' /start
39+
RUN chmod +x /start
40+
41+
COPY . ${APP_HOME}
42+
43+
ENTRYPOINT ["/entrypoint"]

compose/backend/entrypoint

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#!/bin/bash
2+
3+
set -o errexit
4+
set -o pipefail
5+
set -o nounset
6+
7+
if [ -z "${POSTGRES_USER}" ]; then
8+
base_postgres_image_default_user='postgres'
9+
export POSTGRES_USER="${base_postgres_image_default_user}"
10+
fi
11+
12+
export DATABASE_URL="postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}"
13+
14+
python << END
15+
import sys
16+
import time
17+
import psycopg2
18+
19+
suggest_unrecoverable_after = 30
20+
start = time.time()
21+
22+
while True:
23+
try:
24+
psycopg2.connect(
25+
dbname="${POSTGRES_DB}",
26+
user="${POSTGRES_USER}",
27+
password="${POSTGRES_PASSWORD}",
28+
host="${POSTGRES_HOST}",
29+
port="${POSTGRES_PORT}",
30+
)
31+
break
32+
except psycopg2.OperationalError as error:
33+
sys.stderr.write("Waiting for PostgreSQL to become available...\n")
34+
35+
if time.time() - start > suggest_unrecoverable_after:
36+
sys.stderr.write(" This is taking longer than expected. The following exception may be indicative of an unrecoverable error: '{}'\n".format(error))
37+
38+
time.sleep(1)
39+
40+
sys.stderr.write('PostgreSQL is available\n')
41+
END
42+
43+
exec "$@"

compose/backend/start

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/bin/bash
2+
3+
4+
set -o errexit
5+
set -o pipefail
6+
set -o nounset
7+
8+
9+
exec fastapi dev src --host 0.0.0.0 --port 8000

docker-compose.yml

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,26 @@
11
services:
2+
backend:
3+
build:
4+
context: .
5+
dockerfile: ./compose/backend/Dockerfile
6+
container_name: backend
7+
image: backend:latest
8+
ports:
9+
- "8000:8000"
10+
volumes:
11+
- .:/app:z
12+
env_file:
13+
- ./.envs/.backend.env
14+
command: /start
15+
networks:
16+
- bookly-backend-network
17+
depends_on:
18+
postgres:
19+
condition: service_healthy
20+
221
postgres:
322
image: postgres:16
423
container_name: postgres
5-
ports:
6-
- "5432:5432"
724
volumes:
825
- postgres_data:/var/lib/postgresql/data
926
env_file:

pkg/middleware.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import logging
22
import time
33

4-
from fastapi import FastAPI, Request
4+
from fastapi import FastAPI, Request, status
55
from fastapi.middleware.cors import CORSMiddleware
66
from fastapi.middleware.trustedhost import TrustedHostMiddleware
7+
from fastapi.responses import JSONResponse
78

89
logger = logging.getLogger("uvicorn.access")
910
logger.disabled = True
@@ -14,7 +15,13 @@ def register_middleware(app: FastAPI):
1415
@app.middleware("http")
1516
async def custom_logging(request: Request, call_next):
1617
start_time = time.time()
17-
response = await call_next(request)
18+
try:
19+
response = await call_next(request)
20+
except Exception as e:
21+
return JSONResponse(
22+
content={"message": "Internal Server Error", "error": str(e)},
23+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
24+
)
1825
processing_time = time.time() - start_time
1926
message = (
2027
f"{request.client.host}:{request.client.port} - {request.method} "
@@ -23,14 +30,6 @@ async def custom_logging(request: Request, call_next):
2330
print(message)
2431
return response
2532

26-
app.add_middleware(
27-
CORSMiddleware,
28-
allow_origins=["*"],
29-
allow_methods=["*"],
30-
allow_headers=["Content-Type", "Authorization"],
31-
allow_credentials=True,
32-
)
33-
3433
app.add_middleware(
3534
TrustedHostMiddleware,
3635
allowed_hosts=[
@@ -39,3 +38,11 @@ async def custom_logging(request: Request, call_next):
3938
"0.0.0.0",
4039
],
4140
)
41+
42+
app.add_middleware(
43+
CORSMiddleware,
44+
allow_origins=["*"],
45+
allow_methods=["*"],
46+
allow_headers=["Content-Type", "Authorization"],
47+
allow_credentials=True,
48+
)

requirements.txt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,40 @@
11
alembic==1.13.3
22
annotated-types==0.7.0
33
anyio==4.6.0
4+
certifi==2024.8.30
5+
click==8.1.7
6+
dnspython==2.7.0
7+
email_validator==2.2.0
48
fastapi==0.115.0
9+
fastapi-cli==0.0.5
510
greenlet==3.1.1
11+
h11==0.14.0
12+
httpcore==1.0.6
13+
httptools==0.6.1
14+
httpx==0.27.2
615
idna==3.10
16+
Jinja2==3.1.4
717
Mako==1.3.5
18+
markdown-it-py==3.0.0
819
MarkupSafe==2.1.5
20+
mdurl==0.1.2
921
psycopg2-binary==2.9.9
1022
pydantic==2.9.2
1123
pydantic-settings==2.5.2
1224
pydantic_core==2.23.4
25+
Pygments==2.18.0
1326
python-dotenv==1.0.1
27+
python-multipart==0.0.12
28+
PyYAML==6.0.2
29+
rich==13.9.2
30+
shellingham==1.5.4
1431
sniffio==1.3.1
1532
SQLAlchemy==2.0.35
1633
sqlmodel==0.0.22
1734
starlette==0.38.6
35+
typer==0.12.5
1836
typing_extensions==4.12.2
37+
uvicorn==0.31.0
38+
uvloop==0.20.0
39+
watchfiles==0.24.0
40+
websockets==13.1

src/__init__.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from fastapi import FastAPI
2+
3+
from pkg.errors import register_all_errors
4+
from pkg.middleware import register_middleware
5+
6+
version = "v1"
7+
8+
description = """
9+
Bookly is an innovative online platform designed for book lovers to connect and share their personal collections. Users can easily list the novels and books they own, making them available for others to purchase or borrow. Whether you’re looking to clear space on your bookshelf, discover new reads, or lend a hand to fellow readers, Bookly creates a community-driven marketplace for exchanging books. With a simple and user-friendly interface, Bookly makes it effortless to explore a wide variety of titles, fostering a sustainable and connected book-sharing experience.
10+
11+
This REST API Can:
12+
- User Authentication (Register, Login, Logout, User Activation, Reset Password, etc.)
13+
"""
14+
15+
version_prefix = f"/api/{version}"
16+
17+
app = FastAPI(
18+
title="Bookly",
19+
description=description,
20+
version=version,
21+
license_info={"name": "MIT License", "url": "https://opensource.org/license/mit"},
22+
contact={
23+
"name": "Rohit Vilas Ingole",
24+
"url": "https://github.com/dataorhit",
25+
"email": "rohit.vilas.ingole@gmail.com",
26+
},
27+
openapi_url=f"{version_prefix}/openapi.json",
28+
docs_url=f"{version_prefix}/docs",
29+
redoc_url=f"{version_prefix}/redoc",
30+
)
31+
32+
33+
register_all_errors(app)
34+
register_middleware(app)

src/auth/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)