出于效率等缘由,最近将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