从另一个 URL 发送音频文件作为响应的 HTTP 请求处理程序

HTTP request handler that sends an audio file from another URL as a response

我想允许用户请求音频文件。这些文件托管在单独的文件服务器上。我不希望用户获取这些文件,除非他们先通过我的服务器。

我如何制作一个基本上充当用户和文件服务器之间的中间人的功能。我目前有这样的东西:

async (req, res) => {
    const mediaLink = `https://www.example.com/audio.mp3`;
    const mediaResponse = await fetch(mediaLink, {
        headers: {
            Range: req.headers.range,
        }
    });
    const blob = await mediaResponse.blob(); // I'm guessing here. Idk.
    res.send(blob);
}

我在 <audio> 标签中对此进行了测试,但从未加载音频:

<audio controls src="http://localhost:5001/file-server-middleware" />

处理此类请求的正确方法是 pipe the response body back to the client making sure to copy across any relevant headers that may be in the response from the file server. Read up on the HTTP Functions documentation 查看您应该注意哪些用例(例如 CORS)。

async (req, res) => {
    const mediaLink = `https://www.example.com/audio.mp3`;

    // You may wish to pass through Cache-related headers, such as
    // If-None-Match, If-Match, If-Modified-Since, If-Range, If-Unmodified-Since

    const mediaResponse = await fetch(mediaLink, {
        headers: {
            Range: req.headers.range,
        }
    });

    // note: this currently passes the body & status from the file server
    // as-is, you may want to send your own body on failed status codes to
    // hide the existence of the external server (i.e. custom 404 pages, no
    // Nginx error pages, etc)

    // mediaResponse.status may be:
    //  - 200 (sending full file)
    //  - 206 (sending portion of file)
    //  - 304 (not modified, if using cache headers)
    //  - 404 (file not found)
    //  - 412 (precondition failed, if using cache headers)
    //  - 416 (range not satisfiable)
    //  - 5xx (internal server errors from the file server)

    res
      .status(mediaResponse.status)
      .set({
        /* ... other headers (e.g. CORS, Cache-Control) ... */
        'Content-Type': mediaResponse.headers.get('content-type'),
        'Content-Length': mediaResponse.headers.get('content-length'),
        'Content-Encoding': mediaResponse.headers.get('content-encoding'),
        'Etag': mediaResponse.headers.get('Etag'), // for caching
        'Last-Modified': mediaResponse.headers.get('last-modified') // for caching
      });
    
    mediaResponse.body.pipe(res);
}

您可能还想查看各种 express-compatible proxy modules that can handle the bodies and headers for you. Note that some of these may not function properly if used in a Firebase Cloud Function as the request bodies are automatically consumed for you