imazen / imageflow-dotnet

The official .NET API for Imageflow, the Rust image processing and optimization engine for web servers
GNU Affero General Public License v3.0
143 stars 25 forks source link

Issue w/ CDN Reverse Proxy #54

Closed tachyon1337 closed 7 months ago

tachyon1337 commented 1 year ago

Any reason why the following code snippet will work to successfully resize/process images(retrieved from Azure Blob Storage) if client requests are directed to the app service but fails if requests are forwarded from a CDN(in this, Azure FD)? This snippet is from custom middleware that replaces UseStaticFiles() running in an Azure app service that also serves as a CDN Origin for an Azure FD endpoint.

                    using var buildJob = new ImageJob();
                    var jobResult = await buildJob.BuildCommandString(blobResult.Content.ReadAllBytes(), new BytesDestination(), query).Finish().InProcessAsync();
                    var bytes = jobResult.First.TryGetBytes();
                    if (bytes != null && bytes.HasValue)
                    {
                        response.ContentType = blobResult.Details.ContentType;
                        response.ContentLength = bytes.Value.Count;
                        await response.Body.WriteAsync(bytes.Value.Array, bytes.Value.Offset, bytes.Value.Count);
                        return;
                    }
https://<id-azurewebsites.net>/<container>/<image>?width=600

works perfectly w 200 or 304 response.

https://<id-azurefd.net>/<container>/<image>?width=600

will only render about 75% of the image w/ a 200 while the browser spins for about 3 minutes before finally failing. Application Insights is not offering any insight. And the CDN reverse proxy works fine for rendering unprocessed blobs retrieved from Azure Blob Storage.

If anyone has run into this before, I thought I might give it a shot to ask here. Thanx.

lilith commented 1 year ago

Try not setting the contentlength header.

On Sun, Feb 5, 2023, 3:59 AM S. Francis @.***> wrote:

Any reason why the following code snippet will work to successfully resize/process images(retrieved from Azure Blob Storage) if client requests are directed to the app service but fails if requests are forwarded from a CDN(in this, Azure FD)? This snippet is from custom middleware that replaces UseStaticFiles() running in an Azure app service that also serves as a CDN Origin for an Azure FD endpoint.

                using var buildJob = new ImageJob();
                var jobResult = await buildJob.BuildCommandString(blobResult.Content.ReadAllBytes(), new BytesDestination(), query).Finish().InProcessAsync();
                var bytes = jobResult.First.TryGetBytes();
                if (bytes != null && bytes.HasValue)
                {
                    response.ContentType = blobResult.Details.ContentType;
                    response.ContentLength = bytes.Value.Count;
                    await response.Body.WriteAsync(bytes.Value.Array, bytes.Value.Offset, bytes.Value.Count);
                    return;
                }

https:////?width=600

works perfectly w 200 or 304 response.

https:////?width=600

will only render about 75% of the image w/ a 200 while the browser spins for about 3 minutes before finally failing. Application Insights is not offering any insight. And the CDN reverse proxy works fine for rendering unprocessed blobs retrieved from Azure Blob Storage.

If anyone has run into this before, I thought I might give it a shot to ask here. Thanx.

— Reply to this email directly, view it on GitHub https://github.com/imazen/imageflow-dotnet/issues/54, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAA2LH4QCA6W6LFPVTUXSV3WV6BYXANCNFSM6AAAAAAURWTE64 . You are receiving this because you are subscribed to this thread.Message ID: @.***>

tachyon1337 commented 1 year ago

commenting out the contentlength header was one of the first things I tried. Unfortunately, that results in client requests directed at the app service to stop working properly as well.

lilith commented 1 year ago

Imageflow .NET Server is designed to handle all this for you and the best way to go for production use. It supports processing images from Azure and S3, also, plus the essential caching you need behind a cdn.

Reimplementing it is really out of scope here, but have you tried responding with a byte array and commenting out Imageflow altogether?

On Sun, Feb 5, 2023, 1:00 PM S. Francis @.***> wrote:

commenting out the contentlength header was one of the first things I tried. Unfortunately, that results in client requests directed at the app service to stop working properly as well.

— Reply to this email directly, view it on GitHub https://github.com/imazen/imageflow-dotnet/issues/54, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAA2LH7P4N4GZJ4NX3X5CTLWWABF7ANCNFSM6AAAAAAURWTE64 . You are receiving this because you commented.Message ID: @.***>

tachyon1337 commented 1 year ago

Ok, it appears converting the byte array back to a stream and using the CopyTo extension to write it to the response solved the issue. I'm not sure why CopyTo(response.BodyWriter) works and reponse.Body.Write doesn't vis a vis CDN reverse proxy, but it does. Anyways, thanx for your time.

Stream stream = new MemoryStream(bytes.Value.Array);
await stream.CopyToAsync(response.BodyWriter, ct);
//await response.Body.WriteAsync(bytes.Value.Array, bytes.Value.Offset, bytes.Value.Count);
return;
lilith commented 9 months ago

Sorry, I just saw your reply here. CopyToAsync is optimized for specific types including the PipeWriter (response.BodyWriter).

That said, please adjust MemoryStream there to use the offset and count. The ArraySegment means only part of the array is actually the data (although in practice it's often the whole array, it is important to only return the correct data).

Can I ask what about your situation didn't seem a good fit for Imageflow Server? What you've shared sounds pretty ideal for it.