Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BinaryFileResponse content corruption under nginx on Azure app service (Linux) #42685

Closed
aokrasavin opened this issue Jun 6, 2022 · 5 comments

Comments

@aokrasavin
Copy link

aokrasavin commented Jun 6, 2022

  • Laravel Version: 9.10.1
  • PHP Version: 8.0.17 (cli) (built: Mar 25 2022 18:59:25) ( NTS )
  • Database Driver & Version: N/A (not used, not relevant to this issue)

Description:

A fairly simple controller which picks form input, chooses image from the disk and then returns it to webbrowser. Eg

  $img = .... <get data object describing image>

    $response = response()->file(Storage::disk('public')->path($img->filename));
    $response->headers->set('Content-Type', $img->mime);
    $response->headers->set("Cache-Control", "max-age=86400");
    return $response;

The code works absolutely perfectly on local development instance of Laravel (Windows 10), but corrupts data when deployed on Azure PHP App Service on Linux.

I could confirm from debug that the file exists, could be read and contains correct data.

However, when the data arrives to web browser, it is corrupted in a particular way:

  1. All headers are delivered correctly with code 200
  2. The binary payload for actual image have first 117 bytes stripped out. Eg after the headers, the binary data starts at byte 118, where byte 0 should have been. The rest of the bytes arrive correctly and at the end there are 117 empty bytes (eg 0x00), so the total size is correct.
  3. I have attached an example - the image as expected and the image as delivered
  4. The rest of the application works correctly (Json responses, etc), but any functionality relying on BinaryFileResponse is broken
  5. The issues exists for any files (not just images), for different types of images, for different security (eg HTTP or HTTPS)
  6. The amount of bytes missing at start seems to be always the same and unrelated to image content (eg no magic byte sequence)
  7. The rest of the (fairly complciated) app funcitonality works perfectly - no issues
  8. There is no magical numerology - the numbers of bytes missed seemingly do not correlate with anything (I wish)

Steps To Reproduce:

Run the same code under Windows 10 and under Azure App Service on Linux for PHP 8.0. Below are attached two images - the image stored locally and the image as delivered.

logo 5 good

logo 5 bad

Fix

After lots of headscratching, I found a work around in Symfony code, HOWEVER the problem is not happening in "vanilla" PHP app using Symfony, so I suspect there is a problem with the way Laravel and Symfony interact.

The problem code is this one

namespace Symfony\Component\HttpFoundation;
......
class BinaryFileResponse extends Response
.....
public function sendContent(): static
{
......
stream_copy_to_stream($file, $out, $this->maxlen, $this->offset);
......
}

to fix, I implemented the following - eg PHP native function stream_copy_to_stream is replaced with a custom function, which does (as far as I could tell) the same thing (I have Ranges disabled globally, hence always serve the entire file).

_function pipe_streams($in, $out)
{
$size = 0;
while (!feof($in)) $size += fwrite($out,fread($in,8192));
return $size;
}

public function sendContent(): static

{
......
$this->pipe_streams($file, $out);
......
}_

@rodrigopedra
Copy link
Contributor

Can you try the workaround suggested here: #42681 (comment)

@driesvints
Copy link
Member

Seems this is a Symfony issue. Please don't upgrade to Symfony v6.1 for now and wait until they release a patch release.

@klodoma
Copy link

klodoma commented Aug 8, 2022

I am having a similar issue, some details here:
https://stackoverflow.com/questions/73280423/php-readfile-content-corruption-on-azure-web-applinux

@aokrasavin
Copy link
Author

aokrasavin commented Aug 8, 2022

I am having a similar issue, some details here: https://stackoverflow.com/questions/73280423/php-readfile-content-corruption-on-azure-web-applinux

It is a different manifestation of the same issue. I raised a ticket with Symfony and Azure. They are blaming each other and neither side wants to do the fix.

https://docs.microsoft.com/en-us/answers/questions/953763/php-stream-copy-to-stream-to-php-output-corrupts-d.html

symfony/symfony#47059

@klodoma
Copy link

klodoma commented Aug 8, 2022

Yeah, just found the same azure link. Thanks for the update.

It seems the stream_copy_to_stream function to be the problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants