cdn

Log | Files | Refs | Activity

commit b40e43cc9747aa11c40d5098b0730a32d60e022b
parent 0cd0c89babd48dfb9295c9f4d0c73c72f7b71abb
Author: Amit Dutta <mail@amit.is-a.dev>
Date:   Thu,  3 Sep 2026 15:38:26 +0530

Merge pull request #3 from notamitgamer/fix/raw-path-redirects-cookies

Path-based raw serving, fix HF redirect 404s, add optional YT cookies support
Diffstat:
Mapp/main.py | 41++++++++++++++++++++++-------------------
Mapp/templates/index.html | 4++--
Mapp/ytmusic.py | 12++++++++++++
3 files changed, 36 insertions(+), 21 deletions(-)

diff --git a/app/main.py b/app/main.py @@ -20,17 +20,20 @@ app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler) templates = Jinja2Templates(directory="app/templates") -# Phase 2: Dual-domain routing middleware -@app.middleware("http") -async def route_by_host(request: Request, call_next): - host = request.headers.get("host", "") - request.state.is_raw = host.startswith("raw.") - return await call_next(request) +# Base URL for building shareable links. Set CDN_BASE_URL on Render once +# the custom domain (cdn.amit.is-a.dev) is attached; falls back to the +# temporary onrender.com URL so this still works before that's set up. +CDN_BASE_URL = os.getenv("CDN_BASE_URL", "https://cdn-zt7p.onrender.com") + +# Phase 7: Path-based raw routing (Render free tier only allows one +# custom domain, so raw serving lives at /raw/<path> instead of a +# raw. subdomain) +RAW_PREFIX = "raw/" async def stream_raw(path: str): - """Streams file from Hugging Face for the raw. domain.""" + """Streams file bytes for /raw/<path> requests.""" hf_url = f"https://huggingface.co/datasets/{HF_REPO_ID}/resolve/main/{path}" - client = httpx.AsyncClient() + client = httpx.AsyncClient(follow_redirects=True) req = client.build_request("GET", hf_url) r = await client.send(req, stream=True) @@ -57,7 +60,7 @@ async def stream_raw(path: str): async def download_file(path: str): """Forces a file download from the cdn. domain.""" hf_url = f"https://huggingface.co/datasets/{HF_REPO_ID}/resolve/main/{path}" - client = httpx.AsyncClient() + client = httpx.AsyncClient(follow_redirects=True) req = client.build_request("GET", hf_url) r = await client.send(req, stream=True) @@ -94,8 +97,8 @@ async def handle_upload(file: UploadFile = File(...), _ = Depends(verify_token)) os.remove(temp_path) return { - "cdn_url": f"https://cdn.amit.is-a.dev/{hf_path}", - "raw_url": f"https://raw.cdn.amit.is-a.dev/{hf_path}" + "cdn_url": f"{CDN_BASE_URL}/{hf_path}", + "raw_url": f"{CDN_BASE_URL}/{RAW_PREFIX}{hf_path}" } # Phase 5: Public, rate-limited YouTube Music downloader @@ -109,15 +112,15 @@ async def ytmusic_endpoint(request: Request, url: str = Form(...), background_ta @app.get("/{path:path}") async def serve(request: Request, path: str): - # Route raw traffic - if request.state.is_raw: - if not path: - return HTMLResponse("raw. domain root. Please specify a file path.", status_code=200) - return await stream_raw(path) - - # Route CDN traffic clean_path = path.strip("/") - + + # Path-based raw serving: /raw/<path> + if clean_path == RAW_PREFIX.rstrip("/") or clean_path.startswith(RAW_PREFIX): + raw_path = clean_path[len(RAW_PREFIX):] + if not raw_path: + return HTMLResponse("/raw/ — specify a file path after this prefix.", status_code=200) + return await stream_raw(raw_path) + if clean_path == "upload": return templates.TemplateResponse(request, "index.html", {"page": "upload"}) if clean_path == "ytmusic": diff --git a/app/templates/index.html b/app/templates/index.html @@ -97,8 +97,8 @@ <p style="color: #64748b; margin-bottom: 2rem;">{{ path }}</p> <div style="display: flex; gap: 1rem; justify-content: center;"> <a href="/api/download/{{ path }}" class="btn">Download File</a> - <button onclick="copyToClipboard('https://cdn.amit.is-a.dev/{{ path }}')" class="btn btn-secondary">Copy Link</button> - <button onclick="copyToClipboard('https://raw.cdn.amit.is-a.dev/{{ path }}')" class="btn btn-secondary">Copy Raw Link</button> + <button onclick="copyToClipboard(window.location.origin + '/{{ path }}')" class="btn btn-secondary">Copy Link</button> + <button onclick="copyToClipboard(window.location.origin + '/raw/{{ path }}')" class="btn btn-secondary">Copy Raw Link</button> </div> </div> diff --git a/app/ytmusic.py b/app/ytmusic.py @@ -28,6 +28,18 @@ def process_and_stream_ytmusic(url: str, background_tasks: BackgroundTasks): 'noplaylist': True, 'match_filter': filter_duration_and_live, } + + # Optional: YT_COOKIES env var holding the full contents of a + # Netscape-format cookies.txt exported from a logged-in browser + # session. YouTube sometimes blocks Render's server IPs with a + # "Sign in to confirm you're not a bot" error; passing cookies + # from a real browser session works around that. + cookies_content = os.getenv("YT_COOKIES") + if cookies_content: + cookies_path = os.path.join(temp_dir, "cookies.txt") + with open(cookies_path, "w") as f: + f.write(cookies_content) + ydl_opts['cookiefile'] = cookies_path with yt_dlp.YoutubeDL(ydl_opts) as ydl: info = ydl.extract_info(url, download=True)
© notamitgamer • Site Built: 2026-09-05 01:53:16 UTC • git-mirror commit: c170d72 [view raw info]
Originally created with stagit • modified by notamitgamer
Forked from github.com/notamitgamer/git-mirror