From 455218f7b6f32db06fb1accbb4c85895a3b8a57d Mon Sep 17 00:00:00 2001 From: Kumi Date: Fri, 29 Mar 2024 08:17:56 +0100 Subject: [PATCH] feat: stream proxy content dynamically Refactored the proxy route to stream data dynamically from URLs starting with specific domains, rather than loading it all at once. This change introduces a subfunction within the proxy route handler to manage streaming, which iterates through data chunks and yields them until completion. The new approach aims to enhance performance and resource utilization by avoiding the download of the entire content before sending it to the client. Additionally, error handling has been tightened, specifically for HTTP errors and missing 'content-type' headers, improving the robustness and reliability of the proxy feature. --- main.py | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/main.py b/main.py index e98e1b8..7915c74 100644 --- a/main.py +++ b/main.py @@ -1186,27 +1186,31 @@ def route_explore(): @app.route("/proxy/") def route_proxy(): url = request.args.get("url") - if url != None: + if url is not None: if url.startswith("https://cdn.instructables.com/") or url.startswith( "https://content.instructables.com/" ): + def generate(): + # 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) try: - data = urlopen(unquote(url)) + with urlopen(unquote(url)) as data: + content_type = data.headers["content-type"] except HTTPError as e: abort(e.code) + except KeyError: + raise InternalServerError() - content_disposition = data.headers.get("content-disposition") - - headers = {} - - if content_disposition: - headers["Content-Disposition"] = content_disposition - - return Response( - data.read(), - headers=headers, - content_type=data.headers["content-type"], - ) + return Response(generate(), content_type=content_type) else: raise BadRequest() else: