Closed kirkmadera closed 3 years ago
Hi @kirkmadera. Thank you for your report. To help us process this issue please make sure that you provided the following information:
Please make sure that the issue is reproducible on the vanilla Magento instance following Steps to reproduce. To deploy vanilla Magento instance on our environment, please, add a comment to the issue:
@magento give me 2.4-develop instance
- upcoming 2.4.x release
For more details, please, review the Magento Contributor Assistant documentation.
Please, add a comment to assign the issue: @magento I am working on this
Join Magento Community Engineering Slack and ask your questions in #github channel.
:warning: According to the Magento Contribution requirements, all issues must go through the Community Contributions Triage process. Community Contributions Triage is a public meeting.
:clock10: You can find the schedule on the Magento Community Calendar page.
:telephone_receiver: The triage of issues happens in the queue order. If you want to speed up the delivery of your contribution, please join the Community Contributions Triage session to discuss the appropriate ticket.
:movie_camera: You can find the recording of the previous Community Contributions Triage on the Magento Youtube Channel
:pencil2: Feel free to post questions/proposals/feedback related to the Community Contributions Triage process to the corresponding Slack Channel
This can't be fixed by removing the output as many other classes assume this functionality to exist. I think you should maybe add a flag like $outputDirectly
defaulted to false and call this out in BC breaks. Then update existing core code to either use this with the $response object correctly or set this flag to true.
Our current workaround is add output buffering around this. This feels really dirty, but makes this a non-issue for downloads on the frontend. I think it must technically be sending the headers multiple times, but it does it in one shot which makes PHP not complain. I am guessing that Nginx cleans up the duplicate headers? Not sure of the downstream here, but it does work.
class FileFactoryPlugin
{
/**
* @param \Magento\Framework\App\Response\Http\FileFactory $subject
* @param string $fileName
* @param string|array $content
* @param string $baseDir
* @param string $contentType
* @param int $contentLength
* @return array
*/
public function beforeCreate(
\Magento\Framework\App\Response\Http\FileFactory $subject,
$fileName,
$content,
$baseDir = DirectoryList::ROOT,
$contentType = 'application/octet-stream',
$contentLength = null
) {
ob_start();
return
[
$fileName,
$content,
$baseDir,
$contentType,
$contentLength
];
}
}
I wanted to point out that there was a post in Magento Community Engineering Slack -- General channel -- That appeared to validate this issue.
Warning: Cannot modify header information - headers already sent by (output started at /home/jetrails/a.com/html/vendor/magento/framework/App/Response/Http/FileFactory.php:102) in /home/jetrails/a.com/html/vendor/magento/framework/Stdlib/Cookie/PhpCookieManager.php on line 148
#1 setcookie() called at [vendor/magento/framework/Stdlib/Cookie/PhpCookieManager.php:148]
#2 Magento\Framework\Stdlib\Cookie\PhpCookieManager->setCookie() called at [vendor/magento/framework/Stdlib/Cookie/PhpCookieManager.php:101]
#3 Magento\Framework\Stdlib\Cookie\PhpCookieManager->setSensitiveCookie() called at [vendor/magento/framework/App/Response/Http.php:114]
#4 Magento\Framework\App\Response\Http->sendVary() called at [generated/code/Magento/Framework/App/Response/Http/Interceptor.php:37]
#5 Magento\Framework\App\Response\Http\Interceptor->sendVary() called at [vendor/magento/module-page-cache/Model/App/Response/HttpPlugin.php:25]
#6 Magento\PageCache\Model\App\Response\HttpPlugin->beforeSendResponse() called at [vendor/magento/framework/Interception/Interceptor.php:121]
#7 Magento\Framework\App\Response\Http\Interceptor->Magento\Framework\Interception\{closure}() called at [vendor/magento/framework/Interception/Interceptor.php:153]
#8 Magento\Framework\App\Response\Http\Interceptor->___callPlugins() called at [generated/code/Magento/Framework/App/Response/Http/Interceptor.php:117]
#9 Magento\Framework\App\Response\Http\Interceptor->sendResponse() called at [vendor/magento/framework/App/Bootstrap.php:262]
#10 Magento\Framework\App\Bootstrap->run() called at [pub/index.php:40]
/returns/attachment/download/uid/1b2805dced1f9b4d0e1921f67bf426f8f6cf413f87a521813f69c43c5ee02a32/index.php
Here is additional details with the versioning:
I'm having this error after I upgrade 2.3.3 to 2.3.5p2. Any input is appreciated.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed after 14 days if no further activity occurs. Is this issue still relevant? If so, what is blocking it? Is there anything you can do to help move it forward? Thank you for your contributions!
Hi,
still facing this issue on magento enterprise 2.3.6 when trying to download order invoice from my customer account in storefront.
Any idea if this still happens on magento 2.4.x ?
\Magento\Framework\App\Response\Http\FileFactory::create
generates output causing headers already sent error. It looks like the intent of this is to output the file at the same time as writing to it when creating a new file from string content. This, however, breaks the contract of controllers (or any code, really) that use this method. Specifically, for controllers, the contract is to return a\Magento\Framework\App\ResponseInterface
object and allow the app to do the actual rendering.M2 2.3.5 code
See
$this->_response->sendHeaders();
,echo
, andflush()
\Magento\Framework\App\Response\Http\FileFactory::create
RMA use case where this is used incorrectly
This method returns the response object. When the
create()
method also outputs directly, this result in a "headers already sent" PHP error.Oddly, the behavior is inconsistent. It only seems to fail on the second attempt to download a file on a given frontend page.
\Magento\Rma\Controller\Adminhtml\Rma\PrintLabel::execute See
return $this->_fileFactory->create
Preconditions (*)
Steps to reproduce (*)
Our test case is in downloading the shipping label or packing slip on the frontend for RMA. But it seems this would be true for any file download on the frontend. I am actually not sure why this works in the admin to be honest, because the admin controller suffers from the same issue of both outputting and returning a response object.
var/log/exception.log
to see the "headers already sent" PHP errorExpected result (*)
Actual result (*)
var/log/exception.log
Please provide Severity assessment for the Issue as Reporter. This information will help during Confirmation and Issue triage processes.
Customers are able to potentially work around this if they refresh the full page a few times and try the download until it works. There are times when it doesn't work at all and the customer may have no workaround.
In this use case, this would prevent a customer from being able to print his shipping label and return his item. This would result in a customer service call and a work around on the customer service end of printing the label manually and emailing it to the customer.