Follow same-host redirects in media proxy

Fixes #1415
This commit is contained in:
Zed 2026-06-21 03:10:55 +02:00
commit 1e03595784

View file

@ -34,30 +34,39 @@ template respond*(req: asynchttpserver.Request; headers) =
proc proxyMedia*(req: jester.Request; url: string): Future[HttpCode] {.async.} = proc proxyMedia*(req: jester.Request; url: string): Future[HttpCode] {.async.} =
result = Http200 result = Http200
let request = req.getNativeReq() let request = req.getNativeReq()
var fetchUrl = url
for attempt in 0 .. 2: for attempt in 0 .. 2:
let client = newAsyncHttpClient(maxRedirects = 0) let client = newAsyncHttpClient(maxRedirects = 0)
var shouldRetry = false var shouldRetry = false
try: try:
let resFut = client.get(url) let resFut = client.get(fetchUrl)
let completed = await withTimeout(resFut, 5000) let completed = await withTimeout(resFut, 5000)
if not completed: if not completed:
if attempt < 2: if attempt < 2:
echo "[media] Retry $1/2, timeout after 5s, url: $2" % [$(attempt + 1), url] echo "[media] Retry $1/2, timeout after 5s, url: $2" % [$(attempt + 1), fetchUrl]
shouldRetry = true shouldRetry = true
else: else:
echo "[media] Proxying timeout after 5s, url: $1" % [url] echo "[media] Proxying timeout after 5s, url: $1" % [fetchUrl]
return Http504 return Http504
else: else:
let res = resFut.read() let res = resFut.read()
if res.status != "200 OK": if res.status != "200 OK":
if res.status == "404 Not Found": if res.status == "404 Not Found":
return Http404 return Http404
if res.status.startsWith("30") and res.headers.hasKey("location"):
let location = res.headers["location", 0]
if isTwitterUrl(location):
fetchUrl = location
shouldRetry = true
continue
else:
return Http403
if attempt < 2: if attempt < 2:
echo "[media] Retry $1/2, status: $2, url: $3" % [$(attempt + 1), res.status, url] echo "[media] Retry $1/2, status: $2, url: $3" % [$(attempt + 1), res.status, fetchUrl]
shouldRetry = true shouldRetry = true
else: else:
echo "[media] Proxying failed, status: $1, url: $2" % [res.status, url] echo "[media] Proxying failed, status: $1, url: $2" % [res.status, fetchUrl]
return Http404 return Http404
else: else:
let hashed = $hash(url) let hashed = $hash(url)
@ -88,10 +97,10 @@ proc proxyMedia*(req: jester.Request; url: string): Future[HttpCode] {.async.} =
return Http200 return Http200
except CatchableError: except CatchableError:
if attempt < 2: if attempt < 2:
echo "[media] Retry $1/2, error: $2, url: $3" % [$(attempt + 1), getCurrentExceptionMsg(), url] echo "[media] Retry $1/2, error: $2, url: $3" % [$(attempt + 1), getCurrentExceptionMsg(), fetchUrl]
shouldRetry = true shouldRetry = true
else: else:
echo "[media] Proxying exception, error: $1, url: $2" % [getCurrentExceptionMsg(), url] echo "[media] Proxying exception, error: $1, url: $2" % [getCurrentExceptionMsg(), fetchUrl]
result = Http404 result = Http404
finally: finally:
client.close() client.close()