Skip to content

Fix BinaryFileResponse sending wrong Content-Length header for files modified by stream wrappers/filters #19740

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

Closed
wants to merge 2 commits into from

Conversation

TravisCarden
Copy link
Contributor

Q A
Branch? 2.7
Bug fix? yes
New feature? no
BC breaks? no
Deprecations? no
Tests pass? yes/no
Fixed tickets #19738
License MIT
Doc PR reference to the documentation PR, if any

I have attempted to follow the guidelines for submitting a patch, but this is my first attempt to the contribute to the Symfony community, so I welcome feedback. Thanks.

@fabpot
Copy link
Member

fabpot commented Aug 26, 2016

@TravisCarden You did very well :) What about the suggestion made by @EclipseGc on the linked ticket? It looks like a better way to me at first glance.

@TravisCarden
Copy link
Contributor Author

Sure. As long as no client code depends on \Symfony\Component\HttpFoundation\File\File::getSize() returning the file size on disk specifically, then fixing the problem there solves at a higher level of abstraction. Updating PR...

// Get the file size from a stream rather than from disk in case it is changed later by
// stream wrappers or stream filters.
$file = fopen($this->getPathname(), 'rb');
$fstat = fstat($file);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can't we call stat($this->getPathname()) directly instead?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, just read your linked issue.
any way to add a test case that would break when using the parent getSize()?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To do that I think we'd need to write a test that is actually encrypting files so that the size is different on disc. I assume that's the best way to go about doing this?

…h header for files modified by stream wrappers/filters.
@TravisCarden
Copy link
Contributor Author

I was going to write a unit test for this, but I can't install the project dependencies on the 2.7 branch:

$ composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

Any thoughts?

@jakzal
Copy link
Contributor

jakzal commented Sep 19, 2016

@TravisCarden works for me. Have you updated composer.json by any chance?

@TravisCarden
Copy link
Contributor Author

TravisCarden commented Sep 19, 2016

I've got it working now. Not sure what was actually wrong, since I didn't change anything today. We'll chalk it up to gremlins. Thanks, @jakzal

@TravisCarden TravisCarden force-pushed the 19738 branch 5 times, most recently from b5d8d75 to 126b8ac Compare September 20, 2016 03:15
@TravisCarden
Copy link
Contributor Author

Okay, here's an example of a unit test that fails without the patch and passes with it. It involves an annoyingly large fixture for such a small change, because it requires a stream filter, which in turn necessitates a stream wrapper; and I wasn't sure where those classes should go in the directory structure. They didn't get autoloaded in the test where I put them (hence the @todo), and I didn't have time to look into it. It may be necessary to more fully implement the stream wrapper to prevent a fragile test. In any case, this gets the ball rolling. I would love feedback.

// reliable way to get the effective size of the file is to actually read it.
ob_start();
$size = readfile($this->getPathname());
ob_end_clean();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will load the full response in memory, which means will break for contents that don't fit into memory.
This totally defeat the purpose of using streams imho.
When a stream wrapper/filter is there, we'd better use chunked encoding.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You seem to be correct, of course. I think the code worked in the context of my project on account of incidental configuration details, but considering the matter abstractly it obviously doesn't seem like a solution suitable for generic application. Using chunked encoding in case of a wrapper/filter does seem like a sensible approach. I don't know what that would look like, though.

@nicolas-grekas
Copy link
Member

nicolas-grekas commented Oct 3, 2016

To switch chunked encoding on, one should not send the Content-Length header.
I think we can solve this issue by making getSize return false when a filter/wrapper is at use, and handle that false in BinaryFileResponse.

@nicolas-grekas
Copy link
Member

Since it's impossible to know if a stream has a filter attached to it, the only solution is to make authors responsible for saying it. This is what #21188 tries to achieve. Closing this one.

fabpot added a commit that referenced this pull request Jan 9, 2017
…ryFileResponse (nicolas-grekas)

This PR was merged into the 3.3-dev branch.

Discussion
----------

[HttpFoundation] Add File\Stream for size-unknown BinaryFileResponse

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #19738
| License       | MIT
| Doc PR        | symfony/symfony-docs#7343

Replaces #19740. Native "getSize" is reported to return false on error, so using false as return type doesn't break the signature.

Commits
-------

8011209 [HttpFoundation] Add File\Stream for size-unknown BinaryFileResponse
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants