1. 程式人生 > 實用技巧 >靜態檔案請求路徑 rewrite nginx && openresty 實現

靜態檔案請求路徑 rewrite nginx && openresty 實現

一個很簡單的需求,就是靜態頁面請求url 的rewrite 方便使用,類似mvc 的路由,不同的請求,對應到後邊不同的website,但是是一個地址
作用:類似一種micro frontend 的一些部分功能實現,這樣靜態web site 就有了一個統一而且靈活的入口 ,比較適合sass,或者使用者有特定
需求的場景

格式處理

  • 原有請求格式參考
    html 字尾是可選的
    http://<domain>:<port>/<subpath>/<.html?>
  • 調整為的格式
    http://:/<.html?>/
  • website 部署規則說明
    subpath的命名為/

正則規則

需求比較明確了,rewrite 我們基於正則處理,所以需要先梳理出來正則的格式
參考格式:

^(.*?)(.html)?\/(\d)$

說明 任意字元開始 .html 開頭以及結尾是可選的,同時以數字開頭的(目前只處理了一個數字的,多個也很簡單)

^(.*?)(.html)?\/(\d+)$

重寫處理使用了正則的分組匹配
格式:

/demo$3$1

基於nginx rewrite 的實現

  • 參考部署目錄結構
    說明demo1 以及demo2是我們需要部署的website,為了給使用者一個清晰,簡單的訪問入口,原有提供的格式成為內部(nginx 使用internal)
├── README.md
├── demoapps
├── 404.html
├── default
└── index.html
├── demo1
├── css1
└── index.css
├── index
├── index.html
└── js1
├── demo2
├── css2
└── index.css
├── index
├── index.html
└── js2
├── favicon.ico
└── index.html
├── docker-compose.yaml
├── nginx.conf

為了簡單使用了demo 的prefix

  • nginx 配置
    說明使用rewrite 的正則匹配,內容部分使用了openresty, rewrite 使用了last 模式的
  server {
    listen 80;
    charset utf-8;
    default_type text/html;
    location / {
      root /opt/demoapps/;
      index index.html index.htm index;
      # 不同規則的重寫(比如固定的幾個),注意last 與break 的區別
      rewrite ^(.*?)(.html)?\/(\d)$ /demo$3$1 last;
      # rewrite ^(.*?)(.html)?\/2$ /demo2$1 last;
    }
    error_page 404 /404.html;
    # 不存在預設介面
    location = /404.html {
      root /opt/demoapps/;
    }
    location /css1 {
      root /opt/demoapps/demo1;
    }
    location /css2 {
      root /opt/demoapps/demo2;
    }
    location =/favicon.ico {
      root /opt/demoapps/;
    }
    # 可以基於openresty 的處理,此處可以基於web 框架處理比如 lua-resty-route 以及lua-resty-template
    location ~* ^/demo {
      internal;
      root /opt/demoapps/;
    #   content_by_lua_block {
    #     local cjson = require("cjson.safe")
    #     local args, err = ngx.req.get_uri_args()
    #     if err == "truncated" then
    #       ngx.say(cjson.encode([[fetch error]]))
    #     end
    #     local body = {
    #       args = args,
    #       url = ngx.var.request_uri
    #     }
    #     ngx.say(cjson.encode(body))
    #   }
    }
   } 
  • 基於openresty 的配置
    通過rewrite_by_lua_block 階段處理
server {
    listen 8080;
    charset utf-8;
    default_type text/html;
    location / {
      root /opt/demoapps/;
      index index.html index.htm index;
      rewrite_by_lua_block {
        local uri,n,err = ngx.re.sub(ngx.var.uri, [[^(.*?)(.html)?\/(\d)$]], "/demo$3$1", "o")
        ngx.log(ngx.ERR,"fetch"..uri)
        local newuri = "/default"
        if n > 0 then
          newuri = uri
        end
        ngx.req.set_uri(newuri,true)
       }
    }
    location /css1 {
      root /opt/demoapps/demo1;
    }
    location /css2 {
      root /opt/demoapps/demo2;
    }
    location =/favicon.ico {
      root /opt/demoapps/;
    }
    error_page 404 /404.html;
    # 不存在預設介面
    location = /404.html {
      root /opt/demoapps/;
    }
    location /default/ {
      root /opt/demoapps/;
    }
    # 基於openresty 的處理,此處可以基於web 框架處理比如 lua-resty-route 以及lua-resty-template
    location ~* ^/demo {
      internal;
      index index.html index.htm index;
      root /opt/demoapps/;
    #   content_by_lua_block {
    #     local cjson = require("cjson.safe")
    #     local args, err = ngx.req.get_uri_args()
    #     if err == "truncated" then
    #       ngx.say(cjson.encode([[fetch error]]))
    #     end
    #     local body = {
    #       args = args,
    #       url = ngx.var.request_uri
    #     }
    #     ngx.say(cjson.encode(body))
    #   }
    }
   } 
  • docker-compose 檔案
version: "3"
services: 
 api:
  image: openresty/openresty:alpine
  volumes:
  - "./nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf"
  - "./demoapps:/opt/demoapps"
  ports:
  - "80:80"
  - "8080:8080"

效果

80 與8080的效果是一樣的
預設頁面


不同使用者的website

說明

基於nginx 的rewrite或者使用openresty 的rewrite_by_lua_block 階段,我們可以實現靜態website的動態路由能力,高效而且方便,同時實際我們
使用的過程中基於s3或者oss 等效果會更好,可以讓靜態頁面不在單一,而是具有了靈活的控制能力,比較適合複雜的website 專案而且是前後端
分離的專案

參考資料

https://github.com/rongfengliang/openresty_rewrite_static