У меня в настоящее время есть strtoupper($_SERVER['REQUEST_METHOD'])
в моем коде.
Но нужен ли вызов strtoupper
? Возможно ли $_SERVER['REQUEST_METHOD']
быть заглавным?
У меня в настоящее время есть strtoupper($_SERVER['REQUEST_METHOD'])
в моем коде.
Но нужен ли вызов strtoupper
? Возможно ли $_SERVER['REQUEST_METHOD']
быть заглавным?
RFC 3875 определяет переменную REQUEST_METHOD
как верхний регистр, поэтому все в порядке полагаться на нее.
Мета-переменная REQUEST_METHOD ДОЛЖНА быть установлена на метод, который должен использоваться script для обработки запроса...
REQUEST_METHOD = method method = "GET" | "POST" | "HEAD" | extension-method extension-method = "PUT" | "DELETE" | token
Метод чувствителен к регистру.
Короткий ответ: нет, он не гарантируется, но, как правило, получение HTTP-метода, отличного от верхнего, означает, что клиент нарушил спецификацию.
Если вы имеете дело с методами, определенными спецификациями W3, такими как GET и POST, вам гарантируется, что клиент, отвечающий спецификации, отправит вам их в верхнем регистре. Это связано с тем, что методы HTTP определены как чувствительные к регистру...
Маркер метода указывает способ, который должен выполняться на ресурсе, идентифицированном Request-URI. Метод чувствителен к регистру.
и W3-определенные методы, такие как OPTIONS, GET, POST и т.д. определены в верхнем регистре.
Однако, если вы имеете дело с клиентом, не совместимым со спецификацией, ни ваш веб-сервер, ни PHP не будут волшебным образом принуждать значение $_SERVER['REQUEST_METHOD']
к прописному. Это можно легко продемонстрировать с помощью простого script, подобного этому...
<?php
echo "The method used by your request was $_SERVER[REQUEST_METHOD]";
?>
Если мы нажмем на это script с HTTP-запросом, метод которого не является прописным, он будет отгонять метод в прописном. Множество общих инструментов позволит нам это сделать. Например, ударим его из оболочки UNIX:
$ 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
... или используя Python:
>>> import httplib
>>> connection = httplib.HTTPConnection('localhost')
>>> connection.request('pOsT', '/echo_method.php')
>>> connection.getresponse().read()
'The method used by your request was pOsT'
"Хорошо", можно сказать, "так что есть потенциальные проблемы, если мой API используется плохо написанными сценариями или родными приложениями. Но мой API используется только для вызовов AJAX, вызванных JavaScript, запущенных в веб-браузере Это влияет на меня?"
К сожалению, да. Похоже, что современные браузеры принуждают большинство стандартных HTTP-методов заглавными при отправке AJAX, но в настоящее время не делают этого для каких-либо настраиваемых методов HTTP или, в частности, PATCH метод.
Нажимая тот же PHP script от ранее, на этот раз на консоли Chrome JavaScript...
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);
}
}
дает результат
The method used by your request was GET
но изменение метода HTTP на pATcH
дает нам
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);
}
}
дает нам
The method used by your request was pATcH
Хуже того, веб-браузеры не являются единственными клиентами, которые будут принуждать все методы, кроме метода PATCH, в верхний регистр.
В заключение: в то время как спецификация HTTP требует, чтобы запросы включали HTTP-метод в верхнем регистре (если только это особый метод, специально определенный в другом случае), общие веб-инструменты делают его достаточно простым для разработчиков, и переменная PHP $_SERVER['REQUEST_METHOD']
не будет магически принуждать метод к заглавному для вас, если они это сделают.
Для вас, конечно же, хотите ли вы полагаться на своих клиентов, соблюдающих спецификацию, подтвердите, что метод имеет верхний регистр и отвечает соответствующим кодом состояния (возможно, 400 или 405) и сообщением об ошибке, если это не так, или принимать HTTP-методы с неправильным обходом, путем принудительного ввода метода в верхний регистр с помощью strtoupper($_SERVER['REQUEST_METHOD'])
, как это было здесь у заданного здесь вопроса.
Это полностью SAPI-специфический, и насколько я знаю, в PHP "спецификация" нет ничего, что заставило бы заглавное имя метода. Здесь фрагмент кода из AOL Server SAPI:
Ns_RegisterRequest(ctx->ns_server, "POST", value, php_ns_request_handler, NULL, ctx, 0);
Если кто-то изменит это значение POST
на POST
, это будет строчным.
Один вызов strtoupper()
не требует от вас абсолютно ничего, поэтому не рискуйте и просто используйте его.
Да, что PHP внутренне ищет под 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")) {
Он передавал эти значения с сервера, но если он не соответствует спецификации для передачи данных, это плохо работает сервер... но HTTP RFC говорит только о верхнем регистре. Таким образом, это не будет проблемой.
Верхний случай гарантирован из-за этих вещей.
Обычно это так, но я не буду рассчитывать на это на 100%. Что-то вроде этого может измениться в новой версии программного обеспечения или в другой конфигурации. Вы действительно не хотите что-то такое же маленькое, как это взломать ваш код при обновлении сервера. Если вы хотите сравнить его, то всегда убедитесь, что обе строки имеют либо нижний, либо верхний регистр.
Документация php указывает, что для этой переменной существует четыре возможных значения: GET, HEAD, POST или PUT, все из которых верхний регистр. Вы всегда можете сделать strcasecmp вместо сравнения ==.