Spaces:
Running on Zero
Running on Zero
PropNode Deploy commited on
Commit ·
cd2ba4f
1
Parent(s): 32b00f5
Deploy PropNode ZeroGPU gateway (2026-11-01 13:04:21 UTC)
Browse files
app.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
"""Public Hugging Face ZeroGPU Gateway for PropNode Admin.
|
| 2 |
|
| 3 |
- Keeps the real codebase private in GitHub (`Gini-Eddie/propnode-admin`).
|
| 4 |
-
- Displays a public decoy Gradio interface to regular Hugging Face visitors.
|
| 5 |
- Unlocks the real PropNode Admin portal only via `/gate/<GATEWAY_KEY>` or authorized origins.
|
| 6 |
"""
|
| 7 |
import hashlib
|
|
@@ -102,7 +102,7 @@ def _load_private_admin_app():
|
|
| 102 |
check=False,
|
| 103 |
)
|
| 104 |
if result.returncode != 0:
|
| 105 |
-
logger.error("Failed to clone private repository (code %s)
|
| 106 |
return None
|
| 107 |
|
| 108 |
sys.path.insert(0, str(RUNTIME_DIR))
|
|
@@ -118,7 +118,7 @@ def _load_private_admin_app():
|
|
| 118 |
admin_app = _load_private_admin_app()
|
| 119 |
|
| 120 |
# ---------------------------------------------------------------------------
|
| 121 |
-
# 3. Public Decoy + Secret Gate FastAPI App
|
| 122 |
# ---------------------------------------------------------------------------
|
| 123 |
public_app = FastAPI(docs_url=None, redoc_url=None, openapi_url=None)
|
| 124 |
|
|
@@ -128,7 +128,7 @@ async def unlock_gateway(key: str):
|
|
| 128 |
"""Secret entry URL that sets an HttpOnly pass cookie and opens the admin login."""
|
| 129 |
expected = _expected_key()
|
| 130 |
if not expected or not hmac.compare_digest(key, expected):
|
| 131 |
-
return RedirectResponse(url="/
|
| 132 |
|
| 133 |
response = RedirectResponse(url="/login.html", status_code=302)
|
| 134 |
response.set_cookie(
|
|
@@ -143,17 +143,27 @@ async def unlock_gateway(key: str):
|
|
| 143 |
return response
|
| 144 |
|
| 145 |
|
| 146 |
-
|
| 147 |
-
async def root_redirect():
|
| 148 |
-
return RedirectResponse(url="/decoy", status_code=302)
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
public_app = gr.mount_gradio_app(public_app, demo, path="/decoy")
|
| 152 |
|
| 153 |
|
| 154 |
# ---------------------------------------------------------------------------
|
| 155 |
# 4. Zero-Leakage ASGI Gateway Dispatcher
|
| 156 |
# ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 157 |
class GatewayRouter:
|
| 158 |
def __init__(self, decoy_asgi, private_asgi):
|
| 159 |
self.decoy_asgi = decoy_asgi
|
|
@@ -164,7 +174,7 @@ class GatewayRouter:
|
|
| 164 |
return False
|
| 165 |
|
| 166 |
path: str = scope.get("path", "")
|
| 167 |
-
if path.startswith("/
|
| 168 |
return False
|
| 169 |
|
| 170 |
headers = {
|
|
@@ -212,13 +222,6 @@ class GatewayRouter:
|
|
| 212 |
await self.private_asgi(scope, receive, send)
|
| 213 |
return
|
| 214 |
|
| 215 |
-
if scope.get("type") == "http":
|
| 216 |
-
path = scope.get("path", "")
|
| 217 |
-
if not (path == "/" or path.startswith("/decoy") or path.startswith("/gate/")):
|
| 218 |
-
response = RedirectResponse(url="/decoy", status_code=302)
|
| 219 |
-
await response(scope, receive, send)
|
| 220 |
-
return
|
| 221 |
-
|
| 222 |
await self.decoy_asgi(scope, receive, send)
|
| 223 |
|
| 224 |
|
|
@@ -226,4 +229,6 @@ app = GatewayRouter(public_app, admin_app)
|
|
| 226 |
|
| 227 |
if __name__ == "__main__":
|
| 228 |
port = int(os.environ.get("PORT", 7860))
|
| 229 |
-
uvicorn.run(app, host="0.0.0.0", port=port)
|
|
|
|
|
|
|
|
|
| 1 |
"""Public Hugging Face ZeroGPU Gateway for PropNode Admin.
|
| 2 |
|
| 3 |
- Keeps the real codebase private in GitHub (`Gini-Eddie/propnode-admin`).
|
| 4 |
+
- Displays a public decoy Gradio interface at `/` to regular Hugging Face visitors.
|
| 5 |
- Unlocks the real PropNode Admin portal only via `/gate/<GATEWAY_KEY>` or authorized origins.
|
| 6 |
"""
|
| 7 |
import hashlib
|
|
|
|
| 102 |
check=False,
|
| 103 |
)
|
| 104 |
if result.returncode != 0:
|
| 105 |
+
logger.error("Failed to clone private repository (code %s): %s", result.returncode, result.stderr)
|
| 106 |
return None
|
| 107 |
|
| 108 |
sys.path.insert(0, str(RUNTIME_DIR))
|
|
|
|
| 118 |
admin_app = _load_private_admin_app()
|
| 119 |
|
| 120 |
# ---------------------------------------------------------------------------
|
| 121 |
+
# 3. Public Decoy + Secret Gate FastAPI App (Mounted at `/` for Gradio 5)
|
| 122 |
# ---------------------------------------------------------------------------
|
| 123 |
public_app = FastAPI(docs_url=None, redoc_url=None, openapi_url=None)
|
| 124 |
|
|
|
|
| 128 |
"""Secret entry URL that sets an HttpOnly pass cookie and opens the admin login."""
|
| 129 |
expected = _expected_key()
|
| 130 |
if not expected or not hmac.compare_digest(key, expected):
|
| 131 |
+
return RedirectResponse(url="/", status_code=302)
|
| 132 |
|
| 133 |
response = RedirectResponse(url="/login.html", status_code=302)
|
| 134 |
response.set_cookie(
|
|
|
|
| 143 |
return response
|
| 144 |
|
| 145 |
|
| 146 |
+
public_app = gr.mount_gradio_app(public_app, demo, path="/")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 147 |
|
| 148 |
|
| 149 |
# ---------------------------------------------------------------------------
|
| 150 |
# 4. Zero-Leakage ASGI Gateway Dispatcher
|
| 151 |
# ---------------------------------------------------------------------------
|
| 152 |
+
GRADIO_PREFIXES = (
|
| 153 |
+
"/gradio_api",
|
| 154 |
+
"/queue/",
|
| 155 |
+
"/ config",
|
| 156 |
+
"/config",
|
| 157 |
+
"/info",
|
| 158 |
+
"/theme.css",
|
| 159 |
+
"/ custom.css",
|
| 160 |
+
"/assets/",
|
| 161 |
+
"/file=",
|
| 162 |
+
"/heartbeat/",
|
| 163 |
+
"/manifest.json",
|
| 164 |
+
)
|
| 165 |
+
|
| 166 |
+
|
| 167 |
class GatewayRouter:
|
| 168 |
def __init__(self, decoy_asgi, private_asgi):
|
| 169 |
self.decoy_asgi = decoy_asgi
|
|
|
|
| 174 |
return False
|
| 175 |
|
| 176 |
path: str = scope.get("path", "")
|
| 177 |
+
if path.startswith("/gate/") or path.startswith(GRADIO_PREFIXES):
|
| 178 |
return False
|
| 179 |
|
| 180 |
headers = {
|
|
|
|
| 222 |
await self.private_asgi(scope, receive, send)
|
| 223 |
return
|
| 224 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 225 |
await self.decoy_asgi(scope, receive, send)
|
| 226 |
|
| 227 |
|
|
|
|
| 229 |
|
| 230 |
if __name__ == "__main__":
|
| 231 |
port = int(os.environ.get("PORT", 7860))
|
| 232 |
+
uvicorn.run(app, host="0.0.0.0", port=port, reload=False)
|
| 233 |
+
|
| 234 |
+
# Deployed: 2026-11-01 13:04:21 UTC
|