Class MediaController

java.lang.Object
vaultWeb.controllers.MediaController

@RestController @RequestMapping("/api/media") public class MediaController extends Object
Serves file bytes to native browser media elements.

An <img>, <video> or <audio> tag issues its own requests and cannot carry an Authorization header, so the previous approach was to download a whole file over XHR and hand the element a blob URL. That defeats streaming entirely: playback cannot begin until the last byte arrives, seeking is impossible, and the file is held in memory.

This controller replaces that with a two-step flow:

  1. the client calls POST /api/media/token over its normal authenticated channel and receives a short-lived token scoped to one file;
  2. the client points the media element at GET /api/media/stream/{token}, which streams the bytes and honours Range requests, so the browser can seek.

The streaming endpoint is reachable without the standard authentication filter — a media element could not satisfy it — and is instead authenticated by the token in its path. That token is signed with a dedicated key and pinned to a single path, so it grants nothing beyond the one file it names.

  • Constructor Details

    • MediaController

      public MediaController()
  • Method Details

    • createMediaToken

      @PostMapping("/token") public org.springframework.http.ResponseEntity<Map<String,Object>> createMediaToken(@RequestBody MediaController.MediaTokenRequest request, org.springframework.security.core.Authentication authentication)
      Issues a media token for one file.

      This runs behind normal authentication, so the username is taken from the security context rather than from anything the caller supplied. A user can therefore only ever mint tokens against their own storage.

    • stream

      @GetMapping("/stream/{token}") public org.springframework.http.ResponseEntity<org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody> stream(@PathVariable String token, @RequestHeader(value="Range",required=false) String range, @RequestHeader(value="If-None-Match",required=false) String ifNoneMatch, @RequestHeader(value="If-Modified-Since",required=false) String ifModifiedSince)
      Streams the file a media token was issued for.

      The path is read from the token, never from the query string, so a holder cannot redirect a valid token at a different file. Range and conditional headers are forwarded upstream and the upstream status is preserved, which is what allows 206 Partial Content and 304 Not Modified to reach the browser intact.