【玩轉Golang】beego下實現martini中的透明式靜態文件服務(static folder)效果。

  出於效率等緣由,最近將web框架由martini切換爲了beego,其餘地方都很平順,只是兩個框架的handler簽名不一致,須要修改,因此耗時較長,這是預計到的。可是有一個地方沒有預計到,也耗費了較多時間,那就是靜態文件的服務。html

  用過martini的tx都知道,在mairtini中若是咱們設置一個目錄爲靜態文件目錄,只需添加martini的Static插件,如設置web子目錄爲應用的靜態文件路徑:jquery

        m.Use(martini.Static("web"))

  此時,若是咱們訪問一個url,此url並無在martini中註冊,可是若是位於web目錄中,就能夠獲得響應,例如:git

http://127.0.0.1:8088/ 
//返回web目錄下的index.html
http://127.0.0.1:8088/ js/jquery.js
//返回web/js/jquery.js

  可是,切換爲beego以後,卻沒有找到這樣的功能。發現beego對於靜態文件的支持設計的有點不夠友好,好比我進行以下設置github

beego.SetStaticPath("/web", "web")

  這時候訪問結果以下web

http://127.0.0.1:8088/ 
//返回404頁面
http://127.0.0.1:8088/web
//返回404頁面
http://127.0.0.1:8088/web/index.html
//返回403 (Forbidden)
http://127.0.0.1:8088/web/chat.html
//返回正常
http://127.0.0.1:8088/web/images/test.png
//返回正常

  據此結果,有兩點不滿意:api

  1. 必須添加該staticdir 映射的path訪問,設置爲「/」 無效
  2. 居然不能返回默認頁面!看文檔須要設置」beego.DirectoryIndex=true「 ,不是我須要的!

  所以,我着手本身實現該需求。經過學習beego文檔,發現能夠設置Filter。因而,編寫以下代碼:app

//main中以下設置filter
beego.InsertFilter("/*", beego.BeforeRouter, TransparentStatic) .
.
. func TransparentStatic(ctx
*context.Context) { defInd := 0 maxInd := len(defHomes) - 1 orpath := ctx.Request.URL.Path beego.Debug(" in trasparentstatic filter orpath", orpath) if strings.Index(orpath, "api/") >= 0 || strings.Index(orpath, "web/") >= 0 { return } DefaultStartPage: p := orpath if strings.EqualFold(p, "/") { p += defHomes[defInd] defInd++ } ps := strings.Split(p, "/") ps = append([]string{"web"}, ps...) rp := strings.Join(ps, "/") fp := fw.MapPath(rp) beego.Debug("test fp", fp) if !fileutils.Exists(fp) { if defInd > 0 && defInd < maxInd { goto DefaultStartPage } return } else { beego.Debug("found static ", fp) http.ServeFile(ctx.ResponseWriter, ctx.Request, fp) //cannot use Redirect! will lead loop //http.Redirect(ctx.ResponseWriter, ctx.Request, rp, http.StatusFound) return } // }

  運行以後,發現訪問服務地址,帶不帶末尾的"/",都不能返回默認頁面,若是明確訪問/index.html能夠實現訪問。後經探索發現,雖然beego說明中說"/*"能夠適配全部url,可是實際上不能適配"/",所以須要在註冊一個filter到」/":框架

beego.InsertFilter("/", beego.BeforeRouter, TransparentStatic) //must has this for default page
beego.InsertFilter("/*", beego.BeforeRouter, TransparentStatic)

至此,一切正常了。oop

相關文章
相關標籤/搜索