|
""" |
|
ๅฎๅ
จๅไฝ็ FastAPI Debug Toolbar - ไฟฎๆญฃ็ |
|
StreamingResponseๅฏพๅฟใใผใธใงใณ + Hugging Face ใชใใธใใชๅๅพๆฉ่ฝ |
|
""" |
|
from fastapi import FastAPI, Request |
|
from fastapi.responses import HTMLResponse, Response |
|
from fastapi.middleware.cors import CORSMiddleware |
|
import time |
|
import json |
|
import asyncio |
|
from datetime import datetime |
|
from starlette.types import Message |
|
|
|
|
|
try: |
|
from huggingface_client import HuggingFaceRepoClient |
|
HF_CLIENT_AVAILABLE = True |
|
except ImportError: |
|
HF_CLIENT_AVAILABLE = False |
|
|
|
app = FastAPI(title="FastAPI Debug Toolbar", description="Laravel้ขจใใใใฐใใผ + Hugging Face้ฃๆบ") |
|
|
|
|
|
app.add_middleware( |
|
CORSMiddleware, |
|
allow_origins=["*"], |
|
allow_credentials=True, |
|
allow_methods=["*"], |
|
allow_headers=["*"], |
|
) |
|
|
|
|
|
debug_data = {"requests": [], "queries": []} |
|
|
|
def generate_debug_bar(request_info): |
|
"""ใใใใฐใใผHTML็ๆ""" |
|
return f""" |
|
<div id="debug-bar" style=" |
|
position: fixed; bottom: 0; left: 0; right: 0; |
|
background: #2d3748; color: white; font-family: monospace; font-size: 12px; |
|
z-index: 9999; border-top: 3px solid #4299e1; max-height: 40px; overflow: hidden; |
|
transition: max-height 0.3s ease; |
|
" onclick="this.style.maxHeight = this.style.maxHeight === '300px' ? '40px' : '300px'"> |
|
|
|
<div style="padding: 8px 15px; background: #1a202c; display: flex; justify-content: space-between; cursor: pointer;"> |
|
<div style="display: flex; gap: 20px;"> |
|
<span style="color: #4299e1; font-weight: bold;">๐ง FastAPI Debug</span> |
|
<span>โฑ๏ธ {request_info['response_time']}</span> |
|
<span>๐ {len(debug_data['queries'])} queries</span> |
|
<span>๐ {request_info['method']} {request_info['path']}</span> |
|
</div> |
|
<span style="color: #68d391;">Status: {request_info['status']}</span> |
|
</div> |
|
|
|
<div style="padding: 15px; max-height: 250px; overflow-y: auto;"> |
|
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;"> |
|
<div> |
|
<h4 style="color: #4299e1; margin: 0 0 8px 0;">๐ Request Info</h4> |
|
<div style="background: #1a202c; padding: 8px; border-radius: 4px; font-size: 11px;"> |
|
<div>Method: {request_info['method']}</div> |
|
<div>Path: {request_info['path']}</div> |
|
<div>Time: {request_info['timestamp']}</div> |
|
<div>Response: {request_info['response_time']}</div> |
|
</div> |
|
</div> |
|
<div> |
|
<h4 style="color: #f56565; margin: 0 0 8px 0;">๐๏ธ Queries ({len(debug_data['queries'])})</h4> |
|
<div style="background: #1a202c; padding: 8px; border-radius: 4px; font-size: 11px;"> |
|
{"<br>".join([f"โข {q['query']} ({q['time']})" for q in debug_data['queries'][-3:]]) or "No queries"} |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
""" |
|
|
|
@app.middleware("http") |
|
async def debug_middleware(request: Request, call_next): |
|
start_time = time.time() |
|
|
|
|
|
response = await call_next(request) |
|
process_time = time.time() - start_time |
|
|
|
|
|
request_info = { |
|
"method": request.method, |
|
"path": request.url.path, |
|
"timestamp": datetime.now().strftime("%H:%M:%S"), |
|
"response_time": f"{process_time:.3f}s", |
|
"status": response.status_code |
|
} |
|
debug_data["requests"].append(request_info) |
|
|
|
|
|
if isinstance(response, HTMLResponse): |
|
try: |
|
body = response.body |
|
if isinstance(body, bytes): |
|
body = body.decode('utf-8') |
|
|
|
if "</body>" in body: |
|
debug_bar = generate_debug_bar(request_info) |
|
body = body.replace("</body>", f"{debug_bar}</body>") |
|
|
|
new_response = HTMLResponse(content=body, status_code=response.status_code) |
|
|
|
for key, value in response.headers.items(): |
|
new_response.headers[key] = value |
|
response = new_response |
|
except Exception as e: |
|
|
|
print(f"Debug bar injection failed: {e}") |
|
|
|
|
|
response.headers["X-Debug-Time"] = f"{process_time:.3f}s" |
|
response.headers["X-Debug-Queries"] = str(len(debug_data["queries"])) |
|
response.headers["X-Debug-Method"] = request.method |
|
response.headers["X-Debug-Path"] = request.url.path |
|
|
|
return response |
|
|
|
def mock_query(sql, delay=0.05): |
|
"""ใใผใฟใใผในใฏใจใชใทใใฅใฌใผใ""" |
|
time.sleep(delay) |
|
debug_data["queries"].append({ |
|
"query": sql, |
|
"time": f"{delay:.3f}s", |
|
"timestamp": datetime.now().isoformat() |
|
}) |
|
|
|
@app.get("/", response_class=HTMLResponse) |
|
async def home(): |
|
|
|
mock_query("SELECT COUNT(*) FROM users", 0.05) |
|
|
|
return f""" |
|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<title>FastAPI Debug Toolbar Demo</title> |
|
<meta charset="utf-8"> |
|
<style> |
|
body {{ |
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; |
|
margin: 0; |
|
padding: 20px; |
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
|
min-height: 100vh; |
|
color: #333; |
|
}} |
|
.container {{ |
|
max-width: 800px; |
|
margin: 0 auto; |
|
background: white; |
|
border-radius: 12px; |
|
box-shadow: 0 10px 30px rgba(0,0,0,0.2); |
|
overflow: hidden; |
|
}} |
|
.header {{ |
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
|
color: white; |
|
padding: 40px; |
|
text-align: center; |
|
}} |
|
.header h1 {{ margin: 0; font-size: 3em; font-weight: 300; }} |
|
.header p {{ margin: 10px 0 0 0; opacity: 0.9; font-size: 1.2em; }} |
|
.content {{ padding: 40px; }} |
|
.feature {{ |
|
background: #f8f9fa; |
|
padding: 25px; |
|
margin: 20px 0; |
|
border-radius: 8px; |
|
border-left: 4px solid #667eea; |
|
}} |
|
.feature h3 {{ |
|
margin: 0 0 15px 0; |
|
color: #667eea; |
|
font-size: 1.3em; |
|
}} |
|
.feature ul {{ margin: 0; padding-left: 20px; }} |
|
.feature li {{ margin: 8px 0; line-height: 1.6; }} |
|
.button {{ |
|
display: inline-block; |
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
|
color: white; |
|
padding: 12px 25px; |
|
text-decoration: none; |
|
border-radius: 25px; |
|
margin: 10px 10px 10px 0; |
|
font-weight: 500; |
|
transition: all 0.3s ease; |
|
box-shadow: 0 3px 10px rgba(102, 126, 234, 0.3); |
|
}} |
|
.button:hover {{ |
|
transform: translateY(-2px); |
|
box-shadow: 0 5px 20px rgba(102, 126, 234, 0.4); |
|
}} |
|
.stats {{ |
|
display: grid; |
|
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); |
|
gap: 20px; |
|
margin: 30px 0; |
|
}} |
|
.stat-card {{ |
|
background: #f8f9fa; |
|
padding: 20px; |
|
border-radius: 8px; |
|
text-align: center; |
|
border-left: 4px solid #28a745; |
|
}} |
|
.stat-number {{ font-size: 2em; font-weight: bold; color: #28a745; }} |
|
.stat-label {{ color: #666; margin-top: 5px; }} |
|
</style> |
|
</head> |
|
<body> |
|
<div class="container"> |
|
<div class="header"> |
|
<h1>๐ง FastAPI Debug Toolbar</h1> |
|
<p>Laravel้ขจใฎใใใใฐใใผใซใใผใฎใใขใณในใใฌใผใทใงใณ</p> |
|
</div> |
|
|
|
<div class="content"> |
|
<div class="stats"> |
|
<div class="stat-card"> |
|
<div class="stat-number">{len(debug_data["requests"])}</div> |
|
<div class="stat-label">Total Requests</div> |
|
</div> |
|
<div class="stat-card"> |
|
<div class="stat-number">{len(debug_data["queries"])}</div> |
|
<div class="stat-label">Database Queries</div> |
|
</div> |
|
<div class="stat-card"> |
|
<div class="stat-number">1</div> |
|
<div class="stat-label">Active Sessions</div> |
|
</div> |
|
</div> |
|
|
|
<div class="feature"> |
|
<h3>โจ ๆฉ่ฝ</h3> |
|
<ul> |
|
<li>๐ฏ <strong>ใชใฏใจในใ่ฟฝ่ทก</strong> - HTTPใกใฝใใใใในใใฌในใใณในๆ้</li> |
|
<li>๐ <strong>ใฏใจใชใขใใฟใชใณใฐ</strong> - ใใผใฟใใผในใฏใจใชใฎๅฎ่กๆ้</li> |
|
<li>โก <strong>ใใใฉใผใใณในๆธฌๅฎ</strong> - ใชใขใซใฟใคใ ใฎๅฟ็ญ้ๅบฆ</li> |
|
<li>๐จ <strong>Laravel้ขจใใถใคใณ</strong> - ่ฆชใใฟใใใใใผใฏใใผใ</li> |
|
</ul> |
|
</div> |
|
|
|
<div class="feature"> |
|
<h3>๐ ไฝฟ็จๆนๆณ</h3> |
|
<p>็ป้ขไธ้จใซ่กจ็คบใใใใใใใฐใใผใใฏใชใใฏใใฆๅฑ้ใใฆใใ ใใใ</p> |
|
<p>ๅใจใณใใใคใณใใซใขใฏใปในใใฆใใใใฐๆ
ๅ ฑใ็ขบ่ชใงใใพใใ</p> |
|
</div> |
|
|
|
<div style="margin-top: 30px; text-align: center;"> |
|
<a href="/api/users" class="button">๐ฅ Users API</a> |
|
<a href="/debug/dashboard" class="button">๐ Debug Dashboard</a> |
|
<a href="/debug/clear" class="button">๐๏ธ Clear Debug Data</a> |
|
<a href="/huggingface" class="button">๐ค HF Repository</a> |
|
</div> |
|
</div> |
|
</div> |
|
</body> |
|
</html> |
|
""" |
|
|
|
@app.get("/api/users", response_class=HTMLResponse) |
|
async def get_users(): |
|
|
|
mock_query("SELECT * FROM users WHERE active = 1", 0.08) |
|
mock_query("SELECT COUNT(*) FROM user_sessions", 0.03) |
|
|
|
users = [ |
|
{"id": 1, "name": "John Doe", "email": "[email protected]"}, |
|
{"id": 2, "name": "Jane Smith", "email": "[email protected]"}, |
|
{"id": 3, "name": "Bob Johnson", "email": "[email protected]"} |
|
] |
|
|
|
|
|
user_rows = "" |
|
for user in users: |
|
user_rows += f""" |
|
<tr> |
|
<td>#{user['id']}</td> |
|
<td>{user['name']}</td> |
|
<td>{user['email']}</td> |
|
<td><span class="badge">Active</span></td> |
|
</tr>""" |
|
|
|
|
|
return f""" |
|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<title>User Management</title> |
|
<meta charset="utf-8"> |
|
<style> |
|
body {{ |
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; |
|
margin: 0; |
|
padding: 20px; |
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
|
min-height: 100vh; |
|
color: #333; |
|
}} |
|
.container {{ |
|
max-width: 1000px; |
|
margin: 0 auto; |
|
background: white; |
|
border-radius: 12px; |
|
box-shadow: 0 10px 30px rgba(0,0,0,0.2); |
|
overflow: hidden; |
|
}} |
|
.header {{ |
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
|
color: white; |
|
padding: 30px; |
|
text-align: center; |
|
}} |
|
.header h1 {{ margin: 0; font-size: 2.5em; font-weight: 300; }} |
|
.content {{ padding: 30px; }} |
|
.stats {{ |
|
display: grid; |
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); |
|
gap: 20px; |
|
margin-bottom: 30px; |
|
}} |
|
.stat-card {{ |
|
background: #f8f9fa; |
|
padding: 20px; |
|
border-radius: 8px; |
|
text-align: center; |
|
border-left: 4px solid #667eea; |
|
}} |
|
.stat-number {{ font-size: 2em; font-weight: bold; color: #667eea; }} |
|
.stat-label {{ color: #666; margin-top: 5px; }} |
|
.user-table {{ |
|
width: 100%; |
|
border-collapse: collapse; |
|
margin-top: 20px; |
|
background: white; |
|
border-radius: 8px; |
|
overflow: hidden; |
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1); |
|
}} |
|
.user-table th {{ |
|
background: #667eea; |
|
color: white; |
|
padding: 15px; |
|
text-align: left; |
|
font-weight: 600; |
|
}} |
|
.user-table td {{ |
|
padding: 15px; |
|
border-bottom: 1px solid #eee; |
|
transition: background 0.2s; |
|
}} |
|
.user-table tr:hover td {{ background: #f8f9fa; }} |
|
.user-table tr:last-child td {{ border-bottom: none; }} |
|
.badge {{ |
|
background: #28a745; |
|
color: white; |
|
padding: 4px 12px; |
|
border-radius: 20px; |
|
font-size: 0.8em; |
|
font-weight: 500; |
|
}} |
|
.nav {{ |
|
background: #f8f9fa; |
|
padding: 15px 30px; |
|
border-bottom: 1px solid #eee; |
|
}} |
|
.nav a {{ |
|
color: #667eea; |
|
text-decoration: none; |
|
margin-right: 20px; |
|
font-weight: 500; |
|
transition: color 0.2s; |
|
}} |
|
.nav a:hover {{ color: #764ba2; }} |
|
</style> |
|
</head> |
|
<body> |
|
<div class="container"> |
|
<div class="nav"> |
|
<a href="/">๐ Home</a> |
|
<a href="/api/users">๐ฅ Users</a> |
|
<a href="/debug/dashboard">๐ง Debug</a> |
|
</div> |
|
|
|
<div class="header"> |
|
<h1>๐ฅ User Management</h1> |
|
<p>Manage your application users</p> |
|
</div> |
|
|
|
<div class="content"> |
|
<div class="stats"> |
|
<div class="stat-card"> |
|
<div class="stat-number">{len(users)}</div> |
|
<div class="stat-label">Total Users</div> |
|
</div> |
|
<div class="stat-card"> |
|
<div class="stat-number">{len(users)}</div> |
|
<div class="stat-label">Active Users</div> |
|
</div> |
|
<div class="stat-card"> |
|
<div class="stat-number">2</div> |
|
<div class="stat-label">Database Queries</div> |
|
</div> |
|
</div> |
|
|
|
<table class="user-table"> |
|
<thead> |
|
<tr> |
|
<th>ID</th> |
|
<th>Name</th> |
|
<th>Email</th> |
|
<th>Status</th> |
|
</tr> |
|
</thead> |
|
<tbody> |
|
{user_rows} |
|
</tbody> |
|
</table> |
|
</div> |
|
</div> |
|
</body> |
|
</html> |
|
""" |
|
|
|
@app.get("/debug/dashboard", response_class=HTMLResponse) |
|
async def debug_dashboard(): |
|
mock_query("SELECT * FROM debug_info", 0.02) |
|
|
|
recent_requests = debug_data["requests"][-10:] |
|
recent_queries = debug_data["queries"][-10:] |
|
|
|
return f""" |
|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<title>Debug Dashboard</title> |
|
<meta charset="utf-8"> |
|
<style> |
|
body {{ font-family: Arial, sans-serif; margin: 20px; background: #1a202c; color: white; }} |
|
.container {{ max-width: 1200px; margin: 0 auto; }} |
|
.grid {{ display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-top: 20px; }} |
|
.card {{ background: #2d3748; padding: 20px; border-radius: 8px; border-left: 4px solid #4299e1; }} |
|
.card h3 {{ margin-top: 0; color: #4299e1; }} |
|
.list-item {{ background: #1a202c; margin: 8px 0; padding: 10px; border-radius: 4px; font-size: 12px; }} |
|
.header {{ text-align: center; color: #4299e1; }} |
|
</style> |
|
</head> |
|
<body> |
|
<div class="container"> |
|
<h1 class="header">๐ง FastAPI Debug Dashboard</h1> |
|
|
|
<div class="grid"> |
|
<div class="card"> |
|
<h3>๐ Recent Requests ({len(recent_requests)})</h3> |
|
{"".join([f'<div class="list-item">{r["timestamp"]} - {r["method"]} {r["path"]} ({r["response_time"]}) - {r["status"]}</div>' for r in recent_requests])} |
|
</div> |
|
|
|
<div class="card"> |
|
<h3>๐๏ธ Recent Queries ({len(recent_queries)})</h3> |
|
{"".join([f'<div class="list-item">{q["query"]} - {q["time"]}</div>' for q in recent_queries])} |
|
</div> |
|
</div> |
|
|
|
<div style="text-align: center; margin-top: 30px;"> |
|
<a href="/" style="color: #4299e1; text-decoration: none;">โ Back to Home</a> |
|
</div> |
|
</div> |
|
</body> |
|
</html> |
|
""" |
|
|
|
@app.get("/debug/clear") |
|
async def clear_debug_data(): |
|
debug_data["requests"].clear() |
|
debug_data["queries"].clear() |
|
return {"message": "Debug data cleared", "status": "success"} |
|
|
|
@app.get("/huggingface", response_class=HTMLResponse) |
|
async def huggingface_repo_viewer(): |
|
"""Hugging Face ใชใใธใใชๆ
ๅ ฑ่กจ็คบใใผใธ""" |
|
if not HF_CLIENT_AVAILABLE: |
|
return """ |
|
<html><body> |
|
<h1>โ Hugging Face Client not available</h1> |
|
<p>huggingface_client.py ใ่ฆใคใใใพใใ</p> |
|
</body></html> |
|
""" |
|
|
|
mock_query("SELECT * FROM hf_repos", 0.03) |
|
|
|
client = HuggingFaceRepoClient() |
|
repo_id = "kenken999/fastapi_django_main_live" |
|
|
|
|
|
repo_info = client.get_repo_info(repo_id, "space") |
|
files = client.list_files(repo_id, "space") |
|
commits = client.get_commit_history(repo_id, "space") |
|
|
|
return f""" |
|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<title>Hugging Face Repository Viewer</title> |
|
<meta charset="utf-8"> |
|
<style> |
|
body {{ |
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; |
|
margin: 0; |
|
padding: 20px; |
|
background: linear-gradient(135deg, #ff7e5f 0%, #feb47b 100%); |
|
min-height: 100vh; |
|
color: #333; |
|
}} |
|
.container {{ |
|
max-width: 1200px; |
|
margin: 0 auto; |
|
background: white; |
|
border-radius: 12px; |
|
box-shadow: 0 10px 30px rgba(0,0,0,0.2); |
|
overflow: hidden; |
|
}} |
|
.header {{ |
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
|
color: white; |
|
padding: 30px; |
|
text-align: center; |
|
}} |
|
.header h1 {{ margin: 0; font-size: 2.5em; font-weight: 300; }} |
|
.nav {{ |
|
background: #f8f9fa; |
|
padding: 15px 30px; |
|
border-bottom: 1px solid #eee; |
|
}} |
|
.nav a {{ |
|
color: #667eea; |
|
text-decoration: none; |
|
margin-right: 20px; |
|
font-weight: 500; |
|
transition: color 0.2s; |
|
}} |
|
.nav a:hover {{ color: #764ba2; }} |
|
.content {{ padding: 30px; }} |
|
.grid {{ display: grid; grid-template-columns: 1fr 1fr; gap: 30px; }} |
|
.card {{ |
|
background: #f8f9fa; |
|
padding: 25px; |
|
border-radius: 8px; |
|
border-left: 4px solid #667eea; |
|
}} |
|
.card h3 {{ margin-top: 0; color: #667eea; }} |
|
.info-grid {{ display: grid; grid-template-columns: auto 1fr; gap: 10px; }} |
|
.info-label {{ font-weight: bold; color: #666; }} |
|
.file-list {{ max-height: 300px; overflow-y: auto; }} |
|
.file-item {{ |
|
background: white; |
|
margin: 5px 0; |
|
padding: 8px 12px; |
|
border-radius: 4px; |
|
border-left: 3px solid #28a745; |
|
font-family: monospace; |
|
font-size: 0.9em; |
|
}} |
|
.commit-item {{ |
|
background: white; |
|
margin: 8px 0; |
|
padding: 12px; |
|
border-radius: 4px; |
|
border-left: 3px solid #ffc107; |
|
}} |
|
.commit-title {{ font-weight: bold; color: #333; }} |
|
.commit-date {{ color: #666; font-size: 0.9em; }} |
|
</style> |
|
</head> |
|
<body> |
|
<div class="container"> |
|
<div class="header"> |
|
<h1>๐ค Hugging Face Repository Viewer</h1> |
|
<p>Repository: {repo_id}</p> |
|
</div> |
|
|
|
<div class="nav"> |
|
<a href="/">๐ Home</a> |
|
<a href="/api/users">๐ฅ Users</a> |
|
<a href="/debug/dashboard">๐ง Debug</a> |
|
<a href="/huggingface">๐ค HF Repository</a> |
|
</div> |
|
|
|
<div class="content"> |
|
<div class="grid"> |
|
<div class="card"> |
|
<h3>๐ Repository Info</h3> |
|
<div class="info-grid"> |
|
<div class="info-label">Author:</div> |
|
<div>{repo_info.get('author', 'N/A')}</div> |
|
<div class="info-label">Created:</div> |
|
<div>{repo_info.get('created_at', 'N/A')[:10] if repo_info.get('created_at') != 'N/A' else 'N/A'}</div> |
|
<div class="info-label">Modified:</div> |
|
<div>{repo_info.get('last_modified', 'N/A')[:10] if repo_info.get('last_modified') != 'N/A' else 'N/A'}</div> |
|
<div class="info-label">Downloads:</div> |
|
<div>{repo_info.get('downloads', 0)}</div> |
|
<div class="info-label">Likes:</div> |
|
<div>{repo_info.get('likes', 0)}</div> |
|
<div class="info-label">Files:</div> |
|
<div>{len(files)}</div> |
|
</div> |
|
</div> |
|
|
|
<div class="card"> |
|
<h3>๐ Files ({len(files)})</h3> |
|
<div class="file-list"> |
|
{''.join([f'<div class="file-item">๐ {file}</div>' for file in files[:20]])} |
|
{f'<div style="text-align: center; margin-top: 10px; color: #666;">... and {len(files) - 20} more files</div>' if len(files) > 20 else ''} |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<div class="card" style="margin-top: 30px;"> |
|
<h3>๐ Recent Commits</h3> |
|
{''.join([f''' |
|
<div class="commit-item"> |
|
<div class="commit-title">{commit['title']}</div> |
|
<div class="commit-date">{commit['date'][:10] if commit['date'] != 'N/A' else 'N/A'} by {commit['author']}</div> |
|
</div> |
|
''' for commit in commits[:5]])} |
|
</div> |
|
</div> |
|
</div> |
|
</body> |
|
</html> |
|
""" |
|
|
|
@app.get("/huggingface/file/{file_path:path}") |
|
async def view_hf_file(file_path: str): |
|
"""Hugging Face ใชใใธใใชใฎ็นๅฎใใกใคใซๅ
ๅฎนใ่กจ็คบ""" |
|
if not HF_CLIENT_AVAILABLE: |
|
return {"error": "Hugging Face Client not available"} |
|
|
|
client = HuggingFaceRepoClient() |
|
repo_id = "kenken999/fastapi_django_main_live" |
|
|
|
content = client.read_file_content(repo_id, file_path, "space") |
|
|
|
return { |
|
"repo_id": repo_id, |
|
"file_path": file_path, |
|
"content": content, |
|
"timestamp": datetime.now().isoformat() |
|
} |
|
|
|
if __name__ == "__main__": |
|
import uvicorn |
|
uvicorn.run(app, host="0.0.0.0", port=8003) |
|
|