Added routers
This commit is contained in:
parent
6a7abd3f95
commit
5fddd43c02
24
README.md
24
README.md
@ -16,6 +16,7 @@ This is a template for building APIs with Clean Architecture. It contains two ex
|
||||
## Prepare
|
||||
|
||||
```bash
|
||||
cp envExample .env
|
||||
make build network
|
||||
```
|
||||
|
||||
@ -25,20 +26,27 @@ make build network
|
||||
make api.fastapi.run
|
||||
```
|
||||
|
||||
Now, you can test the API with the following command:
|
||||
|
||||
```bash
|
||||
curl -X 'GET' 'http://localhost:8000/api/v1/documents/?appName=app_test&clientId=client_test' -H 'accept: application/json' | jq
|
||||
```
|
||||
|
||||
## Run Flask
|
||||
|
||||
```bash
|
||||
make api.flask.run
|
||||
```
|
||||
## API
|
||||
|
||||
Now, you can test the API with the following command:
|
||||
### Welcome
|
||||
|
||||
```bash
|
||||
curl -X 'GET' 'http://localhost:5000/api/v1/documents/?appName=app_test&clientId=client_test' -H 'accept: application/json' | jq
|
||||
curl -X 'GET' 'http://localhost:5000' -H 'accept: application/json'
|
||||
```
|
||||
|
||||
### Documents
|
||||
|
||||
```bash
|
||||
curl -X 'GET' 'http://localhost:5000/api/v1/documents/?appName=app_test&clientId=client_test' -H 'accept: application/json'
|
||||
```
|
||||
|
||||
## SEE
|
||||
|
||||
```bash
|
||||
curl -N -H "Accept:text/event-stream" http://localhost:5000/sse/alerts/
|
||||
```
|
||||
|
0
envExample
Normal file
0
envExample
Normal file
37
src/core/use_case/alerts_use_case.py
Normal file
37
src/core/use_case/alerts_use_case.py
Normal file
@ -0,0 +1,37 @@
|
||||
from pydantic import BaseModel, StrictStr, StrictInt
|
||||
|
||||
from src.core.decorators import check_params
|
||||
from faker import Faker
|
||||
from src.core.entity.ResponseTypes import ResponseTypes
|
||||
import random
|
||||
|
||||
|
||||
class GetNextAlertModel(BaseModel):
|
||||
type_alert: StrictStr
|
||||
point: StrictInt
|
||||
|
||||
faker = Faker()
|
||||
|
||||
@check_params(GetNextAlertModel)
|
||||
def get_next_alert(params) -> dict:
|
||||
"""
|
||||
Get next alert
|
||||
|
||||
:param GetNextAlertModel params:
|
||||
:return: dict
|
||||
"""
|
||||
return {
|
||||
"type": ResponseTypes.SUCCESS,
|
||||
"error": None,
|
||||
"data": {
|
||||
"id": faker.uuid4(),
|
||||
"type": random.choice(["ok", "warning", "danger"]),
|
||||
"message": random.choice([
|
||||
f"The node number {random.randint(1, 8)} needs attention",
|
||||
f"The connection with the node number {random.randint(1, 8)} is unstable",
|
||||
f"The node number {random.randint(1, 8)} is offline",
|
||||
f"The node number {random.randint(1, 8)} is overheating",
|
||||
f"The node number {random.randint(1, 8)} is under maintenance",
|
||||
]),
|
||||
}
|
||||
}
|
@ -2,3 +2,4 @@ FROM base-core-app
|
||||
|
||||
# launcher
|
||||
ENTRYPOINT flask --app main run --host=0.0.0.0 --debug
|
||||
#ENTRYPOINT gunicorn main:app --worker-class gevent --bind 0.0.0.0:5000
|
||||
|
@ -1,21 +1,20 @@
|
||||
import os
|
||||
import time
|
||||
import random
|
||||
|
||||
from flask import Flask, request
|
||||
from flask import Flask, request, Response
|
||||
|
||||
from src.core.use_case import documents_use_case
|
||||
from src.infra.storage.AzureStorage import AzureStorage
|
||||
from src.infra.api.flask.middlewares import register_middlewares
|
||||
from src.infra.api.flask.routes.sse_routes import sse_routes
|
||||
from src.infra.api.flask.routes.api_documents_routes import documents_routes
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
register_middlewares(app)
|
||||
|
||||
# Blueprints
|
||||
app.register_blueprint(documents_routes)
|
||||
app.register_blueprint(sse_routes)
|
||||
|
||||
@app.route("/api/v1/documents/")
|
||||
def documents_list():
|
||||
storage = AzureStorage(
|
||||
account_name=os.getenv("AZURE_STORAGE_ACCOUNT_NAME", ""),
|
||||
account_key=os.getenv("AZURE_STORAGE_ACCOUNT_KEY", ""),
|
||||
)
|
||||
params = request.args
|
||||
return documents_use_case.documents_list(storage=storage, params=params)
|
||||
@app.route('/')
|
||||
def index():
|
||||
return {'Welcome to Clean Architecture template!': 'The endpoint you are looking for is not in this castle. Read the documentation to find the right path.'}
|
||||
|
@ -69,6 +69,7 @@ def register_middlewares(app):
|
||||
"""
|
||||
Convert the keys of the response to camel case (snake_case to camelCase) in all levels
|
||||
"""
|
||||
if response.status_code == 200 and request.headers.get("Accept", None) != "text/event-stream":
|
||||
response.data = json.dumps(
|
||||
convert_keys_to_camel_case(json.loads(response.data))
|
||||
)
|
||||
@ -79,6 +80,7 @@ def register_middlewares(app):
|
||||
"""
|
||||
Convert the response to JSON format
|
||||
"""
|
||||
if response.status_code == 200 and request.headers.get("Accept", None) != "text/event-stream":
|
||||
response.headers["Content-Type"] = "application/json"
|
||||
return response
|
||||
|
||||
|
@ -1 +1,3 @@
|
||||
flask
|
||||
gunicorn
|
||||
gevent
|
||||
|
16
src/infra/api/flask/routes/api_documents_routes.py
Normal file
16
src/infra/api/flask/routes/api_documents_routes.py
Normal file
@ -0,0 +1,16 @@
|
||||
import os
|
||||
from flask import Blueprint, request
|
||||
from src.core.use_case import documents_use_case
|
||||
from src.infra.storage.AzureStorage import AzureStorage
|
||||
|
||||
documents_routes = Blueprint("api_documents_routes", __name__, url_prefix="/api/v1/documents")
|
||||
|
||||
|
||||
@documents_routes.route("/")
|
||||
def documents_list():
|
||||
storage = AzureStorage(
|
||||
account_name=os.getenv("AZURE_STORAGE_ACCOUNT_NAME", ""),
|
||||
account_key=os.getenv("AZURE_STORAGE_ACCOUNT_KEY", ""),
|
||||
)
|
||||
params = request.args
|
||||
return documents_use_case.documents_list(storage=storage, params=params)
|
24
src/infra/api/flask/routes/sse_routes.py
Normal file
24
src/infra/api/flask/routes/sse_routes.py
Normal file
@ -0,0 +1,24 @@
|
||||
import time
|
||||
import random
|
||||
from flask import Blueprint, Response
|
||||
from src.core.use_case import alerts_use_case
|
||||
|
||||
sse_routes = Blueprint("sse_routes", __name__, url_prefix="/sse")
|
||||
|
||||
@sse_routes.route("/alerts/", methods=["GET"])
|
||||
def sse_alerts():
|
||||
"""
|
||||
SSE endpoint to stream alerts
|
||||
"""
|
||||
def generate():
|
||||
try:
|
||||
while True:
|
||||
new_data = alerts_use_case.get_next_alert(params={"type_alert": "test", "point": 1})['data']
|
||||
yield f"data: {new_data}\n\n"
|
||||
time.sleep(random.randint(1, 5))
|
||||
except GeneratorExit:
|
||||
print("SSE stream closed")
|
||||
except Exception as e:
|
||||
print(f"Error in SSE stream: {e}")
|
||||
|
||||
return Response(generate(), content_type="text/event-stream", status=200)
|
Loading…
x
Reference in New Issue
Block a user