出於效率等原因,最近將web框架由martini切換為了beego,其他地方都很平順,只是兩個框架的handler簽名不一致,需要修改,所以耗時較長,這是預計到的。但是有一個地方沒有預計到,也耗費了較多時間,那就是靜態文件的服務。
用過martini的tx都知道,在mairtini中如果我們設置一個目錄為靜態文件目錄,只需添加martini的Static插件,如設置web子目錄為應用的靜態文件路徑:
m.Use(martini.Static("web"))
此時,如果我們訪問一個url,此url並沒有在martini中注冊,但是如果位於web目錄中,就可以得到響應,例如:
http://127.0.0.1:8088/ //返回web目錄下的index.html http://127.0.0.1:8088/ js/jquery.js //返回web/js/jquery.js
但是,切換為beego之后,卻沒有找到這樣的功能。發現beego對於靜態文件的支持設計的有點不夠友好,比如我進行如下設置
beego.SetStaticPath("/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 //返回正常
據此結果,有兩點不滿意:
- 必須添加該staticdir 映射的path訪問,設置為“/” 無效
- 竟然不能返回默認頁面!看文檔需要設置”
beego.DirectoryIndex=true
“ ,不是我需要的!
因此,我着手自己實現該需求。通過學習beego文檔,發現可以設置Filter。於是,編寫如下代碼:
//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)
至此,一切正常了。