Skip to content

Dataset video preview proxy does not support HTTP range requests #960

@yoosful

Description

@yoosful

Describe the bug.

Dataset video previews are routed through the OSMO UI server proxy at /proxy/dataset/file. The proxy currently fetches the upstream file with a plain fetch(result.url) and forwards only a small set of response headers. It does not forward the browser's Range request header, and it does not preserve range-related response headers such as Accept-Ranges or Content-Range.

As a result, MP4 files can appear in the dataset file browser and return 200 with content-type: video/mp4, but the browser <video> element cannot load metadata or play the preview. This is especially visible for MP4 files where the moov atom is near the end of the file, because the browser needs byte-range reads to inspect metadata and seek efficiently.

Expected behavior: dataset video previews should support browser video streaming semantics through the proxy, including Range requests and 206 Partial Content responses when the backing storage supports them.

Actual behavior: a Range: bytes=0-1023 request to /proxy/dataset/file?... returns 200 OK and the full object instead of 206 Partial Content, and the video preview remains a black 0:00 player.

This is related to, but distinct from, #793. Issue #793 covers unsigned fetches against private storage. This issue is about range request handling after the file is reachable through the proxy.

Minimum reproducible example

# 1. Upload or register an MP4 dataset file. The issue is easy to reproduce
#    with MP4 files where the moov atom is at the end of the file.

# 2. Open the dataset detail page with a selected MP4 file:
#    /datasets/<bucket>/<dataset>?file=<video>.mp4

# 3. In browser devtools, inspect the video request to /proxy/dataset/file.
#    Or reproduce with curl:

curl -I \
  -H 'Range: bytes=0-1023' \
  'https://<osmo-ui-host>/proxy/dataset/file?url=<encoded-video-url>'

# Observed response:
# HTTP/2 200
# content-type: video/mp4
# content-length: <full-object-size>

# Expected response when upstream supports ranges:
# HTTP/2 206
# content-type: video/mp4
# accept-ranges: bytes
# content-range: bytes 0-1023/<full-object-size>

Relevant log output

# Browser-side state observed from the OSMO dataset video preview:
video.currentSrc = "https://<osmo-ui-host>/proxy/dataset/file?url=..."
video.networkState = 1
video.readyState = 0
video.duration = null
video.videoWidth = 0
video.videoHeight = 0
video.error = null

# Proxy response without Range handling:
HTTP/2 200
content-type: video/mp4
content-length: 1174609

# Same request with a Range header still returns 200 and the full file:
curl -H 'Range: bytes=0-1023' ...
# => HTTP/2 200, downloaded 1174609 bytes

# The sample MP4 was reachable and was not failing due to storage authorization:
# HEAD / file proxy => 200
# GET  / file proxy => 200

# The same sample file had the moov atom near the end:
ftyp offset: 4
mdat offset: 40
moov offset: 1172420
codec marker: mp4v

Environment

  • Kubernetes version: EKS v1.35.3-eks-bbe087e
  • OSMO version: 6.2.10 pinned in the deployment; UI image nvcr.io/nvidia/osmo/web-ui:6.2
  • OSMO Helm chart version: 1.2.1
  • Scheduler version: KAI Scheduler v0.13.0
  • Cloud provider or hardware configuration: AWS EKS, dataset objects stored in Amazon S3
  • Anything else that is relevant:
    • Reproduced through the production OSMO UI dataset preview path.
    • The storage authorization issue was worked around separately; the video object was reachable through the proxy with HTTP 200.
    • The sample video uses mp4v, so browser codec support may also affect whether that specific sample can play. However, the missing HTTP range forwarding is independent of codec and affects browser video preview behavior for range-dependent MP4 files.

Suggested fix

Forward the incoming Range request header from /proxy/dataset/file to the upstream fetch, and preserve range-related response status and headers. For example:

  • pass Range into fetch(result.url, { headers })
  • preserve upstream 206 Partial Content
  • forward accept-ranges, content-range, content-length, content-type, etag, last-modified, and cache headers
  • keep HEAD behavior consistent with range-capable resources

Code of Conduct

  • I agree to follow NVIDIA OSMO's Code of Conduct
  • I have searched the open bugs and have found no duplicates for this bug report

Metadata

Metadata

Assignees

No one assigned

    Labels

    externalThe author is not in @NVIDIA/osmo-dev

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions