出於效率等緣由,最近將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
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