【问题标题】:Rewrite URL to specifi query parts Nginx将 URL 重写为特定查询部分 Nginx
【发布时间】:2020-07-24 23:45:00
【问题描述】:

我有一种情况,我想重写以下 URL,并将我的第一个 URL 参数作为 data 参数发送,其余作为 query 参数

www.example.com/anything.jpg      //Skip - Do Nothing because its a file from root
www.example.com/anything          //anything == ?data=$1
www.example.com/something/b       //something == ?data=$1    b == &query=$2
www.example.com/certainly/b/c     //certainly == ?data=$1    b/c == &query=$2
www.example.com/anything/b/c.jpg  //anything ==  ?data=$1    b/c.jpg == &query=$2
www.example.com/but/b/c/d         //but ==       ?data=$1    b/c/d == &query=$2

所以我的第一个 URL 参数将始终为 data 并保持为 query 无论它有什么。我在这里htaccess redirect only if it has value after forward slash 找到了这个问题,并在某种程度上得到了它

rewrite ^/(.*)/(.+)$ /handle.php?data=$1&query=$2 last;

这有一些问题,因为这重写为以下

www.example.com/anything.jpg      //Results in 404 Not Found
www.example.com/anything          //Results in 404 Not Found
www.example.com/something/b       //Working good
www.example.com/certainly/b/c     //data=certainly/b    query=c
www.example.com/anything/b/c.jpg  //data=certainly/b    query=c.jpg
www.example.com/but/b/c/d         //data=but/b/c        query=d

我尝试在 rewrite ^/(.*)/(.+)$ /handle.php?data=$1&query=$2 last; 中使用不同的变体,但没有任何效果

【问题讨论】:

  • @mickmackusa 哦对不起,我忘了。我当然接受它作为最佳答案。 :)

标签: php apache nginx url url-rewriting


【解决方案1】:

为了证明正则表达式匹配结果,我将使用preg_replace() 进行演示,但该模式应无缝转换为您的脚本。

代码:(Demo)

$urls = [
    'www.example.com/anything.jpg',      //Skip - Do Nothing because its a file from root
    'www.example.com/anything',          //anything == ?data=$1
    'www.example.com/something/b',       //something == ?data=$1    b == &query=$2
    'www.example.com/certainly/b/c',     //certainly == ?data=$1    b/c == &query=$2
    'www.example.com/anything/b/c.jpg',  //anything ==  ?data=$1    b/c.jpg == &query=$2
    'www.example.com/but/b/c/d',         //but ==       ?data=$1    b/c/d == &query=$2
];

var_export(
    preg_replace('~www\.example\.com/(?![^/]+\.jpg)([^/]+)(?:/(.+))?~', 'www.example.com?data=$1&query=$2', $urls)
);

输出:

array (
  0 => 'www.example.com/anything.jpg',
  1 => 'www.example.com?data=anything&query=',  // note the empty query value
  2 => 'www.example.com?data=something&query=b',
  3 => 'www.example.com?data=certainly&query=b/c',
  4 => 'www.example.com?data=anything&query=b/c.jpg',
  5 => 'www.example.com?data=but&query=b/c/d',
)

对第一个捕获组使用包含斜线的否定字符类将允许贪婪(快速)匹配而不会匹配太多。

负前瞻阻止匹配 jpg 文件。

第二个捕获组是可选的,所以除非你想编写一个单独的模式来匹配data-only url,你需要容忍空分配。

出于您的目的,我未经测试的建议是:

一个声明:

rewrite ^/(?![^/]+\.jpg)([^/]+)(?:/(.+))?$ /handle.php?data=$1&query=$2 last;

或者作为两个声明:

rewrite ^/(?![^/]+\.jpg)([^/]+)$ /handle.php?data=$1 last;
rewrite ^/(?![^/]+\.jpg)([^/]+)/(.+)$ /handle.php?data=$1&query=$2 last;

【讨论】:

  • 嗨米克马克萨!感谢您的友好回答,但我认为有一些问题。你可以测试一下regextester.com
  • 如果上面有演示,我无法在移动设备上查看。你想向我描述这个问题吗?还是使用 regex101.com?我先睡了,我早上去看看。
  • 非常感谢 Mickmackusa!那只是超级答案。实际上,这是我理解正则表达式的错误。它工作得很好。我浏览了你的 SE 个人资料。你很直截了当,你的答案真的就像你在个人资料中所说的那样。爱你
  • 实际上,如果它是对根目录中的图标、png 或 xml 甚至 index.html 等文件的请求,我想跳过。所以,我想我必须在第一个查询部分保留点。因为如果我从第一部分完全删除点,那么它也会重写来自根的任何文件请求。
  • 也许我的建议不清楚。使用^/(?![^/]+\.) 匹配否定前瞻中的文字点(扩展的开头)。您编写的额外(未转义)点将匹配任何字符 - iow,它将匹配扩展名的第一个字符,我认为匹配此字符没有任何价值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-24
  • 1970-01-01
  • 1970-01-01
  • 2021-05-03
  • 2012-02-28
相关资源
最近更新 更多