Skip to content
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

Http Statuscode-Line is ignored in ISS Server (and maybe other fastCGI servers) #19923

Open
Radon8472 opened this issue Aug 2, 2023 · 7 comments
Labels
status:ready for adoption Feel free to implement this issue. type:enhancement

Comments

@Radon8472
Copy link

Radon8472 commented Aug 2, 2023

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

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.

@bizley
Copy link
Member

bizley commented Aug 2, 2023

I can see that Symfony is sending

header(sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText), true, $this->statusCode);

so it looks like our way. Do you think that your problem might come from misconfiguration of the server?

@Radon8472
Copy link
Author

I can see that Symfony is sending

header(sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText), true, $this->statusCode);

so it looks like our way. Do you think that your problem might come from misconfiguration of the server?

I took lot of time investigation this problem.
Currently it seems that:
header(sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText), true, $this->statusCode

is corrent and fine for all "normal" webservers.
But in this strange fast CGI modus there seem to be situations, where you need an additional header of Status: 500 Error-Text that server changes the response-code.

I am not 100% sure if this happens for all servers in fast cgi mode, or only for IIS, or if it is any special configuration in IIS.

@samdark
Copy link
Member

samdark commented Aug 18, 2023

Any disadvantages specifying statusCode argument?

@Radon8472
Copy link
Author

Any disadvantages specifying statusCode argument?

I could not find any disadvantages via google ect.

But I found the matching RFC for this header see rfc3875.
Seems to be true, that this header only affects cgi based calls.

Maybe we should extend the qury for api type a bit to somthing linke the example on php.net to

$sapi_type = php_sapi_name();
if (substr($sapi_type, 0, 3) == 'cgi') {
  header("Status: {$statusCode} {$this->statusText}", true, $statusCode);
else
  header("HTTP/{$this->version} {$statusCode} {$this->statusText}");

That makes it covering fast cgi and basic cgi-mode

@samdark
Copy link
Member

samdark commented Aug 26, 2023

Yes. Good idea.

@samdark
Copy link
Member

samdark commented Aug 26, 2023

Do you have time for a pull request?

@samdark samdark added status:ready for adoption Feel free to implement this issue. type:enhancement and removed status:under discussion labels Aug 26, 2023
@Radon8472
Copy link
Author

Radon8472 commented Aug 30, 2023

Do you have time for a pull request?

I think I can write the code, I am not sure if this is all, or if there is anything more to do in documentations ect..
I would start to make a pr containing the code, and test it in iss and apache, but I need some time, this week is very busy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status:ready for adoption Feel free to implement this issue. type:enhancement
Projects
None yet
Development

No branches or pull requests

3 participants