mirror of
https://github.com/astaxie/beego.git
synced 2024-11-26 12:51:29 +00:00
commit
73168d2f7d
@ -24,21 +24,84 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"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 {
|
type acceptEncoder struct {
|
||||||
name string
|
name string
|
||||||
encode func(io.Writer, int) (io.Writer, error)
|
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 (
|
var (
|
||||||
noneCompressEncoder = acceptEncoder{"", func(wr io.Writer, level int) (io.Writer, error) { return wr, nil }}
|
noneCompressEncoder = acceptEncoder{"", nil, nil, nil}
|
||||||
gzipCompressEncoder = acceptEncoder{"gzip", func(wr io.Writer, level int) (io.Writer, error) { return gzip.NewWriterLevel(wr, level) }}
|
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
|
//according to the sec :http://tools.ietf.org/html/rfc2616#section-3.5 ,the deflate compress in http is zlib indeed
|
||||||
//deflate
|
//deflate
|
||||||
//The "zlib" format defined in RFC 1950 [31] in combination with
|
//The "zlib" format defined in RFC 1950 [31] in combination with
|
||||||
//the "deflate" compression mechanism described in RFC 1951 [29].
|
//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 (
|
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
|
// writeLevel reads from reader,writes to writer by specific encoding and compress level
|
||||||
// the compress level is defined by deflate package
|
// the compress level is defined by deflate package
|
||||||
func writeLevel(encoding string, writer io.Writer, reader io.Reader, level int) (bool, string, error) {
|
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 err error
|
||||||
var ce = noneCompressEncoder
|
var ce = noneCompressEncoder
|
||||||
|
|
||||||
@ -71,11 +134,8 @@ func writeLevel(encoding string, writer io.Writer, reader io.Reader, level int)
|
|||||||
ce = cf
|
ce = cf
|
||||||
}
|
}
|
||||||
encoding = ce.name
|
encoding = ce.name
|
||||||
outputWriter, err = ce.encode(writer, level)
|
outputWriter = ce.encode(writer, level)
|
||||||
|
defer ce.put(outputWriter, level)
|
||||||
if err != nil {
|
|
||||||
return false, "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = io.Copy(outputWriter, reader)
|
_, err = io.Copy(outputWriter, reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
73
router.go
73
router.go
@ -391,14 +391,14 @@ func (p *ControllerRegister) AddAutoPrefix(prefix string, c ControllerInterface)
|
|||||||
route.controllerType = ct
|
route.controllerType = ct
|
||||||
pattern := path.Join(prefix, strings.ToLower(controllerName), strings.ToLower(rt.Method(i).Name), "*")
|
pattern := path.Join(prefix, strings.ToLower(controllerName), strings.ToLower(rt.Method(i).Name), "*")
|
||||||
patternInit := path.Join(prefix, controllerName, 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))
|
patternFix := path.Join(prefix, strings.ToLower(controllerName), strings.ToLower(rt.Method(i).Name))
|
||||||
patternfixInit := path.Join(prefix, controllerName, rt.Method(i).Name)
|
patternFixInit := path.Join(prefix, controllerName, rt.Method(i).Name)
|
||||||
route.pattern = pattern
|
route.pattern = pattern
|
||||||
for _, m := range HTTPMETHOD {
|
for _, m := range HTTPMETHOD {
|
||||||
p.addToRouter(m, pattern, route)
|
p.addToRouter(m, pattern, route)
|
||||||
p.addToRouter(m, patternInit, route)
|
p.addToRouter(m, patternInit, route)
|
||||||
p.addToRouter(m, patternfix, route)
|
p.addToRouter(m, patternFix, route)
|
||||||
p.addToRouter(m, patternfixInit, route)
|
p.addToRouter(m, patternFixInit, route)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -504,12 +504,12 @@ func (p *ControllerRegister) geturl(t *Tree, url, controllName, methodName strin
|
|||||||
if find {
|
if find {
|
||||||
if l.regexps == nil {
|
if l.regexps == nil {
|
||||||
if len(l.wildcards) == 0 {
|
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 len(l.wildcards) == 1 {
|
||||||
if v, ok := params[l.wildcards[0]]; ok {
|
if v, ok := params[l.wildcards[0]]; ok {
|
||||||
delete(params, l.wildcards[0])
|
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, ""
|
return false, ""
|
||||||
}
|
}
|
||||||
@ -518,7 +518,7 @@ func (p *ControllerRegister) geturl(t *Tree, url, controllName, methodName strin
|
|||||||
if e, isok := params[":ext"]; isok {
|
if e, isok := params[":ext"]; isok {
|
||||||
delete(params, ":path")
|
delete(params, ":path")
|
||||||
delete(params, ":ext")
|
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 false, ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true, url + tourl(params)
|
return true, url + toUrl(params)
|
||||||
}
|
}
|
||||||
var i int
|
var i int
|
||||||
var startreg bool
|
var startreg bool
|
||||||
@ -566,7 +566,7 @@ func (p *ControllerRegister) geturl(t *Tree, url, controllName, methodName strin
|
|||||||
for _, p := range ps {
|
for _, p := range ps {
|
||||||
url = strings.Replace(url, urlPlaceholder, p, 1)
|
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.
|
// Implement http.Handler interface.
|
||||||
func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||||
starttime := time.Now()
|
startTime := time.Now()
|
||||||
var (
|
var (
|
||||||
runrouter reflect.Type
|
runRouter reflect.Type
|
||||||
findrouter bool
|
findRouter bool
|
||||||
runMethod string
|
runMethod string
|
||||||
routerInfo *controllerInfo
|
routerInfo *controllerInfo
|
||||||
)
|
)
|
||||||
@ -609,6 +609,8 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
defer p.pool.Put(context)
|
defer p.pool.Put(context)
|
||||||
defer p.recoverPanic(context)
|
defer p.recoverPanic(context)
|
||||||
|
|
||||||
|
context.Output.EnableGzip=BConfig.EnableGzip
|
||||||
|
|
||||||
if BConfig.RunMode == DEV {
|
if BConfig.RunMode == DEV {
|
||||||
context.Output.Header("Server", BConfig.ServerName)
|
context.Output.Header("Server", BConfig.ServerName)
|
||||||
}
|
}
|
||||||
@ -633,7 +635,7 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
|
|
||||||
serverStaticRouter(context)
|
serverStaticRouter(context)
|
||||||
if context.ResponseWriter.Started {
|
if context.ResponseWriter.Started {
|
||||||
findrouter = true
|
findRouter = true
|
||||||
goto Admin
|
goto Admin
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -662,16 +664,15 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
goto Admin
|
goto Admin
|
||||||
}
|
}
|
||||||
|
|
||||||
if !findrouter {
|
if !findRouter {
|
||||||
httpMethod := r.Method
|
httpMethod := r.Method
|
||||||
if t, ok := p.routers[httpMethod]; ok {
|
if t, ok := p.routers[httpMethod]; ok {
|
||||||
runObject := t.Match(urlPath, context)
|
runObject := t.Match(urlPath, context)
|
||||||
if r, ok := runObject.(*controllerInfo); ok {
|
if r, ok := runObject.(*controllerInfo); ok {
|
||||||
routerInfo = r
|
routerInfo = r
|
||||||
findrouter = true
|
findRouter = true
|
||||||
if splat := context.Input.Param(":splat"); splat != "" {
|
if splat := context.Input.Param(":splat"); splat != "" {
|
||||||
splatlist := strings.Split(splat, "/")
|
for k, v := range strings.Split(splat, "/") {
|
||||||
for k, v := range splatlist {
|
|
||||||
context.Input.SetParam(strconv.Itoa(k), v)
|
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 no matches to url, throw a not found exception
|
||||||
if !findrouter {
|
if !findRouter {
|
||||||
exception("404", context)
|
exception("404", context)
|
||||||
goto Admin
|
goto Admin
|
||||||
}
|
}
|
||||||
|
|
||||||
if findrouter {
|
if findRouter {
|
||||||
//execute middleware filters
|
//execute middleware filters
|
||||||
if p.execFilter(context, BeforeExec, urlPath) {
|
if p.execFilter(context, BeforeExec, urlPath) {
|
||||||
goto Admin
|
goto Admin
|
||||||
@ -705,7 +706,7 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
isRunnable = true
|
isRunnable = true
|
||||||
routerInfo.handler.ServeHTTP(rw, r)
|
routerInfo.handler.ServeHTTP(rw, r)
|
||||||
} else {
|
} else {
|
||||||
runrouter = routerInfo.controllerType
|
runRouter = routerInfo.controllerType
|
||||||
method := r.Method
|
method := r.Method
|
||||||
if r.Method == "POST" && context.Input.Query("_method") == "PUT" {
|
if r.Method == "POST" && context.Input.Query("_method") == "PUT" {
|
||||||
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 {
|
if !isRunnable {
|
||||||
//Invoke the request handler
|
//Invoke the request handler
|
||||||
vc := reflect.New(runrouter)
|
vc := reflect.New(runRouter)
|
||||||
execController, ok := vc.Interface().(ControllerInterface)
|
execController, ok := vc.Interface().(ControllerInterface)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic("controller is not ControllerInterface")
|
panic("controller is not ControllerInterface")
|
||||||
}
|
}
|
||||||
|
|
||||||
//call the controller init function
|
//call the controller init function
|
||||||
execController.Init(context, runrouter.Name(), runMethod, vc.Interface())
|
execController.Init(context, runRouter.Name(), runMethod, vc.Interface())
|
||||||
|
|
||||||
//call prepare function
|
//call prepare function
|
||||||
execController.Prepare()
|
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()
|
execController.Finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -797,31 +798,31 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
p.execFilter(context, FinishRouter, urlPath)
|
p.execFilter(context, FinishRouter, urlPath)
|
||||||
|
|
||||||
Admin:
|
Admin:
|
||||||
timeend := time.Since(starttime)
|
timeDur := time.Since(startTime)
|
||||||
//admin module record QPS
|
//admin module record QPS
|
||||||
if BConfig.Listen.AdminEnable {
|
if BConfig.Listen.AdminEnable {
|
||||||
if FilterMonitorFunc(r.Method, r.URL.Path, timeend) {
|
if FilterMonitorFunc(r.Method, r.URL.Path, timeDur) {
|
||||||
if runrouter != nil {
|
if runRouter != nil {
|
||||||
go toolbox.StatisticsMap.AddStatistics(r.Method, r.URL.Path, runrouter.Name(), timeend)
|
go toolbox.StatisticsMap.AddStatistics(r.Method, r.URL.Path, runRouter.Name(), timeDur)
|
||||||
} else {
|
} 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 {
|
if BConfig.RunMode == DEV || BConfig.Log.AccessLogs {
|
||||||
var devinfo string
|
var devInfo string
|
||||||
if findrouter {
|
if findRouter {
|
||||||
if routerInfo != nil {
|
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 {
|
} 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 {
|
} 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) {
|
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 {
|
if len(params) == 0 {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user