mirror of
https://github.com/astaxie/beego.git
synced 2024-11-23 04:00:56 +00:00
commit
d3b54c46e3
2
beego.go
2
beego.go
@ -51,6 +51,7 @@ func AddAPPStartHook(hf hookfunc) {
|
|||||||
// beego.Run(":8089")
|
// beego.Run(":8089")
|
||||||
// beego.Run("127.0.0.1:8089")
|
// beego.Run("127.0.0.1:8089")
|
||||||
func Run(params ...string) {
|
func Run(params ...string) {
|
||||||
|
|
||||||
initBeforeHTTPRun()
|
initBeforeHTTPRun()
|
||||||
|
|
||||||
if len(params) > 0 && params[0] != "" {
|
if len(params) > 0 && params[0] != "" {
|
||||||
@ -74,6 +75,7 @@ func initBeforeHTTPRun() {
|
|||||||
AddAPPStartHook(registerDocs)
|
AddAPPStartHook(registerDocs)
|
||||||
AddAPPStartHook(registerTemplate)
|
AddAPPStartHook(registerTemplate)
|
||||||
AddAPPStartHook(registerAdmin)
|
AddAPPStartHook(registerAdmin)
|
||||||
|
AddAPPStartHook(registerGzip)
|
||||||
|
|
||||||
for _, hk := range hooks {
|
for _, hk := range hooks {
|
||||||
if err := hk(); err != nil {
|
if err := hk(); err != nil {
|
||||||
|
@ -353,7 +353,7 @@ func (b *beegoAppConfig) String(key string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *beegoAppConfig) Strings(key string) []string {
|
func (b *beegoAppConfig) Strings(key string) []string {
|
||||||
if v := b.innerConfig.Strings(BConfig.RunMode + "::" + key); v[0] != "" {
|
if v := b.innerConfig.Strings(BConfig.RunMode + "::" + key); len(v) > 0 {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
return b.innerConfig.Strings(key)
|
return b.innerConfig.Strings(key)
|
||||||
|
@ -27,6 +27,33 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
//Default size==20B same as nginx
|
||||||
|
defaultGzipMinLength = 20
|
||||||
|
//Content will only be compressed if content length is either unknown or greater than gzipMinLength.
|
||||||
|
gzipMinLength = defaultGzipMinLength
|
||||||
|
//The compression level used for deflate compression. (0-9).
|
||||||
|
gzipCompressLevel int
|
||||||
|
//List of HTTP methods to compress. If not set, only GET requests are compressed.
|
||||||
|
includedMethods map[string]bool
|
||||||
|
getMethodOnly bool
|
||||||
|
)
|
||||||
|
|
||||||
|
func InitGzip(minLength, compressLevel int, methods []string) {
|
||||||
|
if minLength >= 0 {
|
||||||
|
gzipMinLength = minLength
|
||||||
|
}
|
||||||
|
gzipCompressLevel = compressLevel
|
||||||
|
if gzipCompressLevel < flate.NoCompression || gzipCompressLevel > flate.BestCompression {
|
||||||
|
gzipCompressLevel = flate.BestSpeed
|
||||||
|
}
|
||||||
|
getMethodOnly = (len(methods) == 0) || (len(methods) == 1 && strings.ToUpper(methods[0]) == "GET")
|
||||||
|
includedMethods = make(map[string]bool, len(methods))
|
||||||
|
for _, v := range methods {
|
||||||
|
includedMethods[strings.ToUpper(v)] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type resetWriter interface {
|
type resetWriter interface {
|
||||||
io.Writer
|
io.Writer
|
||||||
Reset(w io.Writer)
|
Reset(w io.Writer)
|
||||||
@ -43,18 +70,18 @@ func (n nopResetWriter) Reset(w io.Writer) {
|
|||||||
type acceptEncoder struct {
|
type acceptEncoder struct {
|
||||||
name string
|
name string
|
||||||
levelEncode func(int) resetWriter
|
levelEncode func(int) resetWriter
|
||||||
bestSpeedPool *sync.Pool
|
customCompressLevelPool *sync.Pool
|
||||||
bestCompressionPool *sync.Pool
|
bestCompressionPool *sync.Pool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ac acceptEncoder) encode(wr io.Writer, level int) resetWriter {
|
func (ac acceptEncoder) encode(wr io.Writer, level int) resetWriter {
|
||||||
if ac.bestSpeedPool == nil || ac.bestCompressionPool == nil {
|
if ac.customCompressLevelPool == nil || ac.bestCompressionPool == nil {
|
||||||
return nopResetWriter{wr}
|
return nopResetWriter{wr}
|
||||||
}
|
}
|
||||||
var rwr resetWriter
|
var rwr resetWriter
|
||||||
switch level {
|
switch level {
|
||||||
case flate.BestSpeed:
|
case flate.BestSpeed:
|
||||||
rwr = ac.bestSpeedPool.Get().(resetWriter)
|
rwr = ac.customCompressLevelPool.Get().(resetWriter)
|
||||||
case flate.BestCompression:
|
case flate.BestCompression:
|
||||||
rwr = ac.bestCompressionPool.Get().(resetWriter)
|
rwr = ac.bestCompressionPool.Get().(resetWriter)
|
||||||
default:
|
default:
|
||||||
@ -65,13 +92,18 @@ func (ac acceptEncoder) encode(wr io.Writer, level int) resetWriter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ac acceptEncoder) put(wr resetWriter, level int) {
|
func (ac acceptEncoder) put(wr resetWriter, level int) {
|
||||||
if ac.bestSpeedPool == nil || ac.bestCompressionPool == nil {
|
if ac.customCompressLevelPool == nil || ac.bestCompressionPool == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
wr.Reset(nil)
|
wr.Reset(nil)
|
||||||
|
|
||||||
|
//notice
|
||||||
|
//compressionLevel==BestCompression DOES NOT MATTER
|
||||||
|
//sync.Pool will not memory leak
|
||||||
|
|
||||||
switch level {
|
switch level {
|
||||||
case flate.BestSpeed:
|
case gzipCompressLevel:
|
||||||
ac.bestSpeedPool.Put(wr)
|
ac.customCompressLevelPool.Put(wr)
|
||||||
case flate.BestCompression:
|
case flate.BestCompression:
|
||||||
ac.bestCompressionPool.Put(wr)
|
ac.bestCompressionPool.Put(wr)
|
||||||
}
|
}
|
||||||
@ -79,28 +111,22 @@ func (ac acceptEncoder) put(wr resetWriter, level int) {
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
noneCompressEncoder = acceptEncoder{"", nil, nil, nil}
|
noneCompressEncoder = acceptEncoder{"", nil, nil, nil}
|
||||||
gzipCompressEncoder = acceptEncoder{"gzip",
|
gzipCompressEncoder = acceptEncoder{
|
||||||
func(level int) resetWriter { wr, _ := gzip.NewWriterLevel(nil, level); return wr },
|
name: "gzip",
|
||||||
&sync.Pool{
|
levelEncode: func(level int) resetWriter { wr, _ := gzip.NewWriterLevel(nil, level); return wr },
|
||||||
New: func() interface{} { wr, _ := gzip.NewWriterLevel(nil, flate.BestSpeed); return wr },
|
customCompressLevelPool: &sync.Pool{New: func() interface{} { wr, _ := gzip.NewWriterLevel(nil, gzipCompressLevel); return wr }},
|
||||||
},
|
bestCompressionPool: &sync.Pool{New: func() interface{} { wr, _ := gzip.NewWriterLevel(nil, flate.BestCompression); 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",
|
deflateCompressEncoder = acceptEncoder{
|
||||||
func(level int) resetWriter { wr, _ := zlib.NewWriterLevel(nil, level); return wr },
|
name: "deflate",
|
||||||
&sync.Pool{
|
levelEncode: func(level int) resetWriter { wr, _ := zlib.NewWriterLevel(nil, level); return wr },
|
||||||
New: func() interface{} { wr, _ := zlib.NewWriterLevel(nil, flate.BestSpeed); return wr },
|
customCompressLevelPool: &sync.Pool{New: func() interface{} { wr, _ := zlib.NewWriterLevel(nil, gzipCompressLevel); return wr }},
|
||||||
},
|
bestCompressionPool: &sync.Pool{New: func() interface{} { wr, _ := zlib.NewWriterLevel(nil, flate.BestCompression); return wr }},
|
||||||
&sync.Pool{
|
|
||||||
New: func() interface{} { wr, _ := zlib.NewWriterLevel(nil, flate.BestCompression); return wr },
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -120,7 +146,11 @@ func WriteFile(encoding string, writer io.Writer, file *os.File) (bool, string,
|
|||||||
|
|
||||||
// WriteBody reads writes content to writer by the specific encoding(gzip/deflate)
|
// WriteBody reads writes content to writer by the specific encoding(gzip/deflate)
|
||||||
func WriteBody(encoding string, writer io.Writer, content []byte) (bool, string, error) {
|
func WriteBody(encoding string, writer io.Writer, content []byte) (bool, string, error) {
|
||||||
return writeLevel(encoding, writer, bytes.NewReader(content), flate.BestSpeed)
|
if encoding == "" || len(content) < gzipMinLength {
|
||||||
|
_, err := writer.Write(content)
|
||||||
|
return false, "", err
|
||||||
|
}
|
||||||
|
return writeLevel(encoding, writer, bytes.NewReader(content), gzipCompressLevel)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
@ -156,7 +186,10 @@ func ParseEncoding(r *http.Request) string {
|
|||||||
if r == nil {
|
if r == nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
if (getMethodOnly && r.Method == "GET") || includedMethods[r.Method] {
|
||||||
return parseEncoding(r)
|
return parseEncoding(r)
|
||||||
|
}
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
type q struct {
|
type q struct {
|
||||||
|
12
hooks.go
12
hooks.go
@ -6,6 +6,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/astaxie/beego/context"
|
||||||
"github.com/astaxie/beego/session"
|
"github.com/astaxie/beego/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -91,3 +92,14 @@ func registerAdmin() error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func registerGzip() error {
|
||||||
|
if BConfig.EnableGzip {
|
||||||
|
context.InitGzip(
|
||||||
|
AppConfig.DefaultInt("gzipMinLength", -1),
|
||||||
|
AppConfig.DefaultInt("gzipCompressLevel", -1),
|
||||||
|
AppConfig.DefaultStrings("includedMethods", []string{"GET"}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user