我有以下场景:nginx 为客户端提供静态文件。对于请求,在本地目录中搜索文件,如果未找到,则通过指令将请求转发到 Amazon S3 proxy_pass
。
问题是,如果找不到文件,Amazon S3 将返回 HTTP 403,而我想将客户端的该代码更改为 404。
(附注:这台运行 nginx 的机器被授权无需任何凭证即可从 S3 检索文件,并且运行正常)
我的配置如下:
user nobody;
worker_processes auto;
pid /run/nginx.pid;
events {
worker_connections 2048;
multi_accept on;
use epoll;
}
http {
reset_timedout_connection on;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
gzip off;
open_file_cache off;
server {
listen 8000 backlog=1000;
server_name blablabla;
#
# Requests made to this server are in the form of GET /file/<sha256> and
# for aabbc1111111111...11 the file will be located in:
# * /files/aa/bb/c/aabbc111111...11.bin on the disk
# * s3://my-bucket-name/aa/bb/c/aabbc1111111...11.bin in S3
#
location ~ "^/file/(?<a>[0-9a-fA-F]{2})(?<b>[0-9a-fA-F]{2})(?<c>[0-9a-fA-F])(?<d>[0-9a-fA-F]{59})$" {
root /files;
rewrite ^ /$a/$b/$c/$a$b$c$d.bin break;
# If 404 results from trying to serve the file from the local directory,
# move to S3
error_page 404 = @try_s3;
}
location @try_s3 {
rewrite ^(.*)\.bin$ /my-bucket-name$1 break;
return 404;
proxy_http_version 1.1;
proxy_pass https://s3-eu-west-1.amazonaws.com;
proxy_set_header Connection ""; break;
proxy_intercept_errors on;
# This is not working, I still get 403, but the difference is that
# with it, I get 403 from nginx (with its 403 HTML template), without
# it I get the 403 sent from S3 (with their HTML in it)
error_page 403 =404;
}
# This is used for the load balancer
location /ping {
return 200;
}
location / {
return 404;
}
}
}
答案1
该error_page
指令就是您想要在这里使用的,因此您走在正确的轨道上。 文档表示该uri
参数不是可选的。您可能会因此而犯错。尝试以下操作:
error_page 403 =404 /404.html;
确保创建一个404.html
有用的地方。
你可能也可以通过将 403 错误页面指向不存在的文件来“欺骗” nginx 返回 404 错误:
error_page 403 /this-does-not-exist.flibettyjibbety;
这可能会有效,因为 nginx 返回 URI 处理期间遇到的最后一个错误代码。
如果所有这些都不起作用,那么您将需要获取正在处理的请求的一些调试日志,如果您无法弄清楚,请将其编辑到您的问题中以进行进一步分析。