Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Symfony duplicates content-type header #21204

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
rommeras opened this issue Jan 8, 2017 · 18 comments
Closed

Symfony duplicates content-type header #21204

rommeras opened this issue Jan 8, 2017 · 18 comments

Comments

@rommeras
Copy link

rommeras commented Jan 8, 2017

Q A
Bug report? yes
Feature request? no
BC Break report? no
RFC? no
Symfony version 3.1.8

I use php 7.0.0 with symfony 3.1.8. The issue is when I got errors from php - symfony doesn't return me stack trace, all I can see is "Internal Server Error" page. In logs of apache I found FastCGI: comm with server "/Applications/MAMP/fcgi-bin/php7.0.0.fcgi" aborted: error parsing headers: duplicate header 'Content-Type'
I started debugging, and that's what I found. I use php scalar type hinting, so when the wrong type comes as argument, php returns TypeError, symfony catches it, and then step by step:

  1. Symfony\Component\Debug\ErrorHandler:handleException
    call_user_func($this->exceptionHandler, $exception) L:546
  2. Symfony\Component\Debug\ExceptionHandler:handle
    $this->sendPhpResponse($exception); L:121
  3. Symfony\Component\Debug\ExceptionHandler:sendPhpResponse
    header('Content-Type: text/html; charset='.$this->charset); L:173 - which sends me header of content type first time.
  4. Symfony\Component\Debug\ExceptionHandler:handle (continue)
    call_user_func($this->handler, $exception); L:144
  5. Symfony\Component\HttpKernel\HttpKernel:terminateWithException
    $response->sendHeaders(); L:104
  6. Symfony\Component\HttpFoundation\Response:sendHeaders
    header($name.': '.$value, false, $this->statusCode); L:339 - which sends me header of content type second time.

The output of headers_list function:
0 = "X-Powered-By: PHP/7.0.0"
1 = "Content-Type: text/html; charset=UTF-8"
2 = "Cache-Control: no-cache"
3 = "X-Debug-Token: 242fbb"
4 = "X-Debug-Token-Link: http://pr.project/app_dev.php/_profiler/242fbb"
5 = "Content-Type: text/html; charset=UTF-8"
6 = "Date: Sun, 08 Jan 2017 18:45:04 GMT"

Which causes error of duplicating headers.
Please fix.

@dmaicher
Copy link
Contributor

Maybe this is an issue with your php settings regarding output buffering?

http://php.net/manual/de/function.headers-sent.php#75835

Because normally the headers will not be send again:

https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/Response.php#L369

@rommeras
Copy link
Author

rommeras commented Feb 4, 2017

dmaicher, thank you for response.

Output buffering allows you to send header lines (including cookies) even
; after you send body content, at the price of slowing PHP's output layer a
; bit.

This is not that case, because headers are sent before the body content.
headers_sent function returns true, only when headers were sent, for instance when I do "echo 'text';". Before I output anything, it will return false. (I have output_buffering=Off in php.ini).
In my case, what is happening:

  1. header('Content-Type: text/html; charset='UTF-8');
  2. headers_sent(); // returns false
  3. header('Content-Type: text/html; charset='UTF-8');
  4. echo 'some error';

As a result, header Content-Type is duplicated, I get FCGI error.

@dmaicher
Copy link
Contributor

dmaicher commented Feb 4, 2017

Ok indeed for me in your example headers_sent() also returns false 😋
But I don't get any error using php-fpm & nginx.

@mneuhaus
Copy link

i've experienced this very same issue a few times as well, mostly triggered by the ExceptionHandler.
I've dug a bit in there and found the following problem:

  1. ExceptionHandler puts a Content-Type header into the "header list" to be sent
  2. HttpFoundation Response uses the headers_sent method to check if any headers have been sent, this returns false if you use fcgi, because the headers have not been sent, only "added" to the "header list"
  3. HttpFoundation Response adds it's headers to the "header list"
  4. fcgi tries to send all headers in the "header list" and encounters a problem, because Content-Type was added twice

I've also found a possible solution, instead of using headers_sent to check in the sendHeaders method, !empty(headers_list) could be used to check, if headers have been "scheduled" to be sent.

Example:

<?php
public function sendHeaders()
{
        // headers have already been sent by the developer
        if (headers_sent() || !empty(headers_list())) {
            return $this;
        }
...
}

i could open a pull-request for this, if no-one sees any obvious fault with this?

@binano
Copy link

binano commented Nov 30, 2017

Thanks Mneuhaus, your patch works !

@binano
Copy link

binano commented Dec 7, 2017

Arf... now I have a mistake every morning at the same time. this error is triggered by googlebot every morning at 2:20 AM, every day.

[Thu Dec 07 02:20:34 2017] [error] [client 66.249.64.19] [host www.binano.fr] (104)Connection reset by peer: AH10143: FastCGI: comm with server "/homez.xx/user/www/viewtopic.php" aborted: read failed
[Thu Dec 07 02:20:34 2017] [error] [client 66.249.64.19] [host www.binano.fr] AH10149: FastCGI: incomplete headers (0 bytes) received from server "/homez.xx/user/www/viewtopic.php"
[Thu Dec 07 02:20:34 2017] [error] [client 66.249.64.19] [host www.binano.fr] AH10157: FastCGI: An error happend on Fastcgi processing, fallback to CGI

@aliechti
Copy link

aliechti commented Jan 5, 2018

@mneuhaus Is there any existing PR for this fix?

Currently it isn't possible to use sendHeaders with output buffering on, without having multiple headers sent.

@mneuhaus
Copy link

mneuhaus commented Jan 5, 2018

@thejahweh no, there is no PR yet, because i can't really tell the implications, because this is quite deep in the core of Symfony. i could open one of course.

@sylfabre
Copy link
Contributor

I'm having the same issue with Symfony 4.0 and PHP 7.1

@cristoforocervino
Copy link
Contributor

I have the same issue. Content-Type is sent 2 times sometimes when an exception is thrown because of ExceptionHandler.
schermata 2018-02-15 alle 22 06 32
Because of this, I see a 500 internal server error instead of the Symfony Exception page.
schermata 2018-02-15 alle 22 07 17

By using @mneuhaus fix in HttpFoundation\Response::sendHeaders() I see again the Symfony Exception page.
Or, another way to fix it, is to set the replace parameter of the header function to true.

// headers
foreach ($this->headers->allPreserveCaseWithoutCookies() as $name => $values) {
    foreach ($values as $value) {
        header($name.': '.$value, true, $this->statusCode);
    }
}

I don't have enough knowledge of the HttpFoundation to understand if these are good solutions.
I'm using Symfony 3.4.4 and PHP 7.2.1.

@mvrhov
Copy link

mvrhov commented Feb 16, 2018

you shouldn't set the replace to true as for example the Links header can appear multiple times and this is perfectly legal.

@mikysan
Copy link

mikysan commented Feb 16, 2018

I was wondering why the ExceptionHandler::handle method triggers the ExceptionHandler::sendPhpResponse who sets the header "Content-Type" when there is a Response object responsible of putting that header in the first place? It seems a nonsense to me, what am I missing?

@stephanegg
Copy link

Any news on this error ? I started few weeks, having the same kind of errors on production website..

@fabpot
Copy link
Member

fabpot commented Oct 16, 2018

I understand what happens here. Looking for a fix now.

@nicolas-grekas
Copy link
Member

Introduced in #10941. Headers need to be recalled like the body is already.

@nicolas-grekas
Copy link
Member

Should be fixed by #29057, please confirm if possible.

@mikysan
Copy link

mikysan commented Nov 6, 2018

Should be fixed by #29057, please confirm if possible.

I was curious about how to fix this so I read the fix you propose and it might solve the issue in most cases but actually the last thing setting "Content-Type" header will be used no matters what. And my question remains unanswered, are we sure ExceptionHandler::handle is really meant to set this header?

I do not know if I made my point clear I can try to be more exhaustive if you want :)

@nicolas-grekas
Copy link
Member

nicolas-grekas commented Nov 6, 2018

The answer is yes: the exception handler buffers a response that should be sent to the browser whenever the regular error handling fails. When it doesn't, it's the responsibility of the regular error handling to take over.

nicolas-grekas added a commit that referenced this issue Nov 8, 2018
…ers (nicolas-grekas)

This PR was merged into the 2.8 branch.

Discussion
----------

[HttpFoundation] replace any preexisting Content-Type headers

| Q             | A
| ------------- | ---
| Branch?       | 2.8
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #21204
| License       | MIT
| Doc PR        | -

Commits
-------

de2ce58 [HttpFoundation] replace any preexisting Content-Type headers
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests