子文件夹的 Nginx 重写规则

Posted

技术标签:

【中文标题】子文件夹的 Nginx 重写规则【英文标题】:Nginx rewrite rule for a subfolder 【发布时间】:2016-08-16 06:52:22 【问题描述】:

我正在尝试重写如下网址:

https://example.com/products/product-post ---> https://example.com/product-post

但我希望同时可以访问 url https://example.com/products/,因为它是产品目录,因此无需任何修改。

这不起作用导致 500 服务器错误:

location /products/ 
    rewrite ^/(.*)$ /products/$1 last;

出于组织原因,我将文件保存在 /products/file1、file2 等中。 也许我应该使用“别名”而不是“重写”?

谢谢。

更新:下面是我的 server.conf 配置

server 
    server_name     www.example.com;
    listen          80;
    listen          443 ssl spdy;
    listen          [::]:80;
    listen          [::]:443 ssl spdy;
    ssl_certificate /opt/ssl/example.com.chained.crt;
    ssl_certificate_key /opt/ssl/example.com.key;
    # Non-www redirect
    return          301 https://example.com$request_uri;

server 
    server_name     example.com;
    listen          443 ssl spdy;
    listen          [::]:443 ssl spdy;
    root            /home/html_public;
    charset      UTF-8;
    ssl_certificate /opt/ssl/example.com.chained.crt;
    ssl_certificate_key /opt/ssl/example.com.key;
    add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload';
    ssl_prefer_server_ciphers on;
    ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_session_cache   shared:SSL:10m;
    ssl_session_timeout 10m;
    keepalive_timeout   70;
    ssl_buffer_size 1400;
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=86400;
    resolver_timeout 10;
    ssl_trusted_certificate /opt/ssl/example.com.chained.crt;
location ~* \.(jpg|jpeg|gif|png|ico|cur|gz|svgz|mp4|ogg|ogv|webm|htc|css|js|otf|eot|svg|ttf|woff|woff2)(\?ver=[0-9.]+)?$ 
    expires 1M;
    add_header Pragma public;
    add_header Cache-Control "public, must-revalidate, proxy-revalidate";
    access_log off;
    
    #access_log  logs/host.access.log  main;
    #===BAN COUNTRIES START ==============
    if ($allowed_country = no) 
    return 403;
    
    if ($bad_referer) 
    return 444;
    
location @extensionless-php 
    rewrite ^(.*)/$ $1.php last;
    rewrite ^(.*[^/])$ $1/ permanent;
    
location / 
    try_files $uri $uri/ @extensionless-php;
    #limit_conn num_conn 15;
    #limit_req zone=num_reqs;
    
    #=====PAGE SPEED START==========
location ~ "\.pagespeed\.([a-z]\.)?[a-z]2\.[^.]10\.[^.]+" 
    add_header "" "";
    
location ~ "^/pagespeed_static/"  
location ~ "^/ngx_pagespeed_beacon$"  
    #=====PAGE SPEED END==========
error_page  404    /404.php;
#pass the PHP scripts to FastCGI server listening on php-fpm unix socket
location ~ \.php$ 
    try_files       $uri =404;
    fastcgi_index   index.php;
    fastcgi_pass    unix:/tmp/php5-fpm.sock;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_param   SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    fastcgi_intercept_errors on;
    fastcgi_ignore_client_abort off;
    fastcgi_connect_timeout 60;
    fastcgi_send_timeout 180;
    fastcgi_read_timeout 180;
    fastcgi_buffer_size 128k;
    fastcgi_buffers 4 256k;
    fastcgi_busy_buffers_size 256k;
    fastcgi_temp_file_write_size 256k;
    include fastcgi_params;

location = /robots.txt 
    access_log off;
    log_not_found off;
    
location ~ /\. 
    deny  all;
    access_log off;
    log_not_found off;
    
#=====START phpMyAdmin==============#
location /phpMyAdmin 
    root /usr/share/;
    location ~ ^/phpMyAdmin/(.+\.php)$ 
    root        /usr/share/;
    try_files   $uri =404;
    fastcgi_index   index.php;
    fastcgi_pass    unix:/tmp/php5-fpm.sock;
    fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include         fastcgi_params;
    
    location ~* ^/phpMyAdmin/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt))$ 
    root /usr/share/;
    
    
