【问题标题】:Serve multiple versions of multiple Single Page Applications from one nginx server?从一台 nginx 服务器提供多个单页应用程序的多个版本?
【发布时间】:2020-06-04 10:53:44
【问题描述】:

我需要从一台服务器提供多个单页应用程序 (SPA) 的多个版本。

如果 URL 指定的版本在服务器上不存在,我想提供一个备用版本。

有些版本实际上是其他版本的符号链接。

# /var/www/apps/example-app
0.1.0
0.1.1
0.1.2
fooversion -> /var/www/apps/example-spa/0.1.2
latest -> /var/www/apps/example-spa/0.1.1

latest 版本是我想用作后备的版本。

所有 SPA 都有一个 index.html 文件。

我特别不想同时提供来自不同版本的文件。如果服务器上存在某个版本,则应从该文件夹提供对该版本的所有请求。

# excerpt from nginx config
...

location ~ ^/apps/(?<appname>.+?)/(?<appversion>.+?)/(?<suffix>.*)
{
    # 'latest' is the name of the folder with the fallback version
    set $effectiveversion latest;

    # NOTE: file check does not take into account `root` directive, use full path
    if (-f /var/www/apps/$appname/$appversion/index.html) {
        set $effectiveversion $appversion;
    }

    # try path, then force to SPA index
    try_files /apps/$appname/$effectiveversion/$suffix /apps/$appname/$effectiveversion/index.html;
}

# catch requests that end without a trailing slash
location ~ ^/apps/(?<appname>.+?)/(?<appversion>[^\/]+)$
{
    try_files /NONEXISTENTFILE /apps/$appname/$appversion/;
}

...

我知道if 可能是个问题,因为它在 nginx 配置中享有盛誉。

(注意:后缀是指版本之后的斜线之后的任何内容,因此/file.extension/some/folder/that/does/notexist/ 都是后缀。如果文件存在,则应提供文件,并且所有子文件夹都应提供版本的index.html .

此代码目前适用于以下网址:

https://example.com/apps/bar-app/nonexistentversion/nonexistentsuffix
https://example.com/apps/bar-app/nonexistentversion/nonexistentsuffix/
https://example.com/apps/bar-app/nonexistentversion
https://example.com/apps/bar-app/nonexistentversion/
https://example.com/apps/bar-app/nonexistentversion/existentsuffix
https://example.com/apps/bar-app/existentversion/existentsuffix
https://example.com/apps/bar-app/existentversion/
https://example.com/apps/bar-app/existentversion

但它不适用于这些:

https://example.com/apps/bar-app/existentversion/nonexistentsuffix
https://example.com/apps/bar-app/existentversion/nonexistentsuffix/

目前这最后两个返回 404。

==> /var/log/nginx/error.log <==
2020/06/03 14:23:15 [error] 7100#7100: *1289803 open() "/var/www/apps/example-app/fooversion/somefrontendroute" failed (2: No such file or directory), client: ..., server: , request: "GET /apps/example-app/fooversion/somefrontendroute HTTP/1.1", host: "static.bar.com", referrer: ...

==> /var/log/nginx/access.log <==
[03/Jun/2020:14:23:15 +1000] ... - "GET /apps/example-app/fooversion/somefrontendroute HTTP/1.1" 404 209 - 0.000 - - - 1591158195.572 -"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36" "..., ..."

有没有办法解决这最后几个案例?或者甚至是一种更简洁的方式来处理整个问题?

工作解决方案:

(99% 理查德·史密斯的回答,我只是添加了重写)

# cover case where version has no trailing `/`
rewrite ^/apps/([^/]+?)/([^/]+)$ /apps/$1/$2/;

location ~ ^/apps/(?<app>.+?)/(?<version>.+?)/(?<rest>.*)$
{
  try_files
    /apps/$app/$version/$rest
    /apps/$app/$version/index.html
    /apps/$app/latest/$rest
    /apps/$app/latest/index.html
  ;
}

如果 URI 不存在,它将提供索引而不是 404。这对我来说是可以接受的

【问题讨论】:

    标签: nginx single-page-application nginx-config


    【解决方案1】:

    您可能可以删除if 块,因为try_files 指令实际上与if (-f 相同。

    try_files 语句的最后一个参数不是文件 术语。通过在语句末尾添加=404,您的最后一个参数将成为常规file 术语,这可能是您的问题案例的根本原因。

    详情请见this document

    例如:

    location ~ ^/apps/(?<appname>.+?)/(?<appversion>.+?)/(?<suffix>.*)$
    {
        try_files 
            $uri
            /apps/$appname/$appversion/index.html
            /apps/$appname/latest/$suffix 
            /apps/$appname/latest/index.html
            =404
        ;
    }
    

    【讨论】:

      猜你喜欢
      • 2018-06-16
      • 2019-01-13
      • 1970-01-01
      • 2019-07-19
      • 1970-01-01
      • 2019-10-29
      • 1970-01-01
      • 2021-10-01
      • 1970-01-01
      相关资源
      最近更新 更多