mirror of
https://github.com/This-weiyuqing/mi-fitness-health.git
synced 2026-10-18 03:03:49 +08:00
feat: REST API with API keys, QR login, and web dashboard (v0.2.0)
- REST API (FastAPI): all data endpoints, sync (foreground/background), coverage stats, interactive docs at /docs - API key system: exchange Xiaomi credentials for mif_sk_* keys (multi-account contexts, last-used tracking, prefix revocation); static key via MI_FITNESS_API_KEY, admin endpoints via MI_FITNESS_ADMIN_KEY - QR code login: reverse-engineered Xiaomi universal QR flow (sid=xiaomiio), auto-issues API key after scan confirmation - Built-in web dashboard (Flask): visual console for all endpoints, key management, QR login; reverse proxy with server-side key relay - Standalone testpage/ console (python app.py, no install needed) - Fix: pin mcp<2 (SDK 2.x removed Server.list_tools, broke startup) - CI: install [all,dev] extras; docs: full technical documentation and QR login implementation guide
This commit is contained in:
1 parent
7fcd06980f
commit
2dd32f1ee6
21 files changed
+8723
-165
No files matched your search
@@ -0,0 +1,66 @@
|
||||
"""Tests for Flask Web UI and reverse proxy."""
|
||||
|
||||
import httpx
|
||||
import respx
|
||||
from httpx import Response
|
||||
|
||||
from mi_fitness_mcp.web import create_app
|
||||
|
||||
|
||||
def test_index_route():
|
||||
app = create_app()
|
||||
app.config["TESTING"] = True
|
||||
client = app.test_client()
|
||||
|
||||
response = client.get("/")
|
||||
assert response.status_code == 200
|
||||
assert "Mi Fitness" in response.text or "Mi Fitness Web UI" in response.text
|
||||
|
||||
|
||||
def test_proxy_status_route():
|
||||
app = create_app(backend_url="http://127.0.0.1:8321")
|
||||
app.config["TESTING"] = True
|
||||
client = app.test_client()
|
||||
|
||||
response = client.get("/api/proxy_status")
|
||||
assert response.status_code == 200
|
||||
data = response.get_json()
|
||||
assert data["proxy"] == "running"
|
||||
assert data["proxy_type"] == "Flask (Python)"
|
||||
assert data["backend_url"] == "http://127.0.0.1:8321"
|
||||
|
||||
|
||||
@respx.mock
|
||||
def test_proxy_forwarding():
|
||||
backend_url = "http://test-backend:8321"
|
||||
respx.get(f"{backend_url}/api/summary").mock(
|
||||
return_value=Response(200, json=[{"date": "2026-08-30", "steps": 8500}])
|
||||
)
|
||||
|
||||
app = create_app(backend_url=backend_url, api_key="mif_sk_secret_test")
|
||||
app.config["TESTING"] = True
|
||||
client = app.test_client()
|
||||
|
||||
resp = client.get("/proxy/api/summary?start_date=2026-08-30&end_date=2026-08-31")
|
||||
assert resp.status_code == 200
|
||||
assert "X-Upstream-Time-Ms" in resp.headers
|
||||
data = resp.get_json()
|
||||
assert len(data) == 1
|
||||
assert data[0]["steps"] == 8500
|
||||
|
||||
|
||||
@respx.mock
|
||||
def test_proxy_upstream_error_502():
|
||||
backend_url = "http://non-existent-backend:8321"
|
||||
respx.get(f"{backend_url}/api/status").mock(
|
||||
side_effect=httpx.ConnectError("Connection refused")
|
||||
)
|
||||
app = create_app(backend_url=backend_url)
|
||||
app.config["TESTING"] = True
|
||||
client = app.test_client()
|
||||
|
||||
resp = client.get("/proxy/api/status")
|
||||
assert resp.status_code == 502
|
||||
data = resp.get_json()
|
||||
assert "error" in data
|
||||
assert "Flask 代理无法访问后端" in data["error"]
|
||||
Reference in new issue
Block a user