重写pushState-URL的nginx

Ind*_*ial 21 rewrite nginx backbone.js pushstate

我正在尝试nginx使用我在Javascript应用程序中为我管理的pushState基于URI的URI处理backbone.js.

现在正在访问一个级别的URI,例如.example.com/users效果很好,但不是两级或更深的URI,例如Backbone文档中example.com/users/all提到的:

例如,如果您的路径为/ documents/100,则如果浏览器直接访问该网址,您的网络服务器必须能够提供该网页

因此,我不太了解nginx的重写选项,我仍然确定我可以做一些事情,比如rewrite ^ /index.html;将所有内容重定向到我的内容index.html,但是丢失了存储在我需要的同一台服务器上的任何最终静态文件(图像,javascript和css)能够访问.

那么我应该怎样做以下所示的当前配置,以使其工作?

server {
    listen   80;
    server_name  example.com;

    location / {
        root   /var/www/example.com;
        try_files $uri /index.html;
    }

}
Run Code Online (Sandbox Code Playgroud)

Chr*_*isC 32

我最终选择了这个解决方案:

server {

    listen 80;
    server_name example.com;
    root /var/www/example.com;

    # Any route containing a file extension (e.g. /devicesfile.js)
    location ~ ^.+\..+$ {
        try_files $uri =404;
    }

    # Any route that doesn't have a file extension (e.g. /devices)
    location / {
        try_files $uri /index.html;
    }

}
Run Code Online (Sandbox Code Playgroud)

这样,如果找不到文件,至少我仍然会得到正确的404错误.

  • 谢谢,这对我有用.拥有一个实际的404很重要 - 如果请求的JS文件不存在而且返回HTML,浏览器会尝试将其解析为JS并抛出各种JS错误.这可能会搞砸SPA. (2认同)

jne*_*ney 19

这是我对我的申请所做的.每个以'/'结尾的路线(除了自己的根)都将用于index.html:

  location ~ ^/.+/$ {
    rewrite .* /index.html last;
  }
Run Code Online (Sandbox Code Playgroud)

您还可以为您的路线添加前缀:

Backbone.history.start({pushState: true, root: "/prefix/"})
Run Code Online (Sandbox Code Playgroud)

然后 :

  location ~ ^/prefix/ {
    rewrite .* /index.html last;
  }
Run Code Online (Sandbox Code Playgroud)

或者为每个案例定义一个规则.

  • 你的第一个建议似乎需要一个斜杠...当我转到"/ search /"而不是"/ search"时,重写有效 (3认同)

Ada*_*ite 15

我像这样管理它:

#set root and index
root /var/www/conferences/video/;
index  index.html;

#route all requests that don't serve a file through index.html
location / {
   if (!-e $request_filename){
      rewrite ^(.*)$ /index.html break;
   }
}
Run Code Online (Sandbox Code Playgroud)


pxw*_*ise 7

使用客户端应用程序路径:

/
/foo
/foo/bar
/foo/bar/baz
/foo/bar/baz/123
/tacos
/tacos/123
Run Code Online (Sandbox Code Playgroud)

使用:

server {
    listen 80;
    server_name example.com;
    root /var/www/example.com;

    gzip_static on;

    location / {
      try_files $uri $uri/ /index.html;
    }

    # Attempt to load static files, if not found route to @rootfiles
    location ~ (.+)\.(html|json|txt|js|css|jpg|jpeg|gif|png|svg|ico|eot|otf|woff|woff2|ttf)$ {
      try_files $uri @rootfiles;
    }

    # Check for app route "directories" in the request uri and strip "directories"
    # from request, loading paths relative to root.
    location @rootfiles {
      rewrite ^/(?:foo/bar/baz|foo/bar|foo|tacos)/(.*) /$1 redirect;
    }
}
Run Code Online (Sandbox Code Playgroud)

虽然@ Adam-Waite的答案适用于根级别的根和路径,但在位置上下文中使用if被视为反模式,在转换Apache样式指令时经常会出现.请参阅:http://wiki.nginx.org/IfIsEvil.

在使用react-router和HTML5 pushState的类似React应用程序中,其他答案不包括具有目录深度的路由.在"目录"中加载或刷新路由时,例如example.com/foo/bar/baz/213123我的index.html文件将在相对路径引用js文件并解析为example.com/foo/bar/baz/js/app.js而不是example.com/js/app.js.

对于目录深度超出第一级的情况,例如/foo/bar/baz,注意@rootfiles指令中声明的目录的顺序:最长的路径需要先行,然后是下一个较浅的路径/foo/bar,最后/foo.