Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is $_SERVER['REQUEST_METHOD'] guaranteed to be uppercase?

Tags:

php

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?

like image 344
callum Avatar asked May 26 '12 12:05

callum


2 Answers

Short answer: no, it's not guaranteed, but normally receiving a non-uppercase HTTP method means that the client was in violation of spec.

Long answer:

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.

like image 191
Mark Amery Avatar answered Sep 17 '22 12:09

Mark Amery


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.

like image 33
strkol Avatar answered Sep 17 '22 12:09

strkol