Action: file_editor view /app/backend/server.py
Observation: /app/backend/server.py:
1|from fastapi import FastAPI, APIRouter
2|from dotenv import load_dotenv
3|from starlette.middleware.cors import CORSMiddleware
4|from motor.motor_asyncio import AsyncIOMotorClient
5|import os
6|import logging
7|from pathlib import Path
8|from pydantic import BaseModel, Field, ConfigDict
9|from typing import List
10|import uuid
11|from datetime import datetime, timezone
12|
13|
14|ROOT_DIR = Path(_file_).parent
15|load_dotenv(ROOT_DIR / '.env')
16|
17|# MongoDB connection
18|mongo_url = os.environ['MONGO_URL']
19|client = AsyncIOMotorClient(mongo_url)
20|db = client[os.environ['DB_NAME']]
21|
22|# Create the main app without a prefix
23|app = FastAPI()
24|
25|# Create a router with the /api prefix
26|api_router = APIRouter(prefix="/api")
27|
28|
29|# Define Models
30|class StatusCheck(BaseModel):
31| model_config = ConfigDict(extra="ignore") # Ignore MongoDB's _id field
32|
33| id: str = Field(default_factory=lambda: str(uuid.uuid4()))
34| client_name: str
35| timestamp: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
36|
37|class StatusCheckCreate(BaseModel):
38| client_name: str
39|
40|# Add your routes to the router instead of directly to app
41|@api_router.get("/")
42|async def root():
43| return {"message": "Hello World"}
44|
45|@api_router.post("/status", response_model=StatusCheck)
46|async def create_status_check(input: StatusCheckCreate):
47| status_dict = input.model_dump()
48| status_obj = StatusCheck(**status_dict)
49|
50| # Convert to dict and serialize datetime to ISO string for MongoDB
51| doc = status_obj.model_dump()
52| doc['timestamp'] = doc['timestamp'].isoformat()
53|
54| _ = await db.status_checks.insert_one(doc)
55| return status_obj
56|
57|@api_router.get("/status", response_model=List[StatusCheck])
58|async def get_status_checks():
59| # Exclude MongoDB's _id field from the query results
60| status_checks = await db.status_checks.find({}, {"_id": 0}).to_list(1000)
61|
62| # Convert ISO string timestamps back to datetime objects
63| for check in status_checks:
64| if isinstance(check['timestamp'], str):
65| check['timestamp'] = datetime.fromisoformat(check['timestamp'])
66|
67| return status_checks
68|
69|# Include the router in the main app
70|app.include_router(api_router)
71|
72|app.add_middleware(
73| CORSMiddleware,
74| allow_credentials=True,
75| allow_origins=os.environ.get('CORS_ORIGINS', '*').split(','),
76| allow_methods=["*"],
77| allow_headers=["*"],
78|)
79|
80|# Configure logging
81|logging.basicConfig(
82| level=logging.INFO,
83| format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
84|)
85|logger = logging.getLogger(_name_)
86|
Action: file_editor view /app/backend/server.py
Observation: /app/backend/server.py:
1|from fastapi import FastAPI, APIRouter
2|from dotenv import load_dotenv
3|from starlette.middleware.cors import CORSMiddleware
4|from motor.motor_asyncio import AsyncIOMotorClient
5|import os
6|import logging
7|from pathlib import Path
8|from pydantic import BaseModel, Field, ConfigDict
9|from typing import List
10|import uuid
11|from datetime import datetime, timezone
12|
13|
14|ROOT_DIR = Path(_file_).parent
15|load_dotenv(ROOT_DIR / '.env')
16|
17|# MongoDB connection
18|mongo_url = os.environ['MONGO_URL']
19|client = AsyncIOMotorClient(mongo_url)
20|db = client[os.environ['DB_NAME']]
21|
22|# Create the main app without a prefix
23|app = FastAPI()
24|
25|# Create a router with the /api prefix
26|api_router = APIRouter(prefix="/api")
27|
28|
29|# Define Models
30|class StatusCheck(BaseModel):
31| model_config = ConfigDict(extra="ignore") # Ignore MongoDB's _id field
32|
33| id: str = Field(default_factory=lambda: str(uuid.uuid4()))
34| client_name: str
35| timestamp: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
36|
37|class StatusCheckCreate(BaseModel):
38| client_name: str
39|
40|# Add your routes to the router instead of directly to app
41|@api_router.get("/")
42|async def root():
43| return {"message": "Hello World"}
44|
45|@api_router.post("/status", response_model=StatusCheck)
46|async def create_status_check(input: StatusCheckCreate):
47| status_dict = input.model_dump()
48| status_obj = StatusCheck(**status_dict)
49|
50| # Convert to dict and serialize datetime to ISO string for MongoDB
51| doc = status_obj.model_dump()
52| doc['timestamp'] = doc['timestamp'].isoformat()
53|
54| _ = await db.status_checks.insert_one(doc)
55| return status_obj
56|
57|@api_router.get("/status", response_model=List[StatusCheck])
58|async def get_status_checks():
59| # Exclude MongoDB's _id field from the query results
60| status_checks = await db.status_checks.find({}, {"_id": 0}).to_list(1000)
61|
62| # Convert ISO string timestamps back to datetime objects
63| for check in status_checks:
64| if isinstance(check['timestamp'], str):
65| check['timestamp'] = datetime.fromisoformat(check['timestamp'])
66|
67| return status_checks
68|
69|# Include the router in the main app
70|app.include_router(api_router)
71|
72|app.add_middleware(
73| CORSMiddleware,
74| allow_credentials=True,
75| allow_origins=os.environ.get('CORS_ORIGINS', '*').split(','),
76| allow_methods=["*"],
77| allow_headers=["*"],
78|)
79|
80|# Configure logging
81|logging.basicConfig(
82| level=logging.INFO,
83| format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
84|)
85|logger = logging.getLogger(_name_)
86|
87|@app.on_event("shutdown")
88|async def shutdown_db_client():
89| client.close()
87|@app.on_event("shutdown")
88|async def shutdown_db_client():
89| client.close()