location /phpmyadmin 
    rewrite ^/* /phpMyAdmin last;
    
#=====END phpMyAdmin==============#
location /webmail 
    root /usr/share/;
    index index.php index.html index.htm;
    location ~ ^/webmail/(.+\.php)$ 
    root /usr/share/;
    try_files $uri =404;
    fastcgi_pass unix:/tmp/php5-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include       fastcgi_params;
    
    location ~* ^/webmail/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt))$ 
    root /usr/share/;
    

    #====Out Link REDIRECTS===============
    location /go/ 
    rewrite ^/go/(.*)$      /go/site-linker.php?site=$1 last;
    

location ~ /products/(.+) 
    rewrite ^/products/(.*)$ /$1 last;
  

在日志中我得到了这个:

2016/04/24 12:07:45 [notice] 6810#0: *1 "^/products/(.*)$" does not match "/xperia-z5/", client: 192.168.10.2, server: 192.168.10.1, request: "GET /xperia-z5/ HTTP/1.1", host: "192.168.10.1"
2016/04/24 12:07:45 [notice] 6810#0: *1 "^/products/(.*)$" does not match "/xperia-z5/", client: 192.168.10.2, server: 192.168.10.1, request: "GET /xperia-z5/ HTTP/1.1", host: "192.168.10.1"
2016/04/24 12:07:45 [notice] 6810#0: *1 "^(.*)/$" matches "/xperia-z5/", client: 192.168.10.2, server: 192.168.10.1, request: "GET /xperia-z5/ HTTP/1.1", host: "192.168.10.1"
2016/04/24 12:07:45 [notice] 6810#0: *1 "^(.*)/$" matches "/xperia-z5/", client: 192.168.10.2, server: 192.168.10.1, request: "GET /xperia-z5/ HTTP/1.1", host: "192.168.10.1"
2016/04/24 12:07:45 [notice] 6810#0: *1 rewritten data: "/xperia-z5.php", args: "", client: 192.168.10.2, server: 192.168.10.1, request: "GET /xperia-z5/ HTTP/1.1", host: "192.168.10.1"
2016/04/24 12:07:45 [notice] 6810#0: *1 rewritten data: "/xperia-z5.php", args: "", client: 192.168.10.2, server: 192.168.10.1, request: "GET /xperia-z5/ HTTP/1.1", host: "192.168.10.1"

【问题讨论】:

你能重写整个products/product-post吗?这样它应该可以工作...... @MichałZaborowski 如果我这样做,我会得到 404:location /products/(.*)$/ rewrite ^/(.*)$ /products/$1 last; github.com/TeXXaS/nginx-configs/tree/master/rewrite - 请验证这是否不会破坏您的系统,因为需要 sodo。更新配置文件中的重写,然后你可以看到发生了什么 - 查看日志文件 @RichardSmith 是的,产品发布只是一个页面。可以是任何东西。图片如下:domain/category/post/ ---> domain/post/ @RichardSmith 我的意思是我希望将domain/category/post/ 重写为domain/post/。场景是用户看到domain/post/但服务器获取domain/category/post/ 【参考方案1】:

https://www.digitalocean.com/community/tutorials/understanding-nginx-server-and-location-block-selection-algorithms 我已经更新了我的重写示例配置 - https://github.com/TeXXaS/nginx-configs/tree/master/rewrite 从该教程中 - 如果您使用 rewriteindex 或类似的东西,nginx 将在内部重新处理请求。为了解决这个问题 - 我添加了 prods 目录 - 所以对于 .../products/ nginx 服务 /prods/index.html - 而对于所有其他 .../products/(.+) - 请求被重定向到根。因此,如果您键入 http://localhost:10080/products/index.html - 它会从根目录显示 index.html,而不会更改浏览器中的路径。希望对您有所帮助... :)

【讨论】:

再次..没有运气。我认为location @extensionless-php 可能有问题,请查看更新后的问题,我已包含我的配置文件。 开启日志记录:error_log /var/log/nginx/error.log debug; rewrite_log on;。看看哪里出了问题。其他选项 - 请提供 4-5 个示例 URL,以及要执行的目标脚本。我将编写测试来跟踪发生了什么 我用日志更新了问题,因为太大而无法添加为评论。显然有问题。 在第二个服务器级别添加:error_log /var/log/nginx/error.log debug; rewrite_log on; - 然后在服务器上添加tail -f /var/log/nginx/error.log,然后触发您的页面。在控制台上,您将看到发生了什么 - 所有内部重写、正则表达式处理、内部重定向后的重新处理、标头……您命名它 我已经这样做了。 ngx_http_rewrite_module 模块指令处理,结果进入通知级别的error_log。这就是您在日志中看到[notice] 的原因(我更新了问题)【参考方案2】:

经过多次尝试和错误,解决方案原来是:

location / 
    try_files $uri $uri/ @extensionless-php;
    rewrite /(.+$) /products/$1 break;
    
location = /products/ 
    index index.php;

我希望这对将来的某人有所帮助。

【讨论】:

以上是关于子文件夹的 Nginx 重写规则的主要内容,如果未能解决你的问题,请参考以下文章

子文件夹中的重写规则

Nginx 在子文件夹中重写 (404)

将 Nginx 重写从“if”转换为“try_files”

重写子文件夹而不是主网站的规则

nginx配置url重写

特定位置的 nginx 重写规则