what is the difference from setting the responce status in php
header("HTTP/1.0 404 Not Found");
and
header("Status: 404 Not Found");
What is the difference from the client point of view (aka browser or a client implementation for RESTful WS). I understood that the second one has to do something with CGI.
HTTP/1.0 404 Not Found is the HTTP response code, it's what allows clients to determine whether a request succeeded or not.
Status: 404 Not Found just sets an extra header field called Status with the value of 404 Not Found. It has no intrinsic meaning, it's like setting header('Foo: Bar'). It may mean something to somebody, but it's not officially specified what it should mean. The HTTP response code will be a normal 200 OK.
There seems to be a special case when running PHP through FastCGI. Apparently you can't set the HTTP/ status directly when invoking PHP with this method. Instead you have to set this unofficial header, which will be converted to a real HTTP/ code before it's send back to the client (apparently a limitation of how PHP can talk to the web server when invoked via CGI). In all other cases, it'll just be send as-is (with no meaning) and the real HTTP response code will be 200 OK.
That's what I could gather from the description in the manual at least, I've never had to use this. Also, you're insane if you run PHP through CGI, so hopefully nobody needs this in this day and age. ;o)
Related
I have a web application that can be accessed only if the client accessing the application is within a group of allowed subnets.
If not, I want to redirect to a page with an appropriate HTTP header. The HTTP status that seems most obvious to me for this purpose is a 403 Forbidden.
I am currently using:
header('HTTP/1.1 403 Forbidden');
header('Status: 403 Forbidden');
However, is this the ideal status code for the scenario described?
I want to redirect to a page with an appropriate HTTP header
Don't redirect. Just return the error response for the URL that was requested. ("You can find /foo at /error" … "You aren't allowed to read /error" doesn't make much sense).
is this the ideal status code for the scenario described
The definition of 403 is:
The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeated.
Which matches your scenario, so yes, use that.
403 Forbidden seems like the most descriptive status code for this. However, RFC 2616 suggests that you could also use 404 Not Found if you don't want to let the user know that the reason for the failure is an access control restriction. It says:
If ... the server wishes to make public why the request has not been fulfilled, it SHOULD describe the reason for the refusal in the entity. If the server does not wish to make this information available to the client, the status code 404 (Not Found) can be used instead.
If the person attempting the access believes the error code, it might discourage them from trying to find a way around the restriction (e.g. by searching for a proxy). But it probably won't stop a determined hacker.
The server response codes/http status codes (101, 200, 404, etc.) should be sent in headers in every interaction between user and server. How would one monitor the codes from PHP, so that if an error code were sent, it could be linked to user actions logged by the web application, and responded to appropriately, say by locking out or redirecting a user getting repeated 403 (forbidden) codes by trying to access things on the server they shouldn't be?
Check http_response_code:
*If you pass no parameters then http_response_code will get the current status code. If you pass a parameter it will set the response code.*
http://php.net/manual/en/function.http-response-code.php
Basically nohow, as the headers are sent by the web server before the PHP file is parsed and the "real" output is generated. You might use the method http_response_code(), but consider this: if you want to access a folder your www-data does not have read rights, you will get a 403 Forbidden. It is the webserver's message, the PHP is never even touched (because, for the webserver, it doesn't even exist).
The only way you can catch these events if you specifically use a custom ErrorDocument it your configuration or if the response codes are sent out by the PHP file:
if ( !$something )
header("HTTP/1.1 403 Forbidden");
Why is the HTTP response code (or the first line of the HTTP response header) not available in the PHP $_SERVER variable array?
Is it a limitation on the way server technology works? A limitation with PHP? With the HTTP protocol? Or maybe I'd be completely NUTS to ever want the HTTP response code? ;)
In my case, I'm working with Apache2.
Just curious.
EDIT 1: I'm inquiring about the equivalent of %>s (the status of the LAST request) used by Apache's LogFormat directive before the server response is sent.
EDIT 2: The answers make perfect sense, but the question remains, why can't I get my server's internal working response code? If I set an ErrorDocument 403 /index.php, I can access the response code with $_SERVER['REDIRECT_STATUS']. Isn't there an easier way? I'm guessing not. I still learned a lot from your answers, however. It makes sense.
There's also apache_response_headers(), but still no love for the working response code/first line.
Because the HTTP response is something that is sent to the client, and you can change it within your PHP using the header function. It's not something that is automatic within your PHP and would be handled by the server (ie apache) before it would be given over to PHP.
$_SERVER contains all data of the http request, headers and also other info like the path of current file. But not response, your script is meant to create the response, not access it.
http://php.net/manual/en/reserved.variables.server.php
If you don't set it with header function, status code will always be 200 for successful responses and in case of fatal error, php may change it to 500 (Internal Server Error).
Almost every other status is handled by the webserver without passing thee request to your script.
I'm trying to set a custom HTTP 1.0 status code in order to return more descriptive error messages via AJAX (using jQuery).
In PHP I have something like:
header( 'HTTP/1.0 909 Hello World' );
exit;
This works as expected on my development environment using Apache 2.2.15 but it does not work on the production webserver running LiteSpeed 5.5. LiteSpeed instead returns a 200 OK.
Using this:
header( 'HTTP/1.0 404 Hello World' );
exit;
Apache returns the 404 with the text above. LiteSpeed replaces the custom text with the default 'Not Found'.
Any idea how to override this feature in LiteSpeed to make it work the same way as Apache? I understand they are supposed to be comparable webservers.
Any ideas, please do let me know.
-P.
First, why HTTP 1.0 and not 1.1?
Second, you're trying to do things that aren't defined in the HTTP spec. LiteSpeed probably checks the headers its being asked to send and replaces values it doesn't recognise with some default value.
You shouldn't be trying to force HTTP to behave in a non-standard way, as soon as you do, it ceases to be HTTP. The specifications are there to make sure that software implemented at different times by different people can interoperate, and how it should behave if you don't follow the spec is completely undefined.
Apache letting a header it doesn't know through is perfectly acceptable behaviour, and so is LiteSpeed's behaviour of refusing to let it through. Making demons fly out of your nose would also be a valid thing for the server to do in this case. And what is the client meant to do with an HTTP response code it doesn't recognise?
If you need to send additional information in the header, why not add a new header? The following should do.
header ('X-My-App-Header: Hello World!');
While logging HTTP requests to a file I have found something I would not expect.
I just put in the log the $_SERVER['REQUEST_URI'].
Guess what I have found, an url with #fragment attached:
18/05: requested cat/page.html#fragment
Note out of 2477 line of logs I found only one line with fragment attached
Everyone know (should) that fragment is never known server-side but only javascript code can get it. So what is happening here?
I am running PHP 5.3 on Apache 2.X (Debian).
Your assertion that "fragment is never known server-side but only javascript code can get it" is a little short-sighted.
Whilst it's true that, in general operation with a conventional browser, a fragment is not included in the request-to-server, there is nothing stopping me from writing whatever I want in an HTTP request.
echo "GET /lol/werent/expecting/this#were_you HTTP/1.1" > /dev/tcp/yourwebsite.com/80
Someone's testing, someone's playing, someone's playing a bizarre hack attempt, or someone's using a buggy browser.
I wouldn't worry about it.