为pushState-URL重写nginx

发布于 2025-01-03 14:55:26 字数 835 浏览 1 评论 0 原文

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

现在使用一级访问 URI,例如。 example.com/users 效果很好,但不适用于两级或更深的 URI,例如 example.com/users/all “http://documentcloud.github.com/backbone/#Router-navigate">主干文档

例如,如果您的路由为 /documents/100,则您的 Web 服务器 如果浏览器访问该 URL,则必须能够提供该页面 直接

因此,尽管我对 nginx 的重写选项还很不熟悉,但我仍然确信我可以做类似 rewrite ^ /index.html; 的事情来将所有内容重定向到我的 index.html。 html,但丢失了存储在我需要能够访问的同一服务器上的任何最终静态文件(图像、javascript 和 css)。

那么,我应该如何使用下面显示的当前配置来完成这项工作呢?

server {
    listen   80;
    server_name  example.com;

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

}

I am trying to get nginx to work with my pushState-based URI handling that backbone.js manages for me in an Javascript app.

Right now accessing URI's with one level, eg. example.com/users works well, but not two-level or deeper URI's, such as example.com/users/all, which is mentioned in the Backbone documentation:

For example, if you have a route of /documents/100, your web server
must be able to serve that page, if the browser visits that URL
directly

So, being far from acquainted with nginx's rewrite options, I am still sure that I can do something like rewrite ^ /index.html; to redirect everything to my index.html, but loosing out on any eventual static files (images, javascript & css) stored on the same server which I need to be able to access.

So what should I do instead with the below shown, current configuration, to make this work?

server {
    listen   80;
    server_name  example.com;

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

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

时光暖心i 2025-01-10 14:55:26

我最终采用了这个解决方案:

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;
    }

}

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

I ended up going with this solution:

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;
    }

}

This way, at least I still get proper 404 errors if a file isn't found.

最舍不得你 2025-01-10 14:55:26

这是我对我的应用程序所做的事情。每条以“/”结尾的路由(除了根本身)都将提供 index.html

  location ~ ^/.+/$ {
    rewrite .* /index.html last;
  }

您还可以为路由添加前缀 :

Backbone.history.start({pushState: true, root: "/prefix/"})

,然后为 :

  location ~ ^/prefix/ {
    rewrite .* /index.html last;
  }

或为每种情况定义一个规则。

Here is what i did to my application. Every route ending with a '/' (except the root it self) will serve index.html :

  location ~ ^/.+/$ {
    rewrite .* /index.html last;
  }

You can also prefix your route :

Backbone.history.start({pushState: true, root: "/prefix/"})

and then :

  location ~ ^/prefix/ {
    rewrite .* /index.html last;
  }

Or define a rule for each case.

没有你我更好 2025-01-10 14:55:26

我是这样管理的:

#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;
   }
}

I managed it like this:

#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;
   }
}
以歌曲疗慰 2025-01-10 14:55:26

对于客户端应用程序路径:

/
/foo
/foo/bar
/foo/bar/baz
/foo/bar/baz/123
/tacos
/tacos/123

使用:

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;
    }
}

虽然 @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

With client side app paths:

/
/foo
/foo/bar
/foo/bar/baz
/foo/bar/baz/123
/tacos
/tacos/123

Use:

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;
    }
}

While @Adam-Waite's answer works for the root and paths at the root level, using if within the location context is considered an antipattern, often seen when converting Apache style directives. See: http://wiki.nginx.org/IfIsEvil.

The other answers do not cover routes with directory depth for my use case in a similar React app using react-router and HTML5 pushState enabled. When a route is loaded or refreshed within a "directory" such as example.com/foo/bar/baz/213123 my index.html file will reference the js file at a relative path and resolve to example.com/foo/bar/baz/js/app.js instead of example.com/js/app.js.

For cases with directory depth beyond the first level such as /foo/bar/baz, note the order of the directories declared in the @rootfiles directive: the longest possible paths need to go first, followed by the next shallower path /foo/bar and finally /foo.

翻了热茶 2025-01-10 14:55:26

由于可能存在ajax请求api,因此以下适合这种情况,

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;
    }

    # The location block above provides the shortest prefix, of length one, 
    # and so only if all other location blocks fail to provide a match, 
    # this block will be used.

    # Ajax api starts with /v1/ will be proxied
    location /v1/ {
        proxy_pass http://proxy;
    }
}

Since there may be ajax request api, the following suits for this case,

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;
    }

    # The location block above provides the shortest prefix, of length one, 
    # and so only if all other location blocks fail to provide a match, 
    # this block will be used.

    # Ajax api starts with /v1/ will be proxied
    location /v1/ {
        proxy_pass http://proxy;
    }
}
度的依靠╰つ 2025-01-10 14:55:26

我尝试使用 try_files $uri /index.html; 但 nginx 在内部重定向到“/index.html”时不断抱怨错误重写或内部重定向循环。

我喜欢 Arthur Xu 提出的解决方案,但通过将所有没有 . 的 URL 重写为 /index.html 来简化它。

  location / {
    rewrite ^[^.]+$ /index.html last;
    proxy_pass http://web:8080;
    ...

上面将所有不带 . 的 URL 重写为 /index.htm'

I tried with try_files $uri /index.html; but nginx kept complaining with error rewrite or internal redirection cycle while internally redirecting to "/index.html".

I liked the solution Arthur Xu presented, but simplified it by rewriting all URL't that don't have a . to /index.html.

  location / {
    rewrite ^[^.]+$ /index.html last;
    proxy_pass http://web:8080;
    ...

The above rewrites all URL's without . in them to /index.htm'.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文