Spaces:
Sleeping
Sleeping
Serve public vectors through direct signed CDN downloads
Browse files- backend/app.py +21 -3
backend/app.py
CHANGED
|
@@ -20,7 +20,7 @@ import httpx
|
|
| 20 |
from dotenv import load_dotenv
|
| 21 |
from fastapi import Depends, FastAPI, Header, HTTPException, Request
|
| 22 |
from fastapi.middleware.cors import CORSMiddleware
|
| 23 |
-
from fastapi.responses import StreamingResponse
|
| 24 |
from starlette.background import BackgroundTask
|
| 25 |
from pydantic import BaseModel, ConfigDict, Field, model_validator
|
| 26 |
|
|
@@ -153,9 +153,28 @@ def terminology_asset(asset_path: str):
|
|
| 153 |
# HTTPX strips Authorization on cross-origin CDN redirects. Neither the HF
|
| 154 |
# token nor provider keys are forwarded to the browser.
|
| 155 |
client = httpx.Client(timeout=60, follow_redirects=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 156 |
try:
|
| 157 |
response = client.send(client.build_request("GET",
|
| 158 |
-
|
| 159 |
except httpx.HTTPError:
|
| 160 |
client.close()
|
| 161 |
raise HTTPException(502, "The terminology download could not be reached. Please retry.") from None
|
|
@@ -177,7 +196,6 @@ def terminology_asset(asset_path: str):
|
|
| 177 |
close()
|
| 178 |
|
| 179 |
# Public mode permits shared caching; authenticated deployments stay private.
|
| 180 |
-
public = os.getenv("PIPELINE_PUBLIC_ACCESS", "").lower() == "true"
|
| 181 |
cache_control = ("public, max-age=60" if asset_path.endswith("manifest.json") else "public, max-age=31536000, immutable") if public else "private, no-store"
|
| 182 |
return StreamingResponse(chunks(), media_type="application/json" if asset_path.endswith("manifest.json") else "application/octet-stream",
|
| 183 |
headers={"Cache-Control": cache_control, "X-Content-Type-Options": "nosniff"},
|
|
|
|
| 20 |
from dotenv import load_dotenv
|
| 21 |
from fastapi import Depends, FastAPI, Header, HTTPException, Request
|
| 22 |
from fastapi.middleware.cors import CORSMiddleware
|
| 23 |
+
from fastapi.responses import RedirectResponse, StreamingResponse
|
| 24 |
from starlette.background import BackgroundTask
|
| 25 |
from pydantic import BaseModel, ConfigDict, Field, model_validator
|
| 26 |
|
|
|
|
| 153 |
# HTTPX strips Authorization on cross-origin CDN redirects. Neither the HF
|
| 154 |
# token nor provider keys are forwarded to the browser.
|
| 155 |
client = httpx.Client(timeout=60, follow_redirects=True)
|
| 156 |
+
url = f"https://huggingface.co/datasets/{repo}/resolve/{revision}/{asset_path}"
|
| 157 |
+
public = os.getenv("PIPELINE_PUBLIC_ACCESS", "").lower() == "true"
|
| 158 |
+
if public and asset_path.endswith(".f32"):
|
| 159 |
+
# Let the CDN serve large vectors directly. Only the temporary link to
|
| 160 |
+
# this file reaches the browser; the HF access token stays server-side.
|
| 161 |
+
try:
|
| 162 |
+
resolved = client.head(url, headers=headers, follow_redirects=False)
|
| 163 |
+
location = resolved.headers.get("location", "")
|
| 164 |
+
target = httpx.URL(location)
|
| 165 |
+
trusted = target.scheme == "https" and any(
|
| 166 |
+
target.host == domain or target.host.endswith("." + domain)
|
| 167 |
+
for domain in ("hf.co", "huggingface.co"))
|
| 168 |
+
if resolved.is_redirect and trusted:
|
| 169 |
+
client.close()
|
| 170 |
+
# Signed links expire: cache the verified bytes in the browser,
|
| 171 |
+
# never the redirect itself.
|
| 172 |
+
return RedirectResponse(location, status_code=307, headers={"Cache-Control": "no-store"})
|
| 173 |
+
except (httpx.HTTPError, httpx.InvalidURL):
|
| 174 |
+
pass # Retain streaming as a fallback when resolution is unavailable.
|
| 175 |
try:
|
| 176 |
response = client.send(client.build_request("GET",
|
| 177 |
+
url, headers=headers), stream=True)
|
| 178 |
except httpx.HTTPError:
|
| 179 |
client.close()
|
| 180 |
raise HTTPException(502, "The terminology download could not be reached. Please retry.") from None
|
|
|
|
| 196 |
close()
|
| 197 |
|
| 198 |
# Public mode permits shared caching; authenticated deployments stay private.
|
|
|
|
| 199 |
cache_control = ("public, max-age=60" if asset_path.endswith("manifest.json") else "public, max-age=31536000, immutable") if public else "private, no-store"
|
| 200 |
return StreamingResponse(chunks(), media_type="application/json" if asset_path.endswith("manifest.json") else "application/octet-stream",
|
| 201 |
headers={"Cache-Control": cache_control, "X-Content-Type-Options": "nosniff"},
|