mirror of
https://github.com/rommapp/romm.git
synced 2026-06-29 07:16:28 +00:00
Merge pull request #1084 from rommapp/feat/implement-x-accel-redirect
feat: Use X-Accel-Redirect to improve file download speed
This commit is contained in:
@@ -23,13 +23,13 @@ from endpoints.responses.rom import (
|
||||
from exceptions.endpoint_exceptions import RomNotFoundInDatabaseException
|
||||
from exceptions.fs_exceptions import RomAlreadyExistsException
|
||||
from fastapi import File, HTTPException, Query, Request, UploadFile, status
|
||||
from fastapi.responses import FileResponse
|
||||
from fastapi.responses import Response
|
||||
from handler.database import db_platform_handler, db_rom_handler
|
||||
from handler.filesystem import fs_resource_handler, fs_rom_handler
|
||||
from handler.filesystem.base_handler import CoverSize
|
||||
from handler.metadata import meta_igdb_handler, meta_moby_handler
|
||||
from logger.logger import log
|
||||
from stream_zip import NO_COMPRESSION_32, ZIP_AUTO, AsyncMemberFile, async_stream_zip
|
||||
from stream_zip import NO_COMPRESSION_64, ZIP_AUTO, AsyncMemberFile, async_stream_zip
|
||||
from utils.router import APIRouter
|
||||
|
||||
router = APIRouter()
|
||||
@@ -154,7 +154,12 @@ def get_rom(request: Request, id: int) -> DetailedRomSchema:
|
||||
"/roms/{id}/content/{file_name}",
|
||||
[] if DISABLE_DOWNLOAD_ENDPOINT_AUTH else ["roms.read"],
|
||||
)
|
||||
def head_rom_content(request: Request, id: int, file_name: str):
|
||||
async def head_rom_content(
|
||||
request: Request,
|
||||
id: int,
|
||||
file_name: str,
|
||||
files: Annotated[list[str] | None, Query()] = None,
|
||||
):
|
||||
"""Head rom content endpoint
|
||||
|
||||
Args:
|
||||
@@ -171,15 +176,30 @@ def head_rom_content(request: Request, id: int, file_name: str):
|
||||
if not rom:
|
||||
raise RomNotFoundInDatabaseException(id)
|
||||
|
||||
rom_path = f"{LIBRARY_BASE_PATH}/{rom.full_path}"
|
||||
files_to_check = files or [r["filename"] for r in rom.files]
|
||||
|
||||
return FileResponse(
|
||||
path=rom_path if not rom.multi else f'{rom_path}/{rom.files[0]["filename"]}',
|
||||
filename=file_name,
|
||||
if not rom.multi:
|
||||
return Response(
|
||||
media_type="application/octet-stream",
|
||||
headers={
|
||||
"Content-Disposition": f'attachment; filename="{quote(rom.file_name)}"',
|
||||
"X-Accel-Redirect": f"/library/{rom.full_path}",
|
||||
},
|
||||
)
|
||||
|
||||
if len(files_to_check) == 1:
|
||||
return Response(
|
||||
media_type="application/octet-stream",
|
||||
headers={
|
||||
"Content-Disposition": f'attachment; filename="{quote(files_to_check[0])}"',
|
||||
"X-Accel-Redirect": f"/library/{rom.full_path}/{files_to_check[0]}",
|
||||
},
|
||||
)
|
||||
|
||||
return Response(
|
||||
media_type="application/zip",
|
||||
headers={
|
||||
"Content-Disposition": f'attachment; filename="{quote(rom.name)}.zip"',
|
||||
"Content-Type": "application/zip",
|
||||
"Content-Length": str(rom.file_size_bytes),
|
||||
"Content-Disposition": f'attachment; filename="{quote(file_name)}.zip"',
|
||||
},
|
||||
)
|
||||
|
||||
@@ -214,11 +234,21 @@ async def get_rom_content(
|
||||
files_to_download = files or [r["filename"] for r in rom.files]
|
||||
|
||||
if not rom.multi:
|
||||
return FileResponse(path=rom_path, filename=rom.file_name)
|
||||
return Response(
|
||||
media_type="application/octet-stream",
|
||||
headers={
|
||||
"Content-Disposition": f'attachment; filename="{quote(rom.file_name)}"',
|
||||
"X-Accel-Redirect": f"/library/{rom.full_path}",
|
||||
},
|
||||
)
|
||||
|
||||
if len(files_to_download) == 1:
|
||||
return FileResponse(
|
||||
path=f"{rom_path}/{files_to_download[0]}", filename=files_to_download[0]
|
||||
return Response(
|
||||
media_type="application/octet-stream",
|
||||
headers={
|
||||
"Content-Disposition": f'attachment; filename="{quote(files_to_download[0])}"',
|
||||
"X-Accel-Redirect": f"/library/{rom.full_path}/{files_to_download[0]}",
|
||||
},
|
||||
)
|
||||
|
||||
# Builds a generator of tuples for each member file
|
||||
@@ -252,7 +282,7 @@ async def get_rom_content(
|
||||
f"{file_name}.m3u",
|
||||
now,
|
||||
S_IFREG | 0o600,
|
||||
NO_COMPRESSION_32,
|
||||
NO_COMPRESSION_64,
|
||||
m3u_file(),
|
||||
)
|
||||
|
||||
@@ -263,7 +293,7 @@ async def get_rom_content(
|
||||
zipped_chunks,
|
||||
media_type="application/zip",
|
||||
headers={
|
||||
"Content-Disposition": f'attachment; filename="{quote(file_name)}.zip"'
|
||||
"Content-Disposition": f'attachment; filename="{quote(file_name)}.zip"',
|
||||
},
|
||||
emit_body={"id": rom.id},
|
||||
)
|
||||
|
||||
@@ -32,7 +32,6 @@ from endpoints import (
|
||||
)
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.middleware.gzip import GZipMiddleware
|
||||
from handler.auth.base_handler import ALGORITHM
|
||||
from handler.auth.hybrid_auth import HybridAuthBackend
|
||||
from handler.auth.middleware import CustomCSRFMiddleware, SessionMiddleware
|
||||
@@ -68,9 +67,6 @@ if not IS_PYTEST_RUN and not DISABLE_CSRF_PROTECTION:
|
||||
exempt_urls=[re.compile(r"^/token.*"), re.compile(r"^/ws")],
|
||||
)
|
||||
|
||||
# Enable GZip compression for responses
|
||||
app.add_middleware(GZipMiddleware, minimum_size=1024)
|
||||
|
||||
# Handles both basic and oauth authentication
|
||||
app.add_middleware(
|
||||
AuthenticationMiddleware,
|
||||
|
||||
@@ -14,9 +14,14 @@ http {
|
||||
scgi_temp_path /tmp/scgi;
|
||||
|
||||
sendfile on;
|
||||
client_body_buffer_size 128k;
|
||||
client_max_body_size 0;
|
||||
client_header_buffer_size 1k;
|
||||
large_client_header_buffers 4 16k;
|
||||
send_timeout 60s;
|
||||
keepalive_timeout 65s;
|
||||
tcp_nopush on;
|
||||
# types_hash_max_size 2048;
|
||||
tcp_nodelay on;
|
||||
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
@@ -41,6 +46,13 @@ http {
|
||||
error_log /dev/stderr;
|
||||
|
||||
gzip on;
|
||||
gzip_proxied any;
|
||||
gzip_vary on;
|
||||
gzip_comp_level 6;
|
||||
gzip_buffers 16 8k;
|
||||
gzip_min_length 1024;
|
||||
gzip_http_version 1.1;
|
||||
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
|
||||
|
||||
# include /etc/nginx/conf.d/*.conf;
|
||||
# include /etc/nginx/sites-enabled/*;
|
||||
@@ -87,5 +99,11 @@ http {
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
}
|
||||
|
||||
# Internally redirect download requests
|
||||
location /library {
|
||||
internal;
|
||||
alias /romm/library;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user