cdn

Log | Files | Refs | Activity

commit d6071a60f1450e0fceb98780615d0005b52767df
parent 56f728f9a05c19ec3af63d538fd7b24ed20a75cb
Author: Amit Dutta <mail@amit.is-a.dev>
Date:   Thu,  3 Sep 2026 18:40:58 +0530

Merge pull request #6 from notamitgamer/patch

Refactor raw file handling and update links for subdomain support
Diffstat:
Mapp/main.py | 49++++++++++++++++++++++++++++++-------------------
Mapp/templates/index.html | 21+++++++++------------
Mrender.yaml | 7+++++--
3 files changed, 44 insertions(+), 33 deletions(-)

diff --git a/app/main.py b/app/main.py @@ -4,7 +4,7 @@ import uuid import mimetypes import httpx from fastapi import FastAPI, Request, File, UploadFile, Depends, HTTPException -from fastapi.responses import StreamingResponse, HTMLResponse, PlainTextResponse +from fastapi.responses import StreamingResponse, HTMLResponse, PlainTextResponse, RedirectResponse from fastapi.templating import Jinja2Templates from .storage import is_file, list_directory, upload_temp_file, HF_REPO_ID @@ -15,6 +15,8 @@ app = FastAPI() templates = Jinja2Templates(directory="app/templates") CDN_BASE_URL = os.getenv("CDN_BASE_URL", "https://cdn-zt7p.onrender.com") +RAW_DOMAIN = os.getenv("RAW_DOMAIN", "raw.cdn.amit.is-a.dev") +RAW_BASE_URL = os.getenv("RAW_BASE_URL", f"https://{RAW_DOMAIN}") RAW_PREFIX = "raw/" async def stream_raw(path: str): @@ -28,27 +30,27 @@ async def stream_raw(path: str): raise HTTPException(status_code=404, detail="File not found") filename = path.split("/")[-1].lower() + guessed_type, _ = mimetypes.guess_type(filename) - raw_no_ext_files = {"dockerfile", "makefile", "license", "readme", "cname"} - - if filename in raw_no_ext_files: - content_type = "text/plain" + # Allow media and PDFs to render in-browser securely + if guessed_type and ( + guessed_type.startswith("image/") or + guessed_type.startswith("video/") or + guessed_type.startswith("audio/") or + guessed_type == "application/pdf" + ): + content_type = guessed_type else: - guessed_type, _ = mimetypes.guess_type(filename) - - if guessed_type: - if guessed_type.startswith("text/"): - content_type = "text/plain" - else: - content_type = guessed_type - else: - content_type = "text/plain" + # Force all other files (code, HTML, JSON, unknown) to plain text + # This prevents XSS attacks on the raw domain + content_type = "text/plain; charset=utf-8" headers = { "Access-Control-Allow-Origin": "*", "Cache-Control": "public, max-age=31536000", "Content-Type": content_type, - "Content-Disposition": "inline" + "Content-Disposition": "inline", + "X-Content-Type-Options": "nosniff" } async def stream_generator(): @@ -103,7 +105,7 @@ async def handle_upload(files: list[UploadFile] = File(...), _ = Depends(verify_ results.append({ "filename": file.filename, "cdn_url": f"{CDN_BASE_URL}/{hf_path}", - "raw_url": f"{CDN_BASE_URL}/{RAW_PREFIX}{hf_path}" + "raw_url": f"{RAW_BASE_URL}/{hf_path}" # Updated to use new raw subdomain }) return {"files": results} @@ -116,11 +118,18 @@ async def ping(): async def serve(request: Request, path: str): clean_path = path.strip("/") + # 1. Intercept requests coming to the raw subdomain + if request.url.hostname == RAW_DOMAIN: + if not clean_path: + return HTMLResponse("Specify a file path.", status_code=200) + return await stream_raw(clean_path) + + # 2. Keep old /raw/ prefix working on main domain by redirecting to subdomain 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) + return RedirectResponse(f"{RAW_BASE_URL}/{raw_path}") if clean_path == "upload": return templates.TemplateResponse(request, "index.html", {"page": "upload"}) @@ -130,7 +139,8 @@ async def serve(request: Request, path: str): return templates.TemplateResponse(request, "index.html", { "page": "file", "path": clean_path, - "filename": filename + "filename": filename, + "raw_base_url": RAW_BASE_URL }) items = list_directory(clean_path) @@ -140,5 +150,6 @@ async def serve(request: Request, path: str): return templates.TemplateResponse(request, "index.html", { "page": "listing", "path": clean_path, - "items": items + "items": items, + "raw_base_url": RAW_BASE_URL }) diff --git a/app/templates/index.html b/app/templates/index.html @@ -98,7 +98,6 @@ } .filter-input::placeholder { color: var(--text-dim); } - /* Updated list-item so only the links are clickable */ .list-item { display: flex; align-items: center; @@ -232,7 +231,6 @@ <div id="file-list"> {% if path %} - <!-- Note the change: list-item is now a div, only the '..' is an a tag --> <div class="list-item" data-name=".."> <div class="item-name"> <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 14l-4-4 4-4"/><path d="M5 10h11a4 4 0 1 1 0 8h-1"/></svg> @@ -249,8 +247,8 @@ <a href="/{{ item.path }}">{{ item.name }}/</a> {% else %} <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"/><polyline points="13 2 13 9 20 9"/></svg> - <!-- Routes directly to raw for files --> - <a href="/raw/{{ item.path }}">{{ item.name }}</a> + <!-- Updated to link directly to the new raw subdomain --> + <a href="{{ raw_base_url }}/{{ item.path }}">{{ item.name }}</a> {% endif %} </div> <div class="item-meta"> @@ -281,7 +279,7 @@ const term = e.target.value.toLowerCase(); fileList.forEach(item => { const name = item.getAttribute('data-name').toLowerCase(); - if (name === '..') return; // Always show parent dir link + if (name === '..') return; item.style.display = name.includes(term) ? 'flex' : 'none'; }); }); @@ -296,18 +294,18 @@ <div style="display: flex; gap: 1rem; justify-content: center; flex-wrap: wrap;"> <a href="/api/download/{{ path }}" class="btn">Download</a> - <a href="/raw/{{ path }}" class="btn">Open Raw</a> + <!-- Updated links to utilize raw_base_url --> + <a href="{{ raw_base_url }}/{{ path }}" class="btn">Open Raw</a> <button onclick="copyToClipboard(window.location.origin + '/' + '{{ path }}')" class="btn">Copy Link</button> - <button onclick="copyToClipboard(window.location.origin + '/raw/' + '{{ path }}')" class="btn">Copy Raw Link</button> + <button onclick="copyToClipboard('{{ raw_base_url }}/{{ path }}')" class="btn">Copy Raw Link</button> </div> </div> {% elif page == 'upload' %} <blockquote> - If you do not remember the link, go to the <a href="/uploads">uploads folder</a>to find your file. + If you do not remember the link, go to the <a href="/uploads">uploads folder</a> to find your file. </blockquote> - <!-- Hidden token field containing the hardcoded password --> <input type="hidden" id="token" value="Amitthehack2006"> <div id="dropzone"> @@ -344,7 +342,6 @@ function handleFiles(fileList) { errorBox.style.display = 'none'; - // Grabbing the hidden hardcoded password const token = tokenInput.value; const files = Array.from(fileList); @@ -363,7 +360,6 @@ const xhr = new XMLHttpRequest(); xhr.open('POST', '/api/upload', true); - // Automatically append the Bearer prefix and token for backend authentication xhr.setRequestHeader('Authorization', 'Bearer ' + token); xhr.upload.onprogress = (e) => { @@ -380,7 +376,8 @@ const row = rows[item.filename]; if (!row) return; row.classList.add('done'); - const rawPath = item.raw_url.substring(item.raw_url.indexOf('/raw/')); + // Updated to grab the full raw_url since it now points to the subdomain + const rawPath = item.raw_url; row.innerHTML = ` <div style="overflow:hidden; text-overflow:ellipsis; white-space:nowrap; padding-right:1rem; color: #2ea043;">${item.filename}</div> <div style="white-space:nowrap; display:flex; gap:0.75rem;"> diff --git a/render.yaml b/render.yaml @@ -9,4 +9,8 @@ services: - key: HF_TOKEN sync: false - key: ADMIN_TOKEN - sync: false- \ No newline at end of file + sync: false + - key: RAW_DOMAIN + value: raw.cdn.amit.is-a.dev + - key: RAW_BASE_URL + value: https://raw.cdn.amit.is-a.dev
© 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