8

这看起来很荒谬,但我在一个多小时的搜索中没有找到有效的答案。

我有一个运行 nginx 的静态网站(恰好在 Varnish 后面)。索引文件称为index.html. 我想将实际访问该 URL 的任何人重定向mydomain.com/index.htmlmydomain.com.

这是我对该站点的 nginx 配置:

server {
  listen  8080;
  server_name  www.mydomain.com;
  port_in_redirect  off;

  location / {
    root   /usr/share/nginx/www.mydomain.com/public;
    index index.html;
  }

  rewrite /index.html http://www.mydomain.com/ permanent;
}

http://www.mydomain.com/index.html301使用该位置按预期响应,http://www.mydomain.com/但不幸的是,http://www.mydomain.com/它还向自身提供了 301,因此我们得到了一个重定向循环。

如果 index.html 确实在请求中,我如何告诉 nginx 仅提供 301 服务?

4

2 回答 2

10

添加一个新的位置块来处理您的主页,并使用 try_files 指令(而不是“index index.html;”)直接查找 index.html 文件。请注意,try_files 要求您至少输入 2 个选项。所以我把同一个文件放了两次。

location = / {
  root   /usr/share/nginx/www.mydomain.com/public;
  try_files /index.html /index.html;
}

根据我的实验看起来不错:

curl -iL http://www.mydomain.com/index.html
HTTP/1.1 301 Moved Permanently
Server: nginx
Date: Sat, 16 Mar 2013 09:07:27 GMT
Content-Type: text/html
Content-Length: 178
Connection: keep-alive
Location: http://www.mydomain.com/

HTTP/1.1 200 OK
Server: nginx
Date: Sat, 16 Mar 2013 09:07:27 GMT
Content-Type: text/html
Content-Length: 4
Last-Modified: Sat, 16 Mar 2013 08:05:47 GMT
Connection: keep-alive
Accept-Ranges: bytes

[更新]重定向循环的根本原因是'index'指令,它触发nginx再次进行另一轮位置匹配。这就是位置块之外的重写规则再次执行的方式,从而导致循环。所以'index'指令就像一个“rewrite...last;” 指示。你不希望在你的情况下。

诀窍是不要再次触发另一个位置匹配。try_files 可以有效地做到这一点。这就是我在原始答案中选择它的原因。但是,如果您愿意,另一个简单的解决方法是替换

  index index.html;

经过

  rewrite ^/$ /index.html break;

在您原来的“位置/”块内。这个'重写......打破;' 指令将使 nginx 保持在同一位置块内,有效地停止循环。但是,这种方法的副作用是您失去了“索引”指令提供的功能。

[更新 2 ]

实际上,索引指令在重写指令之后执行。所以以下也有效。请注意,我刚刚添加了 rewrite...break; 线。如果请求uri是“/”,nginx首先从rewrite规则中查找现有文件/index.html。所以这个请求永远不会触发 index 指令。因此,两个指令可以一起工作。

  location / {
    root   /usr/share/nginx/www.mydomain.com/public;
    index index.html;
    rewrite ^/$ /index.html break;
  }
于 2013-03-19T03:10:27.227 回答
-1

看起来你真的不想index.php出现在地址栏中,对吗?

如果你在 nginx 配置中添加一个重写指令,你会得到一个重定向循环,正如你所经历的那样。如果您对 javascript 解决方案持开放态度,则可以将其放置在您的任何位置index.html以静默地重写地址栏:

<script>
    history.pushState(null, '', '/');
</script>

了解更多信息

请记住,虽然大多数现代浏览器都支持historyAPI,但并非所有浏览器都支持(即大多数版本的 IE)。

于 2013-03-19T02:42:23.730 回答