我想要提供图像的缩略图,并且这些缩略图是按需生成的,写入磁盘,然后我想要将它们交给 nginx 来提供。
我的缩略图根文件夹是/var/www/images
。当我收到 请求时/thumb/post1/image1.jpg
,我希望像这样处理它:
- 如果图像存在于中
/var/www/images/thumb/post1/image1.jpg
,则直接提供该图像。 - 如果图像不存在,则需要生成,因此将请求传递给 API
@backend
。 - API 生成图像并将其写入缩略图文件夹,然后使用标
X-Accel-Redirect
头将其路径交回给 nginx。 - nginx 从步骤 1 重新开始处理,由于文件现在存在,因此处理将会成功。
- 如果请求的缩略图项目不存在,API 将返回 404,并且 nginx 应该提供位于的占位符图像
/var/www/images/missing.png
。
我的 nginx 配置如下:
upstream api {
server localhost:7440 fail_timeout=0;
}
server {
root /var/www/www.example.com/public;
location / {
try_files $uri @backend;
}
location /thumb {
root /var/www/images;
try_files $uri @backend /missing.png;
}
location @backend {
root /var/www/api.example.com/public;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_redirect off;
proxy_pass http://api;
#For websocket compatibility
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
我的缩略图保存在项目文件夹之外,因此我需要root
在位置中设置一个指令,/thumb
以便让图像在该位置显示。/
位置处理 API 请求和其他静态资产,/thumb
位置执行相同操作,但也可以回退到missing.png
。
一个怪癖:由于历史原因,我的整体root
文件夹与我命名位置使用的文件夹不同@backend
,但是,我在两个location
指令中都覆盖了它,并且没有顶级try_files
。
但是,这不起作用。丢失图片的请求不会发送到 API,但丢失图片的后备会发送到 API!如果我删除后备,请求做被发送到 API,但随后交接x-accel-redirect
失败,即使文件现在存在;当缩略图确实存在时,nginx 不会为其提供服务——它只是再次访问 API。
这该如何配置?
答案1
你的try_files
说法不对,命名位置需要作为最后一个参数。另外,404 响应是由块生成的,与块中的语句location @backend
无关。try_files
location /thumb
您应该尝试proxy_intercept_errors
处理error_page
来自后端的 404 响应。
例如:
location / {
try_files $uri @backend1;
}
location /thumb {
root /var/www/images;
try_files $uri @backend2;
}
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
location @backend1 {
proxy_pass http://api;
}
location @backend2 {
proxy_intercept_errors on;
error_page 404 /missing.png;
proxy_pass http://api;
}