![如果 Accept 标头为 text/plain,则 nginx 提供原始内容](https://linux22.com/image/779061/%E5%A6%82%E6%9E%9C%20Accept%20%E6%A0%87%E5%A4%B4%E4%B8%BA%20text%2Fplain%EF%BC%8C%E5%88%99%20nginx%20%E6%8F%90%E4%BE%9B%E5%8E%9F%E5%A7%8B%E5%86%85%E5%AE%B9.png)
我有一个正在使用的博客deno_blog托管在运行 Nginx 的 Linux VM 上。因此,我使用如下结构的 URL 访问帖子:https:/blog.myblog.com/hello_world
并且是目录hello_world.md
中的文件。根据请求将其作为 HTML 提供。/posts
deno_blog
我有一个部署脚本,它使用 pandoc 将 Markdown 格式的博客文章转换为纯文本,效果非常好。我将这些原始文件托管在一个单独的目录中,raw/
其名称与 HTML 对应文件相同。
就目前而言,我可以通过正常访问我的博客文章https:/blog.myblog.com/hello_world
,也可以通过正确加载纯文本版本https:/blog.myblog.com/raw/hello_world
目标是,raw/
如果客户端的Accept
标头是,则让 NGINX 提供文件夹内的文件text/plain
。但是,当我使用 向 blog.myblog.com/post 发出请求时Accept: text/plain
,我得到了无限重定向。
这是我的 nginx 配置文件,位于/etc/nginx/sites-available and linked to
sites-enabled/`:
server {
server_name blog.myblog.com;
root /opt/blog.myblog.com;
if ($http_accept = "text/plain") {
return 301 https://blog.myblog.com/raw/$request_uri;
}
# Redirect requests on blog.myblog.com to :4096
location / {
proxy_pass http://localhost:4069;
# Pass on information on requests to provided service
proxy_set_header HOST $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-Ip $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /path/to/fullchain.pem; # managed by Certbot
ssl_certificate_key /path/to/privkey.pem; # managed by Certbot
include /path/to/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /path/to/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = blog.myblog.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
server_name blog.myblog.com;
listen 80;
return 404; # managed by Certbot
}
使用 curl -v,您可以看到它正在重定向到/raw/raw/raw/.../raw/raw/hello_world
:
< HTTP/1.1 301 Moved Permanently
< Server: nginx/1.14.0 (Ubuntu)
< Date: Fri, 29 Jul 2022 12:39:44 GMT
< Content-Type: text/html
< Content-Length: 194
< Connection: keep-alive
< Location: https://blog.myblog.com/raw/raw/raw/.../raw/hello_world
答案1
我不会使用重定向来实现这一点,而是使用地图。草稿配置:
map $http_accept $filepath {
"text/plain" /raw$uri;
default $uri;
}
server {
...
location / {
try_files $filepath $filepath/ =404;
}
}
该映射用于$filepath
根据 HTTP Accept 标头定义变量。在上述解决方案中,如果 HTTP Accept 标头为text/plain
,则$filepath
具有前缀 + URI。
然后在虚拟主机配置中,我们使用$filepath
变量来选择要发送给访问者的资源。
最终结果应该是,当http://example.com/1.html
请求的 HTTP Accept 标头仅包含时text/plain
,它将从/raw
目录中提供服务。否则它将从 提供服务root
。
答案2
据我所知,您无法Accept
在 nginx 本身内对标头进行合规操作。使用 执行此操作map
不起作用,因为无法仅使用正则表达式来理解标头。
你能要做的是将请求发送到执行解析的代理(或 fastcgi 等),然后返回X-Accel-Redirect
到您已标记的适当的 nginx 处理程序internal
。
我正在回复一个旧帖子,因为我本周花了太多时间来自己解决这个问题。