首页 > 解决方案 > 使用 NGinx 将找不到的图像文件重定向到 Uri

问题描述

我正在将 Laravel 网站从 Apache (htaccess) 切换到 NGinx。我已经构建了一个 Image Serving,它会生成一个带有适当参数的 uri,用于调整 ex: 的大小pics/images/max24h/music_video_red_icon.png。我 Apache 没有找到将其重定向到image/images/max24h/music_video_red_icon.pnglaravel 中的 Action 创建并返回图像的路径的文件。在.htaccess其中使用此代码:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^pics(.*)\.(jpe?g|png|gif|ico|bmp)$ /image$1.$2 [R=307,L]

现在在 NGinx conf 中,如何正确重定向它?我尝试了很多建议,例如:

# Redirect pics file not found to php laravel route to create the image
location @img_proxy {
    rewrite ^/pics(.*)\.(jpe?g|png|gif|ico|bmp)$ /image$1.$2;
}

location / {
    try_files $uri $uri/ /index.php?$query_string;
}

它根本不起作用,如果我删除这些行,服务器就会起作用。我正在使用 Mac High Sierra 10.13.6 。会不会是一些配置冲突?这是完整的nginx.conf

user _www _www;

worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
        listen 80 default_server;
        server_name localhost;
        root /var/www/megalobiz/public;

        add_header X-Frame-Options "SAMEORIGIN";
        add_header X-XSS-Protection "1; mode=block";
        add_header X-Content-Type-Options "nosniff";

        index index.html index.htm index.php;

        charset utf-8;

        gzip on;
            gzip_vary on;
            gzip_disable "msie6";
            gzip_comp_level 6;
            gzip_min_length 1100;
            gzip_buffers 16 8k;
            gzip_proxied any;
            gzip_types
                text/plain
                text/css
                text/js
                text/xml
                text/javascript
                application/javascript
                application/x-javascript
                application/json
                application/xml
                application/xml+rss;

        location = /favicon.ico { access_log off; log_not_found off; }
        location = /robots.txt  { access_log off; log_not_found off; }

        error_page 404 /index.php;

        # removes trailing slashes (prevents SEO duplicate content issues)
        #if (!-d $request_filename)
        #{
        #    rewrite ^/(.+)/$ /$1 permanent;
        #}

        # Redirect pics file not found to php laravel route to create the image
        location ~ ^/pics(.*)\.(jpe?g|png|gif|ico|bmp)$ {
            try_files $uri @img_proxy;
        }

        location @img_proxy {
            rewrite ^/pics(.*)\.(jpe?g|png|gif|ico|bmp)$ /image$1.$2;
        }

        location / {
            try_files $uri $uri/ /index.php?$query_string;
        }

        location ~ \.php$ {
            try_files      $uri =404;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }

        location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc|svg|woff|woff2|ttf)\$ {
            expires 1M;
            access_log off;
            add_header Cache-Control "public";
        }
        location ~* \.(?:css|js)\$ {
            expires 7d;
            access_log off;
            add_header Cache-Control "public";
        }

        location ~ /\.(?!well-known).* {
            deny all;
        }

        location ~ /\.ht {
            deny  all;
        }
    }

    include servers/*;
}

标签: macosnginx

解决方案


.htaccess文件的功能与您的rewrite语句之间的主要区别在于 Apache 将使用 307 响应执行外部重定向,而 Nginx 将执行内部重定向。有关详细信息,请参阅此文档

要强制 Nginx 执行外部重定向,请将permanentorredirect标志附加到rewrite语句中,这将分别生成 301 或 302 响应。

例如:

location @img_proxy {
    rewrite ^/pics(.*)\.(jpe?g|png|gif|ico|bmp)$ /image$1.$2 redirect;
}

302 和 307 响应之间的区别在于后者将重定向 POST 请求方法而不将其更改为 GET。

如果您需要重定向 POST 请求,则需要使用正则表达式 locationif块捕获 URI 的相关部分并使用 areturn 307代替。

例如:

location @img_proxy {
    if ($uri ~ ^/pics(.*)\.(jpe?g|png|gif|ico|bmp)$) {
        return 307 /image$1.$2$is_args$args;
    }
}

请参阅此使用注意事项if


推荐阅读