I have a Phoenix controller that does an Http GET to CouchDb to retrieve a video file, and forward to the Svelte JS client (an html video tag).
The client is an SPA at a single Phoenix route. The following controller is for the API:
def get_video(conn, params) do
vid_id = params["video_id"]
response = CouchDb.get_video(vid_id)
data = response.body
content_type = "video";
hdr = Enum.find(response.headers, fn x -> elem(x, 0) == "content-type" end)
if (hdr) do
content_type = elem(hdr, 1)
end
conn
|> put_layout(false)
|> put_root_layout(false)
|> put_resp_content_type(content_type, nil)
|> send_resp(200, data)
end
The response.headers
from the CouchDb.get_video
call look like this:
[
{"accept-ranges", "bytes"},
{"cache-control", "must-revalidate"},
{"content-length", "21180417"},
{"content-md5", "YyPKVd3NFiQ6wm3sTndwdw=="},
{"content-security-policy", "sandbox"},
{"content-type", "video"},
{"date", "Thu, 12 Sep 2024 00:16:38 GMT"},
{"etag", "\"YyPKVd3NFiQ6wm3sTndwdw==\""},
{"server", "CouchDB/3.3.3 (Erlang OTP/24)"},
{"x-couch-request-id", "21401eae1f"},
{"x-couchdb-body-time", "0"}
]
The problem is that the video contents work randomly; e.g., the first render might show a playable video, and then navigate to a different page, a similar video fails, and back to the first and it fails, too. The network console shows that no GET request is issued when it fails.
Any idea what might be wrong with the Phoenix controller code? Thanks for any help.
A similar NodeJS API works fine with the same client:
apiRouter.get("/videos/:db_name/:video_id", async (req : Request, res : Response) => {
let video_id = req.params["video_id"];
try {
const result = await db.getVideoByMediaId(fetch, video_id);
let {ok, data, content_type, content_length} = result;
if (!ok || !data) {
console.log("err not found")
return res.status(StatusCodes.NOT_FOUND).json({error : `Video not found!`})
}
res.set('Content-Length', content_length.toString());
res.set('Content-Type', `${content_type}`);
return res.send(data)
// sets content_length and mime type
} catch (error) {
return res.status(StatusCodes.INTERNAL_SERVER_ERROR).json({error})
}
})