feat: add streaming and error handling to proxy route

Introduced streaming support in the proxy route to handle large data transfers more efficiently without loading everything into memory at once. Added error handling for HTTP errors and content-type detection failures to provide more robust and user-friendly responses. Updated import statements to reflect new dependencies.
This commit is contained in:
Kumi 2024-08-03 16:32:44 +02:00
parent 8076dcd937
commit 69e3a5a25d
Signed by: kumi
GPG key ID: ECBCC9082395383F

48
app.py
View file

@ -1,22 +1,50 @@
from flask import Flask, redirect, render_template, request from flask import Flask, render_template, request, Response, abort
from werkzeug.exceptions import InternalServerError
from urllib.request import urlopen from urllib.request import urlopen
from urllib.error import HTTPError
from urllib.parse import unquote
app = Flask(__name__) app = Flask(__name__)
@app.route('/')
@app.route("/")
def home(): def home():
domain = request.url_root domain = request.url_root
return render_template('index.html', domain=domain) return render_template("index.html", domain=domain)
@app.route('/<path:url>')
@app.route("/<path:url>")
def proxy(url): def proxy(url):
jsdelivr_url = f'https://cdn.jsdelivr.net/{url}' jsdelivr_url = f"https://cdn.jsdelivr.net/{url}"
response = urlopen(jsdelivr_url) def generate():
content = response.read() # Subfunction to allow streaming the data instead of
# downloading all of it at once
try:
with urlopen(unquote(url)) as data:
while True:
chunk = data.read(1024 * 1024)
if not chunk:
break
yield chunk
except HTTPError as e:
abort(e.code)
return content try:
with urlopen(unquote(jsdelivr_url)) as data:
content_type = data.headers["content-type"]
except HTTPError as e:
abort(e.code)
except KeyError:
raise InternalServerError()
if __name__ == '__main__': headers = dict()
app.run() filename = url.split("/")[-1]
headers["Content-Disposition"] = f'attachment; filename="{filename}"'
return Response(generate(), content_type=content_type, headers=headers)
if __name__ == "__main__":
app.run()