我正在尝试执行以下操作,但也许我只是陷入了一个愚蠢的语法错误。
旧站点有一个名为数据库的子站点,因此我们有: www.example.com(被彻底取代)
www.example.com/database/< 很多东西 >
新的数据库地点:
database.example.com/ < 与之前不同的内容 >
在 example.com 的 nginx.conf 中:
location ^~/database {
rewrite ^/database/?(.*)$ https://database.example.com/$1 permanent;
}
这部分正在工作。
卷曲: curl -L -vwww.example.com/database/thisisatest
* Connected to www.example.com (<>) port 80 (#0)
> GET /database/thisisatest HTTP/1.1
[...]
< HTTP/1.1 301 Moved Permanently
[...]
< Location: https://database.example.com/thisisatest
<
* Ignoring the response-body
* Connection #0 to host www.example.com left intact
* Issue another request to this URL: 'https://database.example.com/thisisatest'
到目前为止一切顺利。现在我无法完成的部分是:
完整原始请求:
唯一区别:id= 的有效输入是 6 位数字,input= 是 textinput
目标:
- 虚拟:database.example.com/search/XXXX
- 真实:database.example.com/index.php?db=search&name=XXXX
第一个请求 id= 只能是 6 位数字才能构成有效请求。input= 可以是任何文本(德语/英语/西班牙语/法语/波兰语/中文和 0-9)
在 database.example.com 配置中:
从位置内 /
rewrite ^/search.php?input=(.+)/?$ index.php?db=search&name=$1 last;
rewrite ^/view.php?id=([0-9]+)$ index.php?db=search&name=$1 last;
rewrite ^/search/(.+)/?$ index.php?db=search&name=$1 last;
所以,这暂时还不起作用。我的逻辑有些不对。
database.example.com 的完整 nginx.conf:
server {
listen 80;
listen [::]:80;
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name database.example.com;
ssl_certificate /etc/acme.sh/database.example.com/fullchain.pem;
ssl_certificate_key /etc/acme.sh/database.example.com/privkey.pem;
add_header Strict-Transport-Security max-age=15768000;
root /var/webs/database.example.com/htdocs;
access_log /var/webs/database.example.com/logs/access.log main;
error_log /var/webs/database.example.com/logs/error.log warn;
# Add index.php to the list if you are using PHP
index index.php index.html index.htm;
# serve static files directly
location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt)$ {
access_log off;
expires 365d;
}
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
########################################
##### THIS PART HERE DOES NOT WORK #####
########################################
rewrite ^/search.php?input=(.+)/?$ index.php?db=search&name=$1 last;
rewrite ^/view.php?id=([0-9]+)$ index.php?db=search&name=$1 last;
rewrite ^/search/(.+)/?$ index.php?db=search&name=$1 last;
########################################
########################################
}
# pass PHP scripts to FastCGI server
#
location ~ \.php$ {
include snippets/fastcgi-php.conf;
include fastcgi_params;
# With php-fpm (or other unix sockets):
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
location ~ /\.ht {
deny all;
}
location ~ /\.git {
deny all;
}
}
显然,view.php 和 search.php 都不再作为真实文件存在 - 我只是向它们提出了需要修改的请求。
那么,我的逻辑哪里错了? :/ 任何帮助都值得感激。
答案1
该location ~ \.php$
块处理以 结尾的任何 URI .php
,因此前两个rewrite
语句永远不会被触发,因为它们在错误的location
块中。
所有 Nginx URI 都以 开头/
,因此重写的 URI 应该是/index.php
为了正确操作。
rewrite
和语句location
与不包含查询字符串(从?
开始的任何内容)的规范化 URI 进行匹配。查询字符串参数可用作名称以 开头的变量$arg_
。
location
一种可能的解决方案是使用=
and运算符将三个重写语句放入单独的块中^~
。请参阅这个文件了解详情。
例如:
location / {
try_files $uri $uri/ =404;
}
location = /search.php {
rewrite ^ /index.php?db=search&name=$arg_input? last;
}
location = /view.php {
rewrite ^ /index.php?db=search&name=$arg_id? last;
}
location ^~ /search/ {
rewrite ^/search/(.+)/?$ /index.php?db=search&name=$1? last;
}
location ~ \.php$ { ... }
请注意,重写的 URI 带有尾部,?
以防止附加原始查询字符串。请参阅这个文件了解详情。
另一种解决方案使用您原始的正则表达式,但需要针对$request_uri
包含完整原始请求的变量执行。
例如:
map $request_uri $rewrite {
default 0;
~^/search\.php\?input=(?<name>.+)/?$ /index.php?db=search&name=$name;
~^/view\.php\?id=(?<name>[0-9]+)$ /index.php?db=search&name=$name;
~^/search/(?<name>.+)/?$ /index.php?db=search&name=$name;
}
server {
...
if ($rewrite) {
rewrite ^ $rewrite? last;
}
...
}
看这个文件了解详情。