I've currently got strtoupper($_SERVER['REQUEST_METHOD'])
in my code.
But is the strtoupper
call necessary? Is $_SERVER['REQUEST_METHOD']
guaranteed to be uppercase already?
Short answer: no, it's not guaranteed, but normally receiving a non-uppercase HTTP method means that the client was in violation of spec.
If you're dealing with methods defined by W3 specs, like GET and POST, then you're guaranteed that a spec-compliant client will send you them in uppercase. This is because HTTP methods are defined as case-sensitive...
The Method token indicates the method to be performed on the resource identified by the Request-URI. The method is case-sensitive.
and the W3-defined methods like OPTIONS, GET, POST etc. are defined in uppercase.
However, if you're dealing with a non-spec-compliant client, neither your webserver nor PHP will magically coerce the value of $_SERVER['REQUEST_METHOD']
to uppercase for you. This can be demonstrated easily with a simple script like this...
<?php
echo "The method used by your request was $_SERVER[REQUEST_METHOD]";
?>
If we hit that script with a HTTP request whose method is not uppercase, it will echo back the method in non-uppercase. Plenty of common tools will let us do this. For example, let's hit it from the UNIX shell:
$ curl http://localhost/echo_method.php -X GET -w "\n"
The method used by your request was GET
$ curl http://localhost/echo_method.php -X gEt -w "\n"
The method used by your request was gEt
$ curl http://localhost/echo_method.php -X fWoRbLeWoRbLe -w "\n"
The method used by your request was fWoRbLeWoRbLe
... or using Python:
>>> import httplib
>>> connection = httplib.HTTPConnection('localhost')
>>> connection.request('pOsT', '/echo_method.php')
>>> connection.getresponse().read()
'The method used by your request was pOsT'
"Okay", you might well say, "so there are potential problems if my API is being used by badly-written scripts or native applications. But my API is only used by AJAX calls triggered by JavaScript running in a web browser. Does this issue affect me?"
Unfortunately, yes. It seems that modern browsers coerce most of the standard HTTP methods to uppercase when sending AJAX, but do not currently do so for either custom HTTP methods or, notably, the PATCH method.
Hitting that same PHP script from before, this time at the Chrome JavaScript console...
var request;
request = new XMLHttpRequest();
request.open("GeT", "http://localhost/echo_method.php", true);
request.send();
request.onreadystatechange = function() {
if (request.readyState == 4) {
console.log(request.responseText);
}
}
yields the result
The method used by your request was GET
but changing the HTTP method to pATcH
gives us
var request;
request = new XMLHttpRequest();
request.open("pATcH", "http://localhost/echo_method.php", true);
request.send();
request.onreadystatechange = function() {
if (request.readyState == 4) {
console.log(request.responseText);
}
}
gives us
The method used by your request was pATcH
Worse, web browsers are not the only clients that will coerce all methods except the PATCH method to uppercase.
In conclusion: while the HTTP spec requires that requests include the HTTP method in uppercase (unless it's a custom method specifically defined in a different case), common web tools make it reasonably easy for front-end developers to get this wrong, and PHP's $_SERVER['REQUEST_METHOD']
variable will not magically coerce the method to uppercase for you if they do.
It's up to you, of course, whether you want to rely on your clients complying with spec, validate that the method is uppercase and respond with an appropriate status code (perhaps 400 or 405) and error message if it is not, or accept incorrectly-cased HTTP methods by coercing the method to uppercase yourself via strtoupper($_SERVER['REQUEST_METHOD'])
like the question asker here originally was.
RFC 3875 defines the REQUEST_METHOD
variable as upper case, so it's okay to rely on it.
The REQUEST_METHOD meta-variable MUST be set to the method which should be used by the script to process the request ...
REQUEST_METHOD = method method = "GET" | "POST" | "HEAD" | extension-method extension-method = "PUT" | "DELETE" | token
The method is case sensitive.
It's completely SAPI-specific, and as far as I know there is nothing in PHP "specification" that would force uppercase method name. Here's code snippet from AOL Server SAPI:
Ns_RegisterRequest(ctx->ns_server, "POST", value, php_ns_request_handler, NULL, ctx, 0);
If someone would change that POST
into post
it would be lowercase.
A single call to strtoupper()
costs you absolutely nothing, so don't risk and just use it.
Yes, that's what PHP internally looks for under php 5.4
http://lxr.php.net/opengrok/xref/PHP_5_4/main/SAPI.c#456
454 if (SG(server_context)) {
455 if (PG(enable_post_data_reading) && SG(request_info).request_method) {
456 if (SG(request_info).content_type && !strcmp(SG(request_info).request_method, "POST")) {
http://lxr.php.net/opengrok/xref/PHP_5_4/main/SAPI.c#797
796 } else if (SG(request_info).proto_num > 1000 &&
797 SG(request_info).request_method &&
798 strcmp(SG(request_info).request_method, "HEAD") &&
799 strcmp(SG(request_info).request_method, "GET")) {
It's fed those values from the server, but if it's not conforming to the spec for passing the data it's a badly behaving server... but the HTTP RFC says upper case only. So, it's not really going to be an issue, ever.
Upper case is guaranteed because of these things.
It usually is, but I wouldn't count on it 100%. Something like this can change in a new software version or different configuration. You don't really want something as small as this breaking your code with a server upgrade. If you want to compare it, then always make sure that both strings are either lower or uppercase.
The php documentation seems to indicate that there are four possible values for this variable: GET, HEAD, POST or PUT, all of which are uppercase. You could always do a strcasecmp instead of a == comparison to be sure.