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


  出於效率等原因,最近將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
//返回正常

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

  1. 必須添加該staticdir 映射的path訪問,設置為“/” 無效
  2. 竟然不能返回默認頁面!看文檔需要設置”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)

至此,一切正常了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM