[BUGFIX] PSR-7: Do not let legacy code take precedence over HTTP headers 61/42161/2
authorHelmut Hummel <helmut.hummel@typo3.org>
Fri, 31 Jul 2015 09:10:59 +0000 (11:10 +0200)
committerStefan Neufeind <typo3.neufeind@speedpartner.de>
Fri, 31 Jul 2015 14:16:14 +0000 (16:16 +0200)
The code to not overwrite regular headers set by PSR-7 response
is obsolete and should be removed. Legacy code does not have access
to the response object, thus the PSR-7 header list would always be empty.

We also do not want to give legacy code precedence here if our code
explicitly sets some headers.
Also make sure that, if legacy code added some headers, which are also
set in the response object (by us), that the headers are not additionally added
but override the legacy headers.

The only exception is the status code header, which we must allow to
be changed from legacy code for the time being.

Resolves: #68670
Related: #68506
Releases: master
Change-Id: I792f18debcadebc5d9b686a8df2de5a1f547c8ad
Reviewed-on: http://review.typo3.org/42161
Reviewed-by: Markus Klein <markus.klein@typo3.org>
Tested-by: Markus Klein <markus.klein@typo3.org>
Reviewed-by: Stefan Neufeind <typo3.neufeind@speedpartner.de>
Tested-by: Stefan Neufeind <typo3.neufeind@speedpartner.de>
typo3/sysext/core/Classes/Core/Bootstrap.php

index 686dbe2..6e589a0 100644 (file)
@@ -297,20 +297,15 @@ class Bootstrap {
        protected function sendResponse() {
                if ($this->response instanceof \Psr\Http\Message\ResponseInterface) {
                        if (!headers_sent()) {
-                               // headers already set by legacy code
-                               $headers = array_flip(array_map(function($value) { return strtolower(explode(':', $value, 2)[0]); }, headers_list()));
                                foreach ($this->response->getHeaders() as $name => $values) {
-                                       // if the header has already been set, do not overwrite it
-                                       if (!isset($headers[strtolower($name)])) {
-                                               header($name . ': ' . implode(', ', $values), FALSE);
-                                       }
+                                       header($name . ': ' . implode(', ', $values));
                                }
-                               // Send the response type only if it's different from 200.
-                               // This is a safety net if a non 200 status code has already been sent.
-                               // In case we have some non 200 code via the response object though, we write the header in any case.
-                               $statusCode = $this->response->getStatusCode();
-                               if ($statusCode !== 200) {
-                                       header('HTTP/' . $this->response->getProtocolVersion() . ' ' . $statusCode . ' ' . $this->response->getReasonPhrase());
+                               // If the response code was not changed by legacy code (still is 200)
+                               // then allow the PSR-7 response object to explicitly set it.
+                               // Otherwise let legacy code take precedence.
+                               // This code path can be deprecated once we expose the response object to third party code
+                               if (http_response_code() === 200) {
+                                       header('HTTP/' . $this->response->getProtocolVersion() . ' ' . $this->response->getStatusCode() . ' ' . $this->response->getReasonPhrase());
                                }
                        }
                        echo $this->response->getBody()->__toString();