Подтвердить что ты не робот

Является ли $_SERVER ['REQUEST_METHOD'] гарантированным заглавное?

У меня в настоящее время есть strtoupper($_SERVER['REQUEST_METHOD']) в моем коде.

Но нужен ли вызов strtoupper? Возможно ли $_SERVER['REQUEST_METHOD'] быть заглавным?

4b9b3361

Ответ 1

RFC 3875 определяет переменную REQUEST_METHOD как верхний регистр, поэтому все в порядке полагаться на нее.

Мета-переменная REQUEST_METHOD ДОЛЖНА быть установлена ​​на метод, который    должен использоваться script для обработки запроса...

  REQUEST_METHOD   = method
  method           = "GET" | "POST" | "HEAD" | extension-method
  extension-method = "PUT" | "DELETE" | token

Метод чувствителен к регистру.

Ответ 2

Короткий ответ: нет, он не гарантируется, но, как правило, получение 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']), как это было здесь у заданного здесь вопроса.

Ответ 3

Это полностью SAPI-специфический, и насколько я знаю, в PHP "спецификация" нет ничего, что заставило бы заглавное имя метода. Здесь фрагмент кода из AOL Server SAPI:

Ns_RegisterRequest(ctx->ns_server, "POST", value, php_ns_request_handler, NULL, ctx, 0);

Если кто-то изменит это значение POST на POST, это будет строчным.

Один вызов strtoupper() не требует от вас абсолютно ничего, поэтому не рискуйте и просто используйте его.

Ответ 4

Да, что 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 говорит только о верхнем регистре. Таким образом, это не будет проблемой.

Верхний случай гарантирован из-за этих вещей.

Ответ 5

Обычно это так, но я не буду рассчитывать на это на 100%. Что-то вроде этого может измениться в новой версии программного обеспечения или в другой конфигурации. Вы действительно не хотите что-то такое же маленькое, как это взломать ваш код при обновлении сервера. Если вы хотите сравнить его, то всегда убедитесь, что обе строки имеют либо нижний, либо верхний регистр.

Ответ 6

Документация php указывает, что для этой переменной существует четыре возможных значения: GET, HEAD, POST или PUT, все из которых верхний регистр. Вы всегда можете сделать strcasecmp вместо сравнения ==.