专栏首页后端技术探索记一次 Nginx URI rewrite 优化

记一次 Nginx URI rewrite 优化

1. 背景

既上一篇文章记录了组内单页引擎升级路由为 History API 方式,考虑到不支持该方式的浏览器/WebView,需要多页降级。如果不对 Nginx 进行配置,就会出现404,因为多数通过pushState得到的 URL 并没有真实对应的资源。

2. URI 形式

采用 History API 方案的 URL 格式如下:

http[s]://hostname/resource/project/page[/view]?arg1=value1

其中 resource 为资源目录,该目录下放置各个不同的项目文件夹,每个项目对应一个 project 目录。一个 project 中可能会有多个单页应用,每个单页应用对应 URL 中的一个 page。一个单页应用下的不同视图分别对应一个 view。因为采用的单页引擎支持默认路由,所以 view 并非必需。

比如 A 项目下有一个 refund 的单页应用,对应的 HTML 资源为 refund.html,为了 URL 的美观,在 URL 中去掉 html 后缀名。refund 管理两个视图 detail 和 help,且默认视图为 detail。对应该情况,URI 有以下形式:

  • /resource/A/refund
  • /resource/A/refund/detail
  • /resource/A/refund/help

其中第1个 URI 和第2个相同,只是采用了默认视图。这三种 URL 都需要 map 到 refund.html 这个实际存在的 HTML 资源。除去 map HTML 资源,还需要 map 页面请求的各种 JS 和 image 资源。这两种资源都是在页面中通过相对地址引用的,对应的 URL 分别为:

  • ./page/refund.js
  • ./img/icon.png

这两种资源 URL 和上面的 URL 资源组合起来,一共有两种形式的 URL:

  • /resource/A/(page|img)/(refund.js|icon.png)
  • /resource/A/refund/(page|img)/(refund.js|icon.png)

3. 方案

3.1 初始

项目中的实际目录结构如下:

resource_static

--resource

--A

--refund.html

--page

--refund.js

--img

--icon.png

刚开始考虑针对两种类型的资源(HTML 和其他)分别做 rewrite,这样就得到下面的匹配规则:

# match img resource
location ~* ^/resource/([\w-.]+)/([\w-.]+)/(img|page)/(.*)$ {
  rewrite ^/resource/([\w-.]+)/([\w-.]+)/(img|page)/(.*)$ /resource/$1/$3/$4 last;
}
# match HTML resource
location ~* ^/resource/([\w-.]+)/.*$ {
  rewrite ^/resource/([\w-.]+)/([\w-.]+)$ /resource/$1/$2.html last;
  rewrite ^/resource/([\w-.]+)/([\w-.]+)/([\w-.]+)$ /resource/$1/$2.html last;
}
location / {
  root /resource_static/;
  index index.html index;
}

这就是最初也是根据上一步的 URI 分类得出的最直观版本。

3.2 优化

针对3.1中的方案,可以保证新 URI 中所有情况都可以找到对应的资源。但如果单页要引入项目下一个新文件夹中的资源,这时候就要修改上述第1条配置,添加对应目录名,这样扩展性就非常差。

换个角度考虑,其实 rewrite 的目的只是为了去掉由于 URI 中 view 对应的新增虚拟目录导致静态资源寻找多了 page 这一层。所以只要去掉包含这一层的 URL 即可。考虑采用 try_files 直接实现:

location ~* ^/resource/([\w-.]+)/([\w-.]+)(/.*)?$ {
  root /resource_static/;
  try_files /resource/$1/$2/$3 /resource/$1/$3 /resource/$1/$2 /resource/$1/$2.html =404;
}

上面这条配置中,location 后对应的 URI 可以匹配上述所有静态资源的 URI,并且没有写死任何目录名称。try_files 后第1、2个参数分别用来匹配默认视图和指定视图两种 URI 下的静态资源 URI,第3、4个参数用来匹配 HTML 或其它根目录资源,最后一个参数表示如果上述都不匹配,则直接返回404。这样。该条配置同样可以匹配目录下其它子目录或多级子目录的资源匹配。本质做的事情包括两点:针对目录下的资源请求,去掉 URI 中的 page 层;针对单页,添加 html 后缀名。

Nginx 中可以实现重定向的主要有3条指令:return,rewrite 和 try_files。关于3者分别的用法和他们之间的使用场景,可以先去google,本号后面的文章中也会陆续解释。还有一点要注意的是,在[]中写特殊字符,如.时,不需要转义。

4. 总结

综上,其实还是遇到问题不能只做到满足要求即可,而是要进一步深入看有么有更好的办法来解决当前解决方案中的一些瑕疵或者缺陷。借此机会,自己也对 Nginx 配置有了进一步了解。

本文分享自微信公众号 - nginx(nginx-study),作者:zee

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-05-30

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 元宵节专门为程序员设计的灯谜

    元宵节刚过,不过专家说:今年是15的月亮16圆,猿们,考研智商和技术知识面的时刻来了,看看下面的灯谜你能搞出几个来。

    后端技术探索
  • 让nginx更安全的几点注意事项

    Nginx是当今最流行的Web服务器之一。它为世界上7%的web流量提供服务而且正在以惊人的速度增长。它是个让人惊奇的服务器,我愿意部署它。 下面是一个常见安全...

    后端技术探索
  • 常常听到的流处理是什么?

    流处理是一种允许用户在接收到的数据后的短时间内快速查询连续数据流和检测条件的技术。检测时间从几毫秒到几分钟不等。

    后端技术探索
  • Redis的Java API操作你学会了吗?(四)

    上篇文章Redis数据类型以及基本操作你知道吗?(三)给大家简单介绍以及操作了一些Redis的基本数据类型,下面这篇文章,小生主要给大家简单介绍以及操作一下Re...

    刘浩的BigDataPath
  • [javaSE] 多线程通信(等待-唤醒机制)

    两个线程操作同一个资源,比如,输入和输出,操作同一个对象,此时两个线程会争夺cpu的执行权,随机的进行切换。我们想实现先输入再输出,顺序的执行

    陶士涵
  • angular $resource模块

    讲到使用$http同服务器进行通信,但是功能上比较简单,AngularJS还提供了另外一个可选的服务$resource,使用它可以非常方便的同支持restful...

    用户5640963
  • 深究AngularJS(3)——$res

    ngResource模块是一个可选的angularjs模块,如果需要使用,我们要单独引用js

    py3study
  • Vue + Flask 实战开发系列(九)

    接着上一回分享的继续,上一篇文章已经实现了作者信息的添加和列表功能。接下来我们继续来完成剩余的编辑和删除作者信息的功能。这两个功能中,除了更新功能略微复杂一些,...

    TalkPython
  • ArcGIS Image Server简介以及OL2中的加载

    本文讲述Arcgis Image Server相关以及在OL2中如何加载Arcgis Server发布的影像服务。

    lzugis
  • QQ互联登陆(Java) - niceyoo

    腾讯开放平台网址: https://connect.qq.com/index.html

    niceyoo

扫码关注云+社区

领取腾讯云代金券