|
from fastapi import FastAPI, Request |
|
from fastapi.responses import HTMLResponse |
|
from fastapi.staticfiles import StaticFiles |
|
from fastapi.templating import Jinja2Templates |
|
import os |
|
import datetime |
|
from pydantic import BaseModel |
|
import uvicorn |
|
from fastapi.middleware.cors import CORSMiddleware |
|
|
|
|
|
app = FastAPI(title="FastAPI Web App") |
|
|
|
|
|
app.add_middleware( |
|
CORSMiddleware, |
|
allow_origins=["*"], |
|
allow_credentials=True, |
|
allow_methods=["*"], |
|
allow_headers=["*"], |
|
) |
|
|
|
|
|
os.makedirs('templates', exist_ok=True) |
|
|
|
|
|
templates = Jinja2Templates(directory="templates") |
|
|
|
|
|
if not os.path.exists('templates/index.html'): |
|
os.makedirs('templates', exist_ok=True) |
|
with open('templates/index.html', 'w') as f: |
|
f.write(''' |
|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<title>FastAPI Web App on Hugging Face Spaces</title> |
|
<style> |
|
body { |
|
font-family: Arial, sans-serif; |
|
max-width: 800px; |
|
margin: 0 auto; |
|
padding: 20px; |
|
line-height: 1.6; |
|
} |
|
.container { |
|
border: 1px solid #ddd; |
|
border-radius: 5px; |
|
padding: 20px; |
|
margin-top: 20px; |
|
} |
|
button { |
|
background-color: #4CAF50; |
|
color: white; |
|
padding: 10px 15px; |
|
border: none; |
|
border-radius: 4px; |
|
cursor: pointer; |
|
margin-right: 10px; |
|
} |
|
button:hover { |
|
background-color: #45a049; |
|
} |
|
pre { |
|
background-color: #f5f5f5; |
|
padding: 10px; |
|
border-radius: 4px; |
|
overflow-x: auto; |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<h1>Welcome to FastAPI Web App on Hugging Face Spaces</h1> |
|
<p>The current server time is: {{ current_time }}</p> |
|
|
|
<div class="container"> |
|
<h2>API Demo</h2> |
|
<button id="getTimeBtn">Get Current Time</button> |
|
<button id="sendEchoBtn">Send Echo Request</button> |
|
<div id="result"> |
|
<pre id="output">Results will appear here...</pre> |
|
</div> |
|
</div> |
|
|
|
<script> |
|
document.getElementById('getTimeBtn').addEventListener('click', async () => { |
|
try { |
|
const response = await fetch('/api/time'); |
|
const data = await response.json(); |
|
document.getElementById('output').textContent = JSON.stringify(data, null, 2); |
|
} catch (error) { |
|
document.getElementById('output').textContent = 'Error: ' + error.message; |
|
} |
|
}); |
|
|
|
document.getElementById('sendEchoBtn').addEventListener('click', async () => { |
|
try { |
|
const testData = { |
|
message: "Hello from the client!", |
|
timestamp: new Date().toISOString() |
|
}; |
|
|
|
const response = await fetch('/api/echo', { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/json' |
|
}, |
|
body: JSON.stringify(testData) |
|
}); |
|
|
|
const data = await response.json(); |
|
document.getElementById('output').textContent = JSON.stringify(data, null, 2); |
|
} catch (error) { |
|
document.getElementById('output').textContent = 'Error: ' + error.message; |
|
} |
|
}); |
|
</script> |
|
</body> |
|
</html> |
|
''') |
|
|
|
@app.get("/", response_class=HTMLResponse) |
|
async def index(request: Request): |
|
"""Render the home page.""" |
|
current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") |
|
return templates.TemplateResponse("index.html", {"request": request, "current_time": current_time}) |
|
|
|
@app.get("/api/time") |
|
async def get_time(): |
|
"""API endpoint that returns the current time.""" |
|
current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") |
|
return {"time": current_time} |
|
|
|
class EchoRequest(BaseModel): |
|
"""Model for the echo request body.""" |
|
message: str = None |
|
timestamp: str = None |
|
|
|
@app.post("/api/echo") |
|
async def echo(data: EchoRequest): |
|
"""API endpoint that echoes back the JSON data sent to it.""" |
|
return {"status": "success", "echo": data.dict()} |
|
|
|
|
|
if __name__ == '__main__': |
|
uvicorn.run("app:app", host="0.0.0.0", port=7860, reload=True) |
|
|