nginx 服务页面取决于协议
nginx serve page depending on protocol
我想同时针对 HTTP/2 和 HTTP/1.x 优化我的网站。对于 HTTP/2(和 SPDY),由于没有额外的请求往返,我想分别提供我的 CSS 和 JS 文件,以获得独立缓存每个文件的好处。但是,如果我只这样做,HTTP/1.x 客户端将遭受额外的往返;所以对于他们来说,我想提供我的 CSS 和 JS 文件连接。
理想情况下,HTTP/2 用户会得到这样的服务 HTML:
<html>
<head>
<link rel="stylesheet" href="stylesheet-1.css">
<link rel="stylesheet" href="stylesheet-2.css">
</head>
<body>
<script src="script-1.js"></script>
<script src="script-2.js"></script>
</body>
</html>
并且 HTTP/1.x 用户将得到这样的服务 HTML:
<html>
<head>
<link rel="stylesheet" href="all-stylesheets.css">
</head>
<body>
<script src="all-scripts.js"></script>
</body>
</html>
是否可以将 nginx 配置为根据客户端协议提供不同的 HTML 文件?
是的,您可以通过 $server_protocol
变量这样做。我通常会建议通过变量扩展来插入文件位置。但在这种情况下,我担心这会让你容易受到注入攻击,因为这个变量的内容似乎是从请求行中逐字复制的。
虽然有一个利用 ngx_http_map_module 的解决方案。假设您的网站位于 /srv/www
:
map $server_protocol $version {
default "1.1";
"HTTP/2.0" "2.0";
# extra case for any SPDY version
"~SPDY/" "2.0";
}
server {
listen [::]:80;
# The line below requires a working SSL configuration!
listen [::]:443 ssl http2;
server_name example.com
root /srv/www/http-1.1/htdocs;
location / {
root /srv/www/http-$version/htdocs;
try_files $uri $uri/ @fallback;
}
# fallback for HTTP/1.1 files. If this fails as well, we get a 404.
location @fallback {
try_files $uri $uri/ =404;
}
}
这将为 /srv/www/http-2.0/htdocs
中的 HTTP/2.0 请求和 /srv/www/http-1.1/htdocs
中的所有其他请求提供服务。如果找不到为 HTTP/2.0 特制的资源,则 HTTP/1.1 的对应文件将用作后备。
我想同时针对 HTTP/2 和 HTTP/1.x 优化我的网站。对于 HTTP/2(和 SPDY),由于没有额外的请求往返,我想分别提供我的 CSS 和 JS 文件,以获得独立缓存每个文件的好处。但是,如果我只这样做,HTTP/1.x 客户端将遭受额外的往返;所以对于他们来说,我想提供我的 CSS 和 JS 文件连接。
理想情况下,HTTP/2 用户会得到这样的服务 HTML:
<html>
<head>
<link rel="stylesheet" href="stylesheet-1.css">
<link rel="stylesheet" href="stylesheet-2.css">
</head>
<body>
<script src="script-1.js"></script>
<script src="script-2.js"></script>
</body>
</html>
并且 HTTP/1.x 用户将得到这样的服务 HTML:
<html>
<head>
<link rel="stylesheet" href="all-stylesheets.css">
</head>
<body>
<script src="all-scripts.js"></script>
</body>
</html>
是否可以将 nginx 配置为根据客户端协议提供不同的 HTML 文件?
是的,您可以通过 $server_protocol
变量这样做。我通常会建议通过变量扩展来插入文件位置。但在这种情况下,我担心这会让你容易受到注入攻击,因为这个变量的内容似乎是从请求行中逐字复制的。
虽然有一个利用 ngx_http_map_module 的解决方案。假设您的网站位于 /srv/www
:
map $server_protocol $version {
default "1.1";
"HTTP/2.0" "2.0";
# extra case for any SPDY version
"~SPDY/" "2.0";
}
server {
listen [::]:80;
# The line below requires a working SSL configuration!
listen [::]:443 ssl http2;
server_name example.com
root /srv/www/http-1.1/htdocs;
location / {
root /srv/www/http-$version/htdocs;
try_files $uri $uri/ @fallback;
}
# fallback for HTTP/1.1 files. If this fails as well, we get a 404.
location @fallback {
try_files $uri $uri/ =404;
}
}
这将为 /srv/www/http-2.0/htdocs
中的 HTTP/2.0 请求和 /srv/www/http-1.1/htdocs
中的所有其他请求提供服务。如果找不到为 HTTP/2.0 特制的资源,则 HTTP/1.1 的对应文件将用作后备。