【问题标题】:nginx, rewrite, API and spaces in parametersnginx、rewrite、API和参数中的空格
【发布时间】:2016-05-31 20:19:08
【问题描述】:

我们正在与其他系统管理员一起使用 lighthtpd->nginx/1.8.1 迁移和重写规则。

我们有这样的 API 和重写规则(在 nginx 中):

rewrite ^/api/(.*)$ /api.php?action=$1 last;

在我的 PHP API 中,我使用explode PHP 函数将“动作”拆分为一个数组。 因此,GET /api/article/search&key=AUTHENTIFICATION_KEY&q=SEARCH_QUERY 重写为/api.php?action=article/search&key=AUTHENTIFICATION_KEY&q=SEARCH_QUERY

PHP系统数组$_GET包含

"action'" => "article/search"
"key"=>"AUTHENTIFICATION_KEY"
"q"=>SEARCH_QUERY

到目前为止一切顺利...除非搜索查询中有空格,如下所示:

GET /api/article/search&key=AUTHENTIFICATION_KEY&q=SEARCH QUERY&blabla=lol&test=wes (last parameters given as examples)

我不知道为什么,但在这种情况下,URL 中的 & 字符似乎被转义了。因此,我的PHP $_GET 数组只有 on 字段:/api 之后的整个字符串。

["action"] => "article/search&key=AUTHENTIFICATION_KEY&q=SEARCH QUERY&blabla=lol&test=wes"$_GET[['key'], $_GET['q'] etc are empty ...

有什么想法吗?

编辑:但是,如果我将 proxy_pass 与位置一起使用,一切正常:

    location ~ /api/(.*) {
            proxy_redirect off;
            proxy_pass https://127.0.0.1/api.php?action=$1;

但我觉得他的解决方案真的很丑......更不用说我们会有很多重写规则来手动重写(大声笑,重新编码,在配置文件中)从 lighttp 到 nginx

编辑:实际上,我认为@Alexey 提出了正确的问题!当我们使用 lighttpd 时,第一个 GET 参数是在重写规则中设置的,然后是“?”。 对 URL 进行编码时,Nginx 似乎无法以这种方式工作,即使使用“?”也是如此。在重写规则中,第一个 GET 参数必须设置为“?”,而不是“&”。 我们正在运行一些测试,但看起来是这样的

GET /api/article/search?key=AUTHENTIFICATION_KEY&q=SEARCH QUERY&blabla=lol&test=yes

有效:)

【问题讨论】:

  • 但是你为什么用&而不是?呢?
  • 发出请求时,请尝试对请求中的值进行 urlencode。看看有没有帮助。GET /api/article/search&key=AUTHENTIFICATION_KEY&q=SEARCH%20QUERY&blabla=lol&test=wes
  • @AlexeyTen 因为我使用“?”在重写中,要引入 GET 参数“action”。 Firefox 或 PowerShell InvokeRestmethod 自动对请求进行编码,我可以在 nginx 日志中看到它。另一方面,当我使用 proxypass 时,请求没有被编码,然后它就可以工作了。
  • 你应该使用GET /api/article/search?key=...

标签: php nginx url-rewriting


【解决方案1】:

我尝试使用以下设置重现您的问题,但我得到了不同的输出,这是您所期望的。

api.php 中的代码

var_dump($_GET);

在 nginx.conf 中配置

rewrite ^/api/(.*)$ /api.php?action=$1 last;

有要求

"GET /api/article/search&key=AUTHENTIFICATION_KEY&q=SEARCH QUERY&blabla=lol&test=wes HTTP/1.1"

输出正是您所期望的。

array(5) {
  ["action"]=>
  string(14) "article/search"
  ["key"]=>
  string(20) "AUTHENTIFICATION_KEY"
  ["q"]=>
  string(12) "SEARCH QUERY"
  ["blabla"]=>
  string(3) "lol"
  ["test"]=>
  string(3) "wes"
}

编辑

进一步测试,如果你的请求中有 url_encoded 字符串,Nginx(或 PHP 本身)会先对请求进行 url_encode,这会将字符 '&' 转义,当你输出 PHP 变量 $_GET 时,它会自动url_decoded,所以整个请求都会被当作var action的值。

所以在发出请求之前检查你的代码,看看你是否有 url_encoded 任何值。

【讨论】:

  • 您好,感谢您的宝贵时间!实际上,出于测试目的,我的 api.php 现在只做一个 print_r($_REQUEST)。我没有做任何手动 url_encoding 但 nginx(或 php?)仍然逃避?和 & ... 有什么想法吗? nginx或php配置错误可能吗?我正在使用 php-fpm 没有任何特殊的调整。 Nginx 1.8.1 Php 5.4.45-1
  • 另外,有朋友在他的服务器上测试,nginx 1.10.0 和php7-fpm,没有任何特殊配置,结果和我一样……
  • 好吧,我想我明白你的意思了。我正在使用 Firefox 或 PowerShell 进行测试,它们似乎在 %20 中编码 ::space::。我不想避免这种情况,大多数客户都这样做。我正在寻找服务器端的解决方案。
  • @nerthazrim 在这种情况下,我认为您可能需要一个新的重写规则。
  • 我认为 Alexei 提出了正确的问题。 Nginx 和 lighttpd 似乎没有相同的行为。
猜你喜欢
  • 2012-03-27
  • 2022-01-21
  • 2021-12-17
  • 2020-11-07
  • 1970-01-01
  • 1970-01-01
  • 2022-01-08
  • 2014-03-16
  • 1970-01-01
相关资源
最近更新 更多