配置nginx以支持使用HTML5推送状态URL的单页面网站

21
我该如何配置nginx来将所有URL(不以/api 或静态资源(例如JS /图像)开头的URL)重定向到index.html?原因是我正在使用HTML5推送状态URL与单页应用程序。这意味着根据URL更改内容,无论是AJAX还是JS。

我的当前nginx配置如下:

server {
    listen 2000;
    server_name localhost;

    location / {
        root    /labs/Projects/Nodebook/public;
        index   index.html;
    }

    location /api/ {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;

        proxy_pass http://localhost:3000/;
        proxy_redirect off;
    }
}
3个回答

28

6
这难道不会剥夺你发送404状态码的能力,对于那些确实不存在的事物(例如,如果您忘记包含favicon.ico文件,则会返回index.html文件)?! - aschepis
1
@aschepis:没错。要么别忘了 favicon.ico,要么创建一个专门的规则,如果缺少 favicon.ico,则返回 404。或者任何其他需要单独处理的文件。 - mattes
对于那些遇到“内部重定向循环”的人,请在位置上下文中添加“root”和“index”参数。我就是这样解决的。 - Juned Khatri

6
马特的回答几乎是一种解决方案,但是它不会为缺失的文件(例如favicon.icon)提供404,正如aschepis所指出的那样。
Nginx将选择第一个匹配项。因此,我们可以先匹配文件(如果文件不存在,则会给出404)。然后,对于所有url,默认使用index.html进行位置匹配。
    location /.+\..+ { # files (assuming they always have a dot)
        # use eg alias to serve some files here
    }

    location / { # url routed by client, client gives 404 for bad urls
        try_files $uri /index.html;
    }

如果URL是example.com/users/my.name,这个解决方案将不起作用。 - mattes
第一个匹配位置有点模糊。一个好的指南是 https://www.digitalocean.com/community/tutorials/understanding-nginx-server-and-location-block-selection-algorithms 滚动到匹配位置块部分。 - alexrogers
@alexrogins 你是什么意思?这是针对<任何内容>.<任何内容>的模式匹配,并假定点表示文件。您可以将该模式替换为适合您上下文的任何内容。 - j-a
@j-a 抱歉我的评论不是很清楚。所以,在我阅读文档之前,我看了你的答案,从中得出的结论是 Nginx会选择第一个匹配的位置,也就是说它会按照列表顺序进行匹配并选择第一个匹配的位置。然而,优先级似乎比这复杂得多。 - alexrogers
@alexrogins 我明白了,如果你有其他位置可能需要进行调整。在上述情况中,它将两者都视为前缀,并选择匹配较长的一个。因此,如果这是正确的,顺序应该不重要。如果你尝试了请告诉我 :) - j-a
此处所述,第一个位置部分不会被视为正则表达式匹配。因为它缺少正则表达式可选修饰符~ - Ahmad Ahmadi

2

2
虽然这样做可以起作用,但您将失去对真正存在的常规文件的访问权限。 - mattes
@mattes 这是我发现的一种非常糟糕的方式,部分地从客户端解决它。应该在 Nginx 级别更好地处理更多规则来处理你提到的情况。 - albertpeiro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接