如果 Accept 标头为 text/plain,则 nginx 提供原始内容

如果 Accept 标头为 text/plain,则 nginx 提供原始内容

我有一个正在使用的博客deno_blog托管在运行 Nginx 的 Linux VM 上。因此,我使用如下结构的 URL 访问帖子:https:/blog.myblog.com/hello_world并且是目录hello_world.md中的文件。根据请求将其作为 HTML 提供。/postsdeno_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 tosites-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

我正在回复一个旧帖子,因为我本周花了太多时间来自己解决这个问题。

相关内容