-
-
Notifications
You must be signed in to change notification settings - Fork 6.9k
Description
What steps will reproduce the problem?
Set response-code in an IIS Server like this:
\Yii::$app->response->statusCode = 500;
or create any critical php error (e.g. echo 10/0
).
What is the expected result?
Expected result is Statuscode 500 in Browser, and HTTP/1.1 500 Internal Server Error
on first line of http headers.
What do you get instead?
Statuscode 200 and first header line of HTTP/1.1 200 OK
Additional info
Q | A |
---|---|
Yii version | 2.0.48.1 |
PHP version | 8.1 |
Microsoft-IIS version | 8.5 |
Operating system | Window |
my Researches to find the problem
I discovered, that yii does not return a statuscode 500 on php errors, and made some research.
I followed the defined status-code in the response until I found yii\web\Response::sendHeaders().
After more testing I can ensure that the statuscode is correctly passed in this method and correctly passed into the header function.
E.g. adding a custom header as debug like this (e.g. in one of your controller actions):
header("X-StatusLine: HTTP/{$this->version} {$statusCode} {$this->statusText}")
Gives the header X-StatusLine: HTTP/1.0 500 Internal Server Error
, what makes me sure that a currect formated statusline is created in the sendHeaders() function, but statuscode is not delivered to browser.
After more reseach I discovered the Status
-header, and made some tests adding this extra header.
The line
header("Status: {$statusCode} {$this->statusText}");
in Response::sendStatus did not chance anything.
But adding the stuscode to the 3. argument of the header function gave the expected result.
Suggestion to fix
Add the line
header("Status: {$statusCode} {$this->statusText}", true, $statusCode);
right after
yii2/framework/web/Response.php
Line 383 in 504a66d
header("HTTP/{$this->version} {$statusCode} {$this->statusText}"); |
or maybe replace the existing line with
if (php_sapi_name() === 'cgi-fcgi')
header("Status: {$statusCode} {$this->statusText}", true, $statusCode);
else
header("HTTP/{$this->version} {$statusCode} {$this->statusText}");
Reasons
It seems that IIS (and maybe other servers) do not respect the statuscode / message set as HTTP/{Protocol} {code} {message}
-header.
Adding the extra header Status: {code} {message}
tells this server to chance their statusline line expected.
As far as I could find out, this behavior has something to do with cgi/fastCGI, so I thinkt this is not only an IIS exclusive problem, and could affect other server types too.