immich icon indicating copy to clipboard operation
immich copied to clipboard

refactor(server): file streaming logic

Open mertalev opened this issue 2 years ago • 12 comments

Description

Switching to Express's sendFile results in much cleaner code that sets appropriate headers automatically. The current approach is too manual and error-prone in the absence of a good reason for it.

Fixes #3097

How Has This Been Tested?

Tested on web by scrolling, hovering on videos and live photos and switching between content in the expanded view. All content is shown as expected and no errors are reported in the server.

mertalev avatar Jul 03 '23 18:07 mertalev

The latest updates on your projects. Learn more about Vercel for Git ↗︎

1 Ignored Deployment
Name Status Preview Comments Updated (UTC)
immich ⬜️ Ignored (Inspect) Jul 13, 2023 4:15pm

vercel[bot] avatar Jul 03 '23 18:07 vercel[bot]

The issue I encountered was on Android. The media player required those range properties to be sent. Can you please test on Android and make sure that you can stream the video?

alextran1502 avatar Jul 03 '23 18:07 alextran1502

I don't have an Android phone, but sendFile should handle ranges if they're sent in the request header.

mertalev avatar Jul 03 '23 18:07 mertalev

I can help testing later

alextran1502 avatar Jul 03 '23 18:07 alextran1502

Alright, so Nest-style exceptions don't work at all when passthrough is disabled. They leave everything up to you, so throwing an exception actually crashes the server. On the other hand, enabling it also doesn't work because the response is already sent and there's nothing to passthrough. I'm not sure if there's a good way to fix this. I'm all ears if there is, but otherwise I'll have to shelve this.

mertalev avatar Jul 03 '23 23:07 mertalev

Maybe we can use a custom interceptor for these types of requests. Basically automatically catch the exception and map it to a valid response.

I think you can get the http adapter and call reply potentially..

In the controller we probably want to add a .catch(...) and handle the error either via @Next() or httpAdapter.reply()

jrasm91 avatar Jul 03 '23 23:07 jrasm91

Adding an interceptor or filter seems to just get ignored. But adding .catch to the call gets the job done:

this.assetService.serveFile(authUser, id, query, res).catch((err: Error) => {
  let status = 500;
  let body = err.message;
  if (err instanceof HttpException) {
    status = err.getStatus();
    body = JSON.stringify(err.getResponse());
  }
  return res.status(status).end(body);
});

mertalev avatar Jul 04 '23 01:07 mertalev

This is probably good enough for now. We're basically copying the implementation of the default/base nestjs exception filter here though. Might be worth seeing if it is possible to call the filter.catch method manually though, instead of duplicating the logic.

jrasm91 avatar Jul 04 '23 02:07 jrasm91

Exception handling works now without hacks. I.. I just needed to return...

mertalev avatar Jul 04 '23 04:07 mertalev

Hello, can you help me resolve the merge conflict?

alextran1502 avatar Jul 09 '23 02:07 alextran1502

Rebased

mertalev avatar Jul 09 '23 04:07 mertalev

I can test it tomorrow.

jrasm91 avatar Jul 09 '23 12:07 jrasm91