12

我目前已经strtoupper($_SERVER['REQUEST_METHOD'])进入我的代码。

但是有strtoupper必要打电话吗?$_SERVER['REQUEST_METHOD']已经保证是大写了吗?

4

6 回答 6

15

简短回答:不,不能保证,但通常接收非大写 HTTP 方法意味着客户端违反了规范。

长答案:

如果您正在处理 W3 规范定义的方法,例如 GET 和 POST,那么您可以保证符合规范的客户端会以大写形式向您发送它们。这是因为 HTTP 方法被定义为区分大小写...

Method 标记指示要对由 Request-URI 标识的资源执行的方法。该方法区分大小写。

W3 定义的方法,如OPTIONS、GET、POST 等,均以大写形式定义。

但是,如果您正在处理不符合规范的客户端,您的网络服务器和 PHP 都不会神奇地将值强制$_SERVER['REQUEST_METHOD']转换为大写。这可以通过像这样的简单脚本轻松演示......

<?php
    echo "The method used by your request was $_SERVER[REQUEST_METHOD]";
?>

如果我们使用方法不是大写的 HTTP 请求命中该脚本,它将以非大写形式回显该方法。大量的常用工具可以让我们做到这一点。例如,让我们从 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

...或使用 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 仅由运行在 Web 浏览器中的 JavaScript 触发的 AJAX 调用使用。这样做吗?问题对我有影响吗?”

不幸的是,是的。似乎现代浏览器在发送 AJAX 时将大多数标准 HTTP 方法强制为大写,但目前对于自定义 HTTP 方法或特别是PATCH 方法都没有这样做。

使用之前相同的 PHP 脚本,这次是在 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

更糟糕的是,Web 浏览器并不是唯一将 PATCH 方法以外的所有方法强制转换为大写的客户端。

总结:虽然 HTTP 规范要求请求包含大写的 HTTP 方法(除非它是在不同情况下专门定义的自定义方法),但常见的 Web 工具使前端开发人员很容易出错,而 PHP 的$_SERVER['REQUEST_METHOD']变量如果他们这样做,不会神奇地将方法强制为大写。

当然,这取决于您是否要依赖符合规范的客户,验证该方法是否为大写,并以适当的状态码(可能是 400 或 405)和错误消息(如果不是)进行响应,或者不正确地接受-通过strtoupper($_SERVER['REQUEST_METHOD'])像这里的问题提问者一样将方法强制为大写,来封装 HTTP 方法。

于 2014-02-02T14:44:57.230 回答
5

RFC 3875REQUEST_METHOD变量定义为大写,因此可以依赖它。

REQUEST_METHOD 元变量必须设置为脚本应该用来处理请求的方法......

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

该方法区分大小写。

于 2012-05-26T12:39:42.233 回答
0

它完全是特定于 SAPI 的,据我所知,PHP“规范”中没有任何内容会强制使用大写的方法名称。这是来自 AOL Server SAPI 的代码片段:

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

如果有人将其更改POSTpost小写。

一次通话strtoupper()绝对不会花费您任何费用,因此不要冒险并使用它。

于 2012-05-26T12:39:33.360 回答
0

是的,这就是 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 只说大写。所以,这永远不会成为一个问题。

由于这些原因,保证了大写。

于 2012-05-26T13:07:22.893 回答
-1

它通常是,但我不会指望它 100%。这样的事情可能会在新的软件版本或不同的配置中发生变化。您真的不希望通过服务器升级破坏您的代码这么小的东西。如果要比较它,请始终确保两个字符串都是小写或大写。

于 2012-05-26T12:35:37.947 回答
-2

php 文档似乎表明此变量有四个可能的值:GET、HEAD、POST 或 PUT,它们都是大写的。可以肯定的是,您总是可以进行 strcasecmp 而不是 == 比较。

于 2012-05-26T12:39:33.963 回答