-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add FastAPI sample app with postgres and uvicorn
- Loading branch information
Wout Feys
committed
Nov 26, 2024
1 parent
d3e2c7d
commit 99bc180
Showing
12 changed files
with
268 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
AIKIDO_DEBUG=false | ||
AIKIDO_TOKEN="AIK_secret_token" | ||
AIKIDO_BLOCKING=true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
AIKIDO_DEBUG=true | ||
AIKIDO_TOKEN="AIK_secret_token" | ||
AIKIDO_BLOCKING=true | ||
AIKIDO_REALTIME_ENDPOINT="http://host.docker.internal:5000/" | ||
AIKIDO_ENDPOINT="http://host.docker.internal:5000/" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# Use an official Python runtime as a parent image | ||
FROM python:3.11 | ||
|
||
#Copy code base | ||
COPY ./ /tmp | ||
|
||
# Set the working directory | ||
WORKDIR /app | ||
|
||
# Install dependencies | ||
RUN mv /tmp/sample-apps/fastapi-postgres-uvicorn/requirements.txt ./ | ||
RUN pip install -r requirements.txt | ||
|
||
# Build and install aikido_zen from source | ||
WORKDIR /tmp | ||
RUN pip install poetry | ||
RUN rm -rf ./dist | ||
RUN make build | ||
RUN mv ./dist/aikido_zen-*.tar.gz ./dist/aikido_zen.tar.gz | ||
RUN pip install ./dist/aikido_zen.tar.gz | ||
RUN pip list | ||
|
||
WORKDIR /app |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# FastAPI w/ Postgres and Uvicorn Sample app | ||
It runs **multi-threaded** and **async** | ||
|
||
## Getting started | ||
Run (with docker-compose installed) : | ||
```bash | ||
docker-compose up --build | ||
``` | ||
|
||
- You'll be able to access the FastAPI Server at : [localhost:8104](http://localhost:8096) | ||
- To Create a reference test dog use `http://localhost:8104/create/` | ||
- To Create a reference test dog (with executemany) use `http://localhost:8104/create_many/` | ||
|
||
- To test a sql injection enter the following dog name : `Malicious dog', TRUE); -- ` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
from dotenv import load_dotenv | ||
import os | ||
import time | ||
import asyncpg | ||
from fastapi import FastAPI, Request, HTTPException | ||
from fastapi.responses import HTMLResponse, JSONResponse | ||
from fastapi.templating import Jinja2Templates | ||
from fastapi.middleware.cors import CORSMiddleware | ||
|
||
load_dotenv() | ||
firewall_disabled = os.getenv("FIREWALL_DISABLED") | ||
if firewall_disabled is not None: | ||
if firewall_disabled.lower() != "1": | ||
import aikido_zen # Aikido package import | ||
aikido_zen.protect() | ||
|
||
templates = Jinja2Templates(directory="templates") | ||
|
||
app = FastAPI() | ||
|
||
# CORS middleware (optional, depending on your needs) | ||
app.add_middleware( | ||
CORSMiddleware, | ||
allow_origins=["*"], # Adjust this as needed | ||
allow_credentials=True, | ||
allow_methods=["*"], | ||
allow_headers=["*"], | ||
) | ||
|
||
async def get_db_connection(): | ||
return await asyncpg.connect( | ||
host="host.docker.internal", | ||
database="db", | ||
user="user", | ||
password="password" | ||
) | ||
|
||
@app.get("/", response_class=HTMLResponse) | ||
async def homepage(request: Request): | ||
conn = await get_db_connection() | ||
dogs = await conn.fetch("SELECT * FROM dogs") | ||
await conn.close() | ||
return templates.TemplateResponse('index.html', {"request": request, "title": 'Homepage', "dogs": dogs}) | ||
|
||
@app.get("/dogpage/{dog_id:int}", response_class=HTMLResponse) | ||
async def get_dogpage(request: Request, dog_id: int): | ||
conn = await get_db_connection() | ||
dog = await conn.fetchrow("SELECT * FROM dogs WHERE id = $1", dog_id) | ||
await conn.close() | ||
if dog is None: | ||
raise HTTPException(status_code=404, detail="Dog not found") | ||
return templates.TemplateResponse('dogpage.html', {"request": request, "title": 'Dog', "dog": dog, "isAdmin": "Yes" if dog[2] else "No"}) | ||
|
||
@app.get("/create", response_class=HTMLResponse) | ||
async def show_create_dog_form(request: Request): | ||
return templates.TemplateResponse('create_dog.html', {"request": request}) | ||
|
||
@app.post("/create") | ||
async def create_dog(request: Request): | ||
data = await request.form() | ||
dog_name = data.get('dog_name') | ||
|
||
if not dog_name: | ||
return JSONResponse({"error": "dog_name is required"}, status_code=400) | ||
|
||
conn = await get_db_connection() | ||
try: | ||
await conn.execute("INSERT INTO dogs (dog_name, isAdmin) VALUES ($1, FALSE)", dog_name) | ||
finally: | ||
await conn.close() | ||
|
||
return JSONResponse({"message": f'Dog {dog_name} created successfully'}, status_code=201) | ||
|
||
@app.get("/just") | ||
async def just(): | ||
return JSONResponse({"message": "Empty Page"}) | ||
|
||
@app.get("/delayed_route") | ||
async def delayed_route(): | ||
time.sleep(1/1000) # Note: This will block the event loop; consider using asyncio.sleep instead | ||
return JSONResponse({"message": "Empty Page"}) | ||
|
||
@app.get("/sync_route") | ||
def sync_route(): | ||
data = {"message": "This is a non-async route!"} | ||
return JSONResponse(data) |
17 changes: 17 additions & 0 deletions
17
sample-apps/fastapi-postgres-uvicorn/docker-compose.benchmark.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
version: "3" | ||
services: | ||
backend_firewall_disabled: | ||
image: sample_fastapi_postgres_uvicorn | ||
command: sh -c "uvicorn app:app --host 0.0.0.0 --port 5000 --workers 4" | ||
restart: always | ||
volumes: | ||
- .:/app | ||
ports: | ||
- "8105:5000" | ||
extra_hosts: | ||
- "app.local.aikido.io:host-gateway" | ||
- "host.docker.internal:host-gateway" | ||
environment: | ||
- FIREWALL_DISABLED=1 | ||
backend: | ||
env_file: .env.example |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
version: '3' | ||
services: | ||
backend: | ||
image: sample_fastapi_postgres_uvicorn | ||
build: | ||
context: ./../../ | ||
dockerfile: ./sample-apps/fastapi-postgres-uvicorn/Dockerfile | ||
container_name: fastapi_postgres_uvicorn_backend | ||
command: sh -c "uvicorn app:app --host 0.0.0.0 --port 5000 --workers 4" | ||
restart: always | ||
volumes: | ||
- .:/app | ||
ports: | ||
- "8104:5000" | ||
extra_hosts: | ||
- "app.local.aikido.io:host-gateway" | ||
- "host.docker.internal:host-gateway" | ||
environment: | ||
- FIREWALL_DISABLED=0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
CREATE TABLE IF NOT EXISTS dogs ( | ||
id SERIAL PRIMARY KEY, | ||
dog_name VARCHAR(250) NOT NULL, | ||
isadmin BOOLEAN NOT NULL DEFAULT FALSE | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
fastapi | ||
jinja2 | ||
asyncpg | ||
cryptography | ||
uvicorn | ||
python-multipart |
17 changes: 17 additions & 0 deletions
17
sample-apps/fastapi-postgres-uvicorn/templates/create_dog.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Create Dog</title> | ||
</head> | ||
<body> | ||
<h1>Create a Dog</h1> | ||
<form method="post"> | ||
<label for="dog_name">Dog Name:</label> | ||
<input type="text" id="dog_name" name="dog_name" required> | ||
<button type="submit">Create Dog</button> | ||
</form> | ||
</body> | ||
</html> |
25 changes: 25 additions & 0 deletions
25
sample-apps/fastapi-postgres-uvicorn/templates/dogpage.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<title>{{ title }}</title> | ||
<style> | ||
body { | ||
font-family: sans-serif; | ||
} | ||
h1 { | ||
font-family: monospace; | ||
text-align: center; | ||
border: 1px solid black; | ||
border-left: none; | ||
border-right: none; | ||
margin: 4px; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<h1>{{ title }}</h1> | ||
<p><em>Name :</em> {{dog[1]}}</p> | ||
<p><em>Is admin dog? </em>{{ isAdmin }}</p> | ||
<p><em>ID :</em> {{dog[0]}}</p> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<title>{{ title }}</title> | ||
<style> | ||
body { | ||
font-family: sans-serif; | ||
} | ||
/* Style for the list */ | ||
ul { | ||
list-style-type:disc; | ||
} | ||
|
||
/* Style for list items */ | ||
li { | ||
margin-bottom: 10px; | ||
} | ||
|
||
/* Style for links */ | ||
a { | ||
text-decoration: none; | ||
color: #48507f; | ||
} | ||
|
||
/* Hover effect for links */ | ||
a:hover { | ||
color: #007bff; | ||
} | ||
h1 { | ||
font-family: monospace; | ||
text-align: center; | ||
border: 1px solid black; | ||
border-left: none; | ||
border-right: none; | ||
margin: 4px; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<h1>{{ title }}</h1> | ||
<h2>List</h2> | ||
<ul> | ||
{% for dog in dogs %} | ||
<li><a href="/dogpage/{{ dog[0] }}">{{ dog[1] }}</a></li> | ||
{% endfor %} | ||
</ul> | ||
</body> | ||
</html> |