mirror of
https://github.com/astaxie/beego.git
synced 2024-11-22 12:20:54 +00:00
commit
73168d2f7d
@ -24,21 +24,84 @@ import (
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type resetWriter interface {
|
||||
io.Writer
|
||||
Reset(w io.Writer)
|
||||
}
|
||||
|
||||
type nopResetWriter struct {
|
||||
io.Writer
|
||||
}
|
||||
|
||||
func (n nopResetWriter) Reset(w io.Writer) {
|
||||
//do nothing
|
||||
}
|
||||
|
||||
type acceptEncoder struct {
|
||||
name string
|
||||
encode func(io.Writer, int) (io.Writer, error)
|
||||
name string
|
||||
levelEncode func(int) resetWriter
|
||||
bestSpeedPool *sync.Pool
|
||||
bestCompressionPool *sync.Pool
|
||||
}
|
||||
|
||||
func (ac acceptEncoder) encode(wr io.Writer, level int) resetWriter {
|
||||
if ac.bestSpeedPool == nil || ac.bestCompressionPool == nil {
|
||||
return nopResetWriter{wr}
|
||||
}
|
||||
var rwr resetWriter
|
||||
switch level {
|
||||
case flate.BestSpeed:
|
||||
rwr = ac.bestSpeedPool.Get().(resetWriter)
|
||||
case flate.BestCompression:
|
||||
rwr = ac.bestCompressionPool.Get().(resetWriter)
|
||||
default:
|
||||
rwr = ac.levelEncode(level)
|
||||
}
|
||||
rwr.Reset(wr)
|
||||
return rwr
|
||||
}
|
||||
|
||||
func (ac acceptEncoder) put(wr resetWriter, level int) {
|
||||
if ac.bestSpeedPool == nil || ac.bestCompressionPool == nil {
|
||||
return
|
||||
}
|
||||
wr.Reset(nil)
|
||||
switch level {
|
||||
case flate.BestSpeed:
|
||||
ac.bestSpeedPool.Put(wr)
|
||||
case flate.BestCompression:
|
||||
ac.bestCompressionPool.Put(wr)
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
noneCompressEncoder = acceptEncoder{"", func(wr io.Writer, level int) (io.Writer, error) { return wr, nil }}
|
||||
gzipCompressEncoder = acceptEncoder{"gzip", func(wr io.Writer, level int) (io.Writer, error) { return gzip.NewWriterLevel(wr, level) }}
|
||||
noneCompressEncoder = acceptEncoder{"", nil, nil, nil}
|
||||
gzipCompressEncoder = acceptEncoder{"gzip",
|
||||
func(level int) resetWriter { wr, _ := gzip.NewWriterLevel(nil, level); return wr },
|
||||
&sync.Pool{
|
||||
New: func() interface{} { wr, _ := gzip.NewWriterLevel(nil, flate.BestSpeed); return wr },
|
||||
},
|
||||
&sync.Pool{
|
||||
New: func() interface{} { wr, _ := gzip.NewWriterLevel(nil, flate.BestCompression); return wr },
|
||||
},
|
||||
}
|
||||
|
||||
//according to the sec :http://tools.ietf.org/html/rfc2616#section-3.5 ,the deflate compress in http is zlib indeed
|
||||
//deflate
|
||||
//The "zlib" format defined in RFC 1950 [31] in combination with
|
||||
//the "deflate" compression mechanism described in RFC 1951 [29].
|
||||
deflateCompressEncoder = acceptEncoder{"deflate", func(wr io.Writer, level int) (io.Writer, error) { return zlib.NewWriterLevel(wr, level) }}
|
||||
deflateCompressEncoder = acceptEncoder{"deflate",
|
||||
func(level int) resetWriter { wr, _ := zlib.NewWriterLevel(nil, level); return wr },
|
||||
&sync.Pool{
|
||||
New: func() interface{} { wr, _ := zlib.NewWriterLevel(nil, flate.BestSpeed); return wr },
|
||||
},
|
||||
&sync.Pool{
|
||||
New: func() interface{} { wr, _ := zlib.NewWriterLevel(nil, flate.BestCompression); return wr },
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
@ -63,7 +126,7 @@ func WriteBody(encoding string, writer io.Writer, content []byte) (bool, string,
|
||||
// writeLevel reads from reader,writes to writer by specific encoding and compress level
|
||||
// the compress level is defined by deflate package
|
||||
func writeLevel(encoding string, writer io.Writer, reader io.Reader, level int) (bool, string, error) {
|
||||
var outputWriter io.Writer
|
||||
var outputWriter resetWriter
|
||||
var err error
|
||||
var ce = noneCompressEncoder
|
||||
|
||||
@ -71,11 +134,8 @@ func writeLevel(encoding string, writer io.Writer, reader io.Reader, level int)
|
||||
ce = cf
|
||||
}
|
||||
encoding = ce.name
|
||||
outputWriter, err = ce.encode(writer, level)
|
||||
|
||||
if err != nil {
|
||||
return false, "", err
|
||||
}
|
||||
outputWriter = ce.encode(writer, level)
|
||||
defer ce.put(outputWriter, level)
|
||||
|
||||
_, err = io.Copy(outputWriter, reader)
|
||||
if err != nil {
|
||||
|
75
router.go
75
router.go
@ -391,14 +391,14 @@ func (p *ControllerRegister) AddAutoPrefix(prefix string, c ControllerInterface)
|
||||
route.controllerType = ct
|
||||
pattern := path.Join(prefix, strings.ToLower(controllerName), strings.ToLower(rt.Method(i).Name), "*")
|
||||
patternInit := path.Join(prefix, controllerName, rt.Method(i).Name, "*")
|
||||
patternfix := path.Join(prefix, strings.ToLower(controllerName), strings.ToLower(rt.Method(i).Name))
|
||||
patternfixInit := path.Join(prefix, controllerName, rt.Method(i).Name)
|
||||
patternFix := path.Join(prefix, strings.ToLower(controllerName), strings.ToLower(rt.Method(i).Name))
|
||||
patternFixInit := path.Join(prefix, controllerName, rt.Method(i).Name)
|
||||
route.pattern = pattern
|
||||
for _, m := range HTTPMETHOD {
|
||||
p.addToRouter(m, pattern, route)
|
||||
p.addToRouter(m, patternInit, route)
|
||||
p.addToRouter(m, patternfix, route)
|
||||
p.addToRouter(m, patternfixInit, route)
|
||||
p.addToRouter(m, patternFix, route)
|
||||
p.addToRouter(m, patternFixInit, route)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -504,12 +504,12 @@ func (p *ControllerRegister) geturl(t *Tree, url, controllName, methodName strin
|
||||
if find {
|
||||
if l.regexps == nil {
|
||||
if len(l.wildcards) == 0 {
|
||||
return true, strings.Replace(url, "/"+urlPlaceholder, "", 1) + tourl(params)
|
||||
return true, strings.Replace(url, "/"+urlPlaceholder, "", 1) + toUrl(params)
|
||||
}
|
||||
if len(l.wildcards) == 1 {
|
||||
if v, ok := params[l.wildcards[0]]; ok {
|
||||
delete(params, l.wildcards[0])
|
||||
return true, strings.Replace(url, urlPlaceholder, v, 1) + tourl(params)
|
||||
return true, strings.Replace(url, urlPlaceholder, v, 1) + toUrl(params)
|
||||
}
|
||||
return false, ""
|
||||
}
|
||||
@ -518,7 +518,7 @@ func (p *ControllerRegister) geturl(t *Tree, url, controllName, methodName strin
|
||||
if e, isok := params[":ext"]; isok {
|
||||
delete(params, ":path")
|
||||
delete(params, ":ext")
|
||||
return true, strings.Replace(url, urlPlaceholder, p+"."+e, -1) + tourl(params)
|
||||
return true, strings.Replace(url, urlPlaceholder, p+"."+e, -1) + toUrl(params)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -539,7 +539,7 @@ func (p *ControllerRegister) geturl(t *Tree, url, controllName, methodName strin
|
||||
return false, ""
|
||||
}
|
||||
}
|
||||
return true, url + tourl(params)
|
||||
return true, url + toUrl(params)
|
||||
}
|
||||
var i int
|
||||
var startreg bool
|
||||
@ -566,7 +566,7 @@ func (p *ControllerRegister) geturl(t *Tree, url, controllName, methodName strin
|
||||
for _, p := range ps {
|
||||
url = strings.Replace(url, urlPlaceholder, p, 1)
|
||||
}
|
||||
return true, url + tourl(params)
|
||||
return true, url + toUrl(params)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -597,10 +597,10 @@ func (p *ControllerRegister) execFilter(context *beecontext.Context, pos int, ur
|
||||
|
||||
// Implement http.Handler interface.
|
||||
func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||
starttime := time.Now()
|
||||
startTime := time.Now()
|
||||
var (
|
||||
runrouter reflect.Type
|
||||
findrouter bool
|
||||
runRouter reflect.Type
|
||||
findRouter bool
|
||||
runMethod string
|
||||
routerInfo *controllerInfo
|
||||
)
|
||||
@ -609,6 +609,8 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
||||
defer p.pool.Put(context)
|
||||
defer p.recoverPanic(context)
|
||||
|
||||
context.Output.EnableGzip=BConfig.EnableGzip
|
||||
|
||||
if BConfig.RunMode == DEV {
|
||||
context.Output.Header("Server", BConfig.ServerName)
|
||||
}
|
||||
@ -620,7 +622,7 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
||||
urlPath = r.URL.Path
|
||||
}
|
||||
|
||||
// filter wrong httpmethod
|
||||
// filter wrong http method
|
||||
if _, ok := HTTPMETHOD[r.Method]; !ok {
|
||||
http.Error(rw, "Method Not Allowed", 405)
|
||||
goto Admin
|
||||
@ -633,7 +635,7 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
||||
|
||||
serverStaticRouter(context)
|
||||
if context.ResponseWriter.Started {
|
||||
findrouter = true
|
||||
findRouter = true
|
||||
goto Admin
|
||||
}
|
||||
|
||||
@ -662,16 +664,15 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
||||
goto Admin
|
||||
}
|
||||
|
||||
if !findrouter {
|
||||
if !findRouter {
|
||||
httpMethod := r.Method
|
||||
if t, ok := p.routers[httpMethod]; ok {
|
||||
runObject := t.Match(urlPath, context)
|
||||
if r, ok := runObject.(*controllerInfo); ok {
|
||||
routerInfo = r
|
||||
findrouter = true
|
||||
findRouter = true
|
||||
if splat := context.Input.Param(":splat"); splat != "" {
|
||||
splatlist := strings.Split(splat, "/")
|
||||
for k, v := range splatlist {
|
||||
for k, v := range strings.Split(splat, "/") {
|
||||
context.Input.SetParam(strconv.Itoa(k), v)
|
||||
}
|
||||
}
|
||||
@ -681,12 +682,12 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
|
||||
//if no matches to url, throw a not found exception
|
||||
if !findrouter {
|
||||
if !findRouter {
|
||||
exception("404", context)
|
||||
goto Admin
|
||||
}
|
||||
|
||||
if findrouter {
|
||||
if findRouter {
|
||||
//execute middleware filters
|
||||
if p.execFilter(context, BeforeExec, urlPath) {
|
||||
goto Admin
|
||||
@ -705,7 +706,7 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
||||
isRunnable = true
|
||||
routerInfo.handler.ServeHTTP(rw, r)
|
||||
} else {
|
||||
runrouter = routerInfo.controllerType
|
||||
runRouter = routerInfo.controllerType
|
||||
method := r.Method
|
||||
if r.Method == "POST" && context.Input.Query("_method") == "PUT" {
|
||||
method = "PUT"
|
||||
@ -723,17 +724,17 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
}
|
||||
|
||||
// also defined runrouter & runMethod from filter
|
||||
// also defined runRouter & runMethod from filter
|
||||
if !isRunnable {
|
||||
//Invoke the request handler
|
||||
vc := reflect.New(runrouter)
|
||||
vc := reflect.New(runRouter)
|
||||
execController, ok := vc.Interface().(ControllerInterface)
|
||||
if !ok {
|
||||
panic("controller is not ControllerInterface")
|
||||
}
|
||||
|
||||
//call the controller init function
|
||||
execController.Init(context, runrouter.Name(), runMethod, vc.Interface())
|
||||
execController.Init(context, runRouter.Name(), runMethod, vc.Interface())
|
||||
|
||||
//call prepare function
|
||||
execController.Prepare()
|
||||
@ -784,7 +785,7 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
}
|
||||
|
||||
// finish all runrouter. release resource
|
||||
// finish all runRouter. release resource
|
||||
execController.Finish()
|
||||
}
|
||||
|
||||
@ -797,31 +798,31 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
||||
p.execFilter(context, FinishRouter, urlPath)
|
||||
|
||||
Admin:
|
||||
timeend := time.Since(starttime)
|
||||
timeDur := time.Since(startTime)
|
||||
//admin module record QPS
|
||||
if BConfig.Listen.AdminEnable {
|
||||
if FilterMonitorFunc(r.Method, r.URL.Path, timeend) {
|
||||
if runrouter != nil {
|
||||
go toolbox.StatisticsMap.AddStatistics(r.Method, r.URL.Path, runrouter.Name(), timeend)
|
||||
if FilterMonitorFunc(r.Method, r.URL.Path, timeDur) {
|
||||
if runRouter != nil {
|
||||
go toolbox.StatisticsMap.AddStatistics(r.Method, r.URL.Path, runRouter.Name(), timeDur)
|
||||
} else {
|
||||
go toolbox.StatisticsMap.AddStatistics(r.Method, r.URL.Path, "", timeend)
|
||||
go toolbox.StatisticsMap.AddStatistics(r.Method, r.URL.Path, "", timeDur)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if BConfig.RunMode == DEV || BConfig.Log.AccessLogs {
|
||||
var devinfo string
|
||||
if findrouter {
|
||||
var devInfo string
|
||||
if findRouter {
|
||||
if routerInfo != nil {
|
||||
devinfo = fmt.Sprintf("| % -10s | % -40s | % -16s | % -10s | % -40s |", r.Method, r.URL.Path, timeend.String(), "match", routerInfo.pattern)
|
||||
devInfo = fmt.Sprintf("| % -10s | % -40s | % -16s | % -10s | % -40s |", r.Method, r.URL.Path, timeDur.String(), "match", routerInfo.pattern)
|
||||
} else {
|
||||
devinfo = fmt.Sprintf("| % -10s | % -40s | % -16s | % -10s |", r.Method, r.URL.Path, timeend.String(), "match")
|
||||
devInfo = fmt.Sprintf("| % -10s | % -40s | % -16s | % -10s |", r.Method, r.URL.Path, timeDur.String(), "match")
|
||||
}
|
||||
} else {
|
||||
devinfo = fmt.Sprintf("| % -10s | % -40s | % -16s | % -10s |", r.Method, r.URL.Path, timeend.String(), "notmatch")
|
||||
devInfo = fmt.Sprintf("| % -10s | % -40s | % -16s | % -10s |", r.Method, r.URL.Path, timeDur.String(), "notmatch")
|
||||
}
|
||||
if DefaultAccessLogFilter == nil || !DefaultAccessLogFilter.Filter(context) {
|
||||
Debug(devinfo)
|
||||
Debug(devInfo)
|
||||
}
|
||||
}
|
||||
|
||||
@ -863,7 +864,7 @@ func (p *ControllerRegister) recoverPanic(context *beecontext.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
func tourl(params map[string]string) string {
|
||||
func toUrl(params map[string]string) string {
|
||||
if len(params) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user