mirror of
https://github.com/astaxie/beego.git
synced 2024-11-26 13:01:29 +00:00
Merge branch 'astaxie/develop' into issue
This commit is contained in:
commit
c4276d31c5
17
.github/ISSUE_TEMPLATE
vendored
Normal file
17
.github/ISSUE_TEMPLATE
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
Please answer these questions before submitting your issue. Thanks!
|
||||||
|
|
||||||
|
1. What version of Go and beego are you using (`bee version`)?
|
||||||
|
|
||||||
|
|
||||||
|
2. What operating system and processor architecture are you using (`go env`)?
|
||||||
|
|
||||||
|
|
||||||
|
3. What did you do?
|
||||||
|
If possible, provide a recipe for reproducing the error.
|
||||||
|
A complete runnable program is good.
|
||||||
|
|
||||||
|
|
||||||
|
4. What did you expect to see?
|
||||||
|
|
||||||
|
|
||||||
|
5. What did you see instead?
|
@ -1,8 +1,7 @@
|
|||||||
language: go
|
language: go
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- tip
|
- 1.6
|
||||||
- 1.6.0
|
|
||||||
- 1.5.3
|
- 1.5.3
|
||||||
- 1.4.3
|
- 1.4.3
|
||||||
services:
|
services:
|
||||||
@ -32,12 +31,12 @@ install:
|
|||||||
- go get github.com/siddontang/ledisdb/config
|
- go get github.com/siddontang/ledisdb/config
|
||||||
- go get github.com/siddontang/ledisdb/ledis
|
- go get github.com/siddontang/ledisdb/ledis
|
||||||
- go get golang.org/x/tools/cmd/vet
|
- go get golang.org/x/tools/cmd/vet
|
||||||
- go get github.com/golang/lint/golint
|
|
||||||
- go get github.com/ssdb/gossdb/ssdb
|
- go get github.com/ssdb/gossdb/ssdb
|
||||||
before_script:
|
before_script:
|
||||||
- sh -c "if [ '$ORM_DRIVER' = 'postgres' ]; then psql -c 'create database orm_test;' -U postgres; fi"
|
- sh -c "if [ '$ORM_DRIVER' = 'postgres' ]; then psql -c 'create database orm_test;' -U postgres; fi"
|
||||||
- sh -c "if [ '$ORM_DRIVER' = 'mysql' ]; then mysql -u root -e 'create database orm_test;'; fi"
|
- sh -c "if [ '$ORM_DRIVER' = 'mysql' ]; then mysql -u root -e 'create database orm_test;'; fi"
|
||||||
- sh -c "if [ '$ORM_DRIVER' = 'sqlite' ]; then touch $TRAVIS_BUILD_DIR/orm_test.db; fi"
|
- sh -c "if [ '$ORM_DRIVER' = 'sqlite' ]; then touch $TRAVIS_BUILD_DIR/orm_test.db; fi"
|
||||||
|
- sh -c "if [ $(go version) == *1.[5-9]* ]; then go get github.com/golang/lint/golint; golint ./...; fi"
|
||||||
- mkdir -p res/var
|
- mkdir -p res/var
|
||||||
- ./ssdb/ssdb-server ./ssdb/ssdb.conf -d
|
- ./ssdb/ssdb-server ./ssdb/ssdb.conf -d
|
||||||
after_script:
|
after_script:
|
||||||
@ -45,7 +44,4 @@ after_script:
|
|||||||
- rm -rf ./res/var/*
|
- rm -rf ./res/var/*
|
||||||
script:
|
script:
|
||||||
- go vet -x ./...
|
- go vet -x ./...
|
||||||
- $HOME/gopath/bin/golint ./...
|
|
||||||
- go test -v ./...
|
- go test -v ./...
|
||||||
notifications:
|
|
||||||
webhooks: https://hooks.pubu.im/services/z7m9bvybl3rgtg9
|
|
||||||
|
2
admin.go
2
admin.go
@ -196,7 +196,7 @@ func listConf(rw http.ResponseWriter, r *http.Request) {
|
|||||||
BeforeExec: "Before Exec",
|
BeforeExec: "Before Exec",
|
||||||
AfterExec: "After Exec",
|
AfterExec: "After Exec",
|
||||||
FinishRouter: "Finish Router"} {
|
FinishRouter: "Finish Router"} {
|
||||||
if bf, ok := BeeApp.Handlers.filters[k]; ok {
|
if bf := BeeApp.Handlers.filters[k]; len(bf) > 0 {
|
||||||
filterType = fr
|
filterType = fr
|
||||||
filterTypes = append(filterTypes, filterType)
|
filterTypes = append(filterTypes, filterType)
|
||||||
resultList := new([][]string)
|
resultList := new([][]string)
|
||||||
|
3
beego.go
3
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 {
|
||||||
@ -87,5 +89,6 @@ func TestBeegoInit(ap string) {
|
|||||||
os.Setenv("BEEGO_RUNMODE", "test")
|
os.Setenv("BEEGO_RUNMODE", "test")
|
||||||
appConfigPath = filepath.Join(ap, "conf", "app.conf")
|
appConfigPath = filepath.Join(ap, "conf", "app.conf")
|
||||||
os.Chdir(ap)
|
os.Chdir(ap)
|
||||||
|
LoadAppConfig(appConfigProvider, appConfigPath)
|
||||||
initBeforeHTTPRun()
|
initBeforeHTTPRun()
|
||||||
}
|
}
|
||||||
|
@ -316,10 +316,6 @@ func LoadAppConfig(adapterName, configPath string) error {
|
|||||||
return fmt.Errorf("the target config file: %s don't exist", configPath)
|
return fmt.Errorf("the target config file: %s don't exist", configPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
if absConfigPath == appConfigPath {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
appConfigPath = absConfigPath
|
appConfigPath = absConfigPath
|
||||||
appConfigProvider = adapterName
|
appConfigProvider = adapterName
|
||||||
|
|
||||||
@ -353,7 +349,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)
|
||||||
@ -41,20 +68,20 @@ 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 ""
|
||||||
}
|
}
|
||||||
return parseEncoding(r)
|
if (getMethodOnly && r.Method == "GET") || includedMethods[r.Method] {
|
||||||
|
return parseEncoding(r)
|
||||||
|
}
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
type q struct {
|
type q struct {
|
||||||
|
@ -77,6 +77,7 @@ func (ctx *Context) Redirect(status int, localurl string) {
|
|||||||
// Abort stops this request.
|
// Abort stops this request.
|
||||||
// if beego.ErrorMaps exists, panic body.
|
// if beego.ErrorMaps exists, panic body.
|
||||||
func (ctx *Context) Abort(status int, body string) {
|
func (ctx *Context) Abort(status int, body string) {
|
||||||
|
ctx.Output.SetStatus(status)
|
||||||
panic(body)
|
panic(body)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,12 +261,13 @@ func (c *Controller) Abort(code string) {
|
|||||||
|
|
||||||
// CustomAbort stops controller handler and show the error data, it's similar Aborts, but support status code and body.
|
// CustomAbort stops controller handler and show the error data, it's similar Aborts, but support status code and body.
|
||||||
func (c *Controller) CustomAbort(status int, body string) {
|
func (c *Controller) CustomAbort(status int, body string) {
|
||||||
c.Ctx.Output.Status = status
|
|
||||||
// first panic from ErrorMaps, is is user defined error functions.
|
// first panic from ErrorMaps, is is user defined error functions.
|
||||||
if _, ok := ErrorMaps[body]; ok {
|
if _, ok := ErrorMaps[body]; ok {
|
||||||
|
c.Ctx.Output.Status = status
|
||||||
panic(body)
|
panic(body)
|
||||||
}
|
}
|
||||||
// last panic user string
|
// last panic user string
|
||||||
|
c.Ctx.ResponseWriter.WriteHeader(status)
|
||||||
c.Ctx.ResponseWriter.Write([]byte(body))
|
c.Ctx.ResponseWriter.Write([]byte(body))
|
||||||
panic(ErrAbort)
|
panic(ErrAbort)
|
||||||
}
|
}
|
||||||
|
213
error.go
213
error.go
@ -210,159 +210,139 @@ var ErrorMaps = make(map[string]*errorInfo, 10)
|
|||||||
|
|
||||||
// show 401 unauthorized error.
|
// show 401 unauthorized error.
|
||||||
func unauthorized(rw http.ResponseWriter, r *http.Request) {
|
func unauthorized(rw http.ResponseWriter, r *http.Request) {
|
||||||
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
responseError(rw, r,
|
||||||
data := map[string]interface{}{
|
401,
|
||||||
"Title": http.StatusText(401),
|
"<br>The page you have requested can't be authorized."+
|
||||||
"BeegoVersion": VERSION,
|
"<br>Perhaps you are here because:"+
|
||||||
}
|
"<br><br><ul>"+
|
||||||
data["Content"] = template.HTML("<br>The page you have requested can't be authorized." +
|
"<br>The credentials you supplied are incorrect"+
|
||||||
"<br>Perhaps you are here because:" +
|
"<br>There are errors in the website address"+
|
||||||
"<br><br><ul>" +
|
"</ul>",
|
||||||
"<br>The credentials you supplied are incorrect" +
|
)
|
||||||
"<br>There are errors in the website address" +
|
|
||||||
"</ul>")
|
|
||||||
t.Execute(rw, data)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// show 402 Payment Required
|
// show 402 Payment Required
|
||||||
func paymentRequired(rw http.ResponseWriter, r *http.Request) {
|
func paymentRequired(rw http.ResponseWriter, r *http.Request) {
|
||||||
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
responseError(rw, r,
|
||||||
data := map[string]interface{}{
|
402,
|
||||||
"Title": http.StatusText(402),
|
"<br>The page you have requested Payment Required."+
|
||||||
"BeegoVersion": VERSION,
|
"<br>Perhaps you are here because:"+
|
||||||
}
|
"<br><br><ul>"+
|
||||||
data["Content"] = template.HTML("<br>The page you have requested Payment Required." +
|
"<br>The credentials you supplied are incorrect"+
|
||||||
"<br>Perhaps you are here because:" +
|
"<br>There are errors in the website address"+
|
||||||
"<br><br><ul>" +
|
"</ul>",
|
||||||
"<br>The credentials you supplied are incorrect" +
|
)
|
||||||
"<br>There are errors in the website address" +
|
|
||||||
"</ul>")
|
|
||||||
t.Execute(rw, data)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// show 403 forbidden error.
|
// show 403 forbidden error.
|
||||||
func forbidden(rw http.ResponseWriter, r *http.Request) {
|
func forbidden(rw http.ResponseWriter, r *http.Request) {
|
||||||
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
responseError(rw, r,
|
||||||
data := map[string]interface{}{
|
403,
|
||||||
"Title": http.StatusText(403),
|
"<br>The page you have requested is forbidden."+
|
||||||
"BeegoVersion": VERSION,
|
"<br>Perhaps you are here because:"+
|
||||||
}
|
"<br><br><ul>"+
|
||||||
data["Content"] = template.HTML("<br>The page you have requested is forbidden." +
|
"<br>Your address may be blocked"+
|
||||||
"<br>Perhaps you are here because:" +
|
"<br>The site may be disabled"+
|
||||||
"<br><br><ul>" +
|
"<br>You need to log in"+
|
||||||
"<br>Your address may be blocked" +
|
"</ul>",
|
||||||
"<br>The site may be disabled" +
|
)
|
||||||
"<br>You need to log in" +
|
|
||||||
"</ul>")
|
|
||||||
t.Execute(rw, data)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// show 404 notfound error.
|
// show 404 not found error.
|
||||||
func notFound(rw http.ResponseWriter, r *http.Request) {
|
func notFound(rw http.ResponseWriter, r *http.Request) {
|
||||||
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
responseError(rw, r,
|
||||||
data := map[string]interface{}{
|
404,
|
||||||
"Title": http.StatusText(404),
|
"<br>The page you have requested has flown the coop."+
|
||||||
"BeegoVersion": VERSION,
|
"<br>Perhaps you are here because:"+
|
||||||
}
|
"<br><br><ul>"+
|
||||||
data["Content"] = template.HTML("<br>The page you have requested has flown the coop." +
|
"<br>The page has moved"+
|
||||||
"<br>Perhaps you are here because:" +
|
"<br>The page no longer exists"+
|
||||||
"<br><br><ul>" +
|
"<br>You were looking for your puppy and got lost"+
|
||||||
"<br>The page has moved" +
|
"<br>You like 404 pages"+
|
||||||
"<br>The page no longer exists" +
|
"</ul>",
|
||||||
"<br>You were looking for your puppy and got lost" +
|
)
|
||||||
"<br>You like 404 pages" +
|
|
||||||
"</ul>")
|
|
||||||
t.Execute(rw, data)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// show 405 Method Not Allowed
|
// show 405 Method Not Allowed
|
||||||
func methodNotAllowed(rw http.ResponseWriter, r *http.Request) {
|
func methodNotAllowed(rw http.ResponseWriter, r *http.Request) {
|
||||||
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
responseError(rw, r,
|
||||||
data := map[string]interface{}{
|
405,
|
||||||
"Title": http.StatusText(405),
|
"<br>The method you have requested Not Allowed."+
|
||||||
"BeegoVersion": VERSION,
|
"<br>Perhaps you are here because:"+
|
||||||
}
|
"<br><br><ul>"+
|
||||||
data["Content"] = template.HTML("<br>The method you have requested Not Allowed." +
|
"<br>The method specified in the Request-Line is not allowed for the resource identified by the Request-URI"+
|
||||||
"<br>Perhaps you are here because:" +
|
"<br>The response MUST include an Allow header containing a list of valid methods for the requested resource."+
|
||||||
"<br><br><ul>" +
|
"</ul>",
|
||||||
"<br>The method specified in the Request-Line is not allowed for the resource identified by the Request-URI" +
|
)
|
||||||
"<br>The response MUST include an Allow header containing a list of valid methods for the requested resource." +
|
|
||||||
"</ul>")
|
|
||||||
t.Execute(rw, data)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// show 500 internal server error.
|
// show 500 internal server error.
|
||||||
func internalServerError(rw http.ResponseWriter, r *http.Request) {
|
func internalServerError(rw http.ResponseWriter, r *http.Request) {
|
||||||
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
responseError(rw, r,
|
||||||
data := map[string]interface{}{
|
500,
|
||||||
"Title": http.StatusText(500),
|
"<br>The page you have requested is down right now."+
|
||||||
"BeegoVersion": VERSION,
|
"<br><br><ul>"+
|
||||||
}
|
"<br>Please try again later and report the error to the website administrator"+
|
||||||
data["Content"] = template.HTML("<br>The page you have requested is down right now." +
|
"<br></ul>",
|
||||||
"<br><br><ul>" +
|
)
|
||||||
"<br>Please try again later and report the error to the website administrator" +
|
|
||||||
"<br></ul>")
|
|
||||||
t.Execute(rw, data)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// show 501 Not Implemented.
|
// show 501 Not Implemented.
|
||||||
func notImplemented(rw http.ResponseWriter, r *http.Request) {
|
func notImplemented(rw http.ResponseWriter, r *http.Request) {
|
||||||
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
responseError(rw, r,
|
||||||
data := map[string]interface{}{
|
501,
|
||||||
"Title": http.StatusText(504),
|
"<br>The page you have requested is Not Implemented."+
|
||||||
"BeegoVersion": VERSION,
|
"<br><br><ul>"+
|
||||||
}
|
"<br>Please try again later and report the error to the website administrator"+
|
||||||
data["Content"] = template.HTML("<br>The page you have requested is Not Implemented." +
|
"<br></ul>",
|
||||||
"<br><br><ul>" +
|
)
|
||||||
"<br>Please try again later and report the error to the website administrator" +
|
|
||||||
"<br></ul>")
|
|
||||||
t.Execute(rw, data)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// show 502 Bad Gateway.
|
// show 502 Bad Gateway.
|
||||||
func badGateway(rw http.ResponseWriter, r *http.Request) {
|
func badGateway(rw http.ResponseWriter, r *http.Request) {
|
||||||
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
responseError(rw, r,
|
||||||
data := map[string]interface{}{
|
502,
|
||||||
"Title": http.StatusText(502),
|
"<br>The page you have requested is down right now."+
|
||||||
"BeegoVersion": VERSION,
|
"<br><br><ul>"+
|
||||||
}
|
"<br>The server, while acting as a gateway or proxy, received an invalid response from the upstream server it accessed in attempting to fulfill the request."+
|
||||||
data["Content"] = template.HTML("<br>The page you have requested is down right now." +
|
"<br>Please try again later and report the error to the website administrator"+
|
||||||
"<br><br><ul>" +
|
"<br></ul>",
|
||||||
"<br>The server, while acting as a gateway or proxy, received an invalid response from the upstream server it accessed in attempting to fulfill the request." +
|
)
|
||||||
"<br>Please try again later and report the error to the website administrator" +
|
|
||||||
"<br></ul>")
|
|
||||||
t.Execute(rw, data)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// show 503 service unavailable error.
|
// show 503 service unavailable error.
|
||||||
func serviceUnavailable(rw http.ResponseWriter, r *http.Request) {
|
func serviceUnavailable(rw http.ResponseWriter, r *http.Request) {
|
||||||
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
responseError(rw, r,
|
||||||
data := map[string]interface{}{
|
503,
|
||||||
"Title": http.StatusText(503),
|
"<br>The page you have requested is unavailable."+
|
||||||
"BeegoVersion": VERSION,
|
"<br>Perhaps you are here because:"+
|
||||||
}
|
"<br><br><ul>"+
|
||||||
data["Content"] = template.HTML("<br>The page you have requested is unavailable." +
|
"<br><br>The page is overloaded"+
|
||||||
"<br>Perhaps you are here because:" +
|
"<br>Please try again later."+
|
||||||
"<br><br><ul>" +
|
"</ul>",
|
||||||
"<br><br>The page is overloaded" +
|
)
|
||||||
"<br>Please try again later." +
|
|
||||||
"</ul>")
|
|
||||||
t.Execute(rw, data)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// show 504 Gateway Timeout.
|
// show 504 Gateway Timeout.
|
||||||
func gatewayTimeout(rw http.ResponseWriter, r *http.Request) {
|
func gatewayTimeout(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
responseError(rw, r,
|
||||||
|
504,
|
||||||
|
"<br>The page you have requested is unavailable"+
|
||||||
|
"<br>Perhaps you are here because:"+
|
||||||
|
"<br><br><ul>"+
|
||||||
|
"<br><br>The server, while acting as a gateway or proxy, did not receive a timely response from the upstream server specified by the URI."+
|
||||||
|
"<br>Please try again later."+
|
||||||
|
"</ul>",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func responseError(rw http.ResponseWriter, r *http.Request, errCode int, errContent string) {
|
||||||
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
||||||
data := map[string]interface{}{
|
data := map[string]interface{}{
|
||||||
"Title": http.StatusText(504),
|
"Title": http.StatusText(errCode),
|
||||||
"BeegoVersion": VERSION,
|
"BeegoVersion": VERSION,
|
||||||
|
"Content": errContent,
|
||||||
}
|
}
|
||||||
data["Content"] = template.HTML("<br>The page you have requested is unavailable." +
|
|
||||||
"<br>Perhaps you are here because:" +
|
|
||||||
"<br><br><ul>" +
|
|
||||||
"<br><br>The server, while acting as a gateway or proxy, did not receive a timely response from the upstream server specified by the URI." +
|
|
||||||
"<br>Please try again later." +
|
|
||||||
"</ul>")
|
|
||||||
t.Execute(rw, data)
|
t.Execute(rw, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -408,7 +388,10 @@ func exception(errCode string, ctx *context.Context) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
return 503
|
if ctx.Output.Status == 0 {
|
||||||
|
return 503
|
||||||
|
}
|
||||||
|
return ctx.Output.Status
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, ec := range []string{errCode, "503", "500"} {
|
for _, ec := range []string{errCode, "503", "500"} {
|
||||||
|
88
error_test.go
Normal file
88
error_test.go
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
// Copyright 2016 beego Author. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package beego
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type errorTestController struct {
|
||||||
|
Controller
|
||||||
|
}
|
||||||
|
|
||||||
|
const parseCodeError = "parse code error"
|
||||||
|
|
||||||
|
func (ec *errorTestController) Get() {
|
||||||
|
errorCode, err := ec.GetInt("code")
|
||||||
|
if err != nil {
|
||||||
|
ec.Abort(parseCodeError)
|
||||||
|
}
|
||||||
|
if errorCode != 0 {
|
||||||
|
ec.CustomAbort(errorCode, ec.GetString("code"))
|
||||||
|
}
|
||||||
|
ec.Abort("404")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestErrorCode_01(t *testing.T) {
|
||||||
|
registerDefaultErrorHandler()
|
||||||
|
for k, _ := range ErrorMaps {
|
||||||
|
r, _ := http.NewRequest("GET", "/error?code="+k, nil)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
handler := NewControllerRegister()
|
||||||
|
handler.Add("/error", &errorTestController{})
|
||||||
|
handler.ServeHTTP(w, r)
|
||||||
|
code, _ := strconv.Atoi(k)
|
||||||
|
if w.Code != code {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if !strings.Contains(string(w.Body.Bytes()), http.StatusText(code)) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestErrorCode_02(t *testing.T) {
|
||||||
|
registerDefaultErrorHandler()
|
||||||
|
r, _ := http.NewRequest("GET", "/error?code=0", nil)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
handler := NewControllerRegister()
|
||||||
|
handler.Add("/error", &errorTestController{})
|
||||||
|
handler.ServeHTTP(w, r)
|
||||||
|
if w.Code != 404 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestErrorCode_03(t *testing.T) {
|
||||||
|
registerDefaultErrorHandler()
|
||||||
|
r, _ := http.NewRequest("GET", "/error?code=panic", nil)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
handler := NewControllerRegister()
|
||||||
|
handler.Add("/error", &errorTestController{})
|
||||||
|
handler.ServeHTTP(w, r)
|
||||||
|
if w.Code != 200 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if string(w.Body.Bytes()) != parseCodeError {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
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
|
||||||
|
}
|
||||||
|
@ -44,7 +44,7 @@ func NewNamespace(prefix string, params ...LinkNamespace) *Namespace {
|
|||||||
return ns
|
return ns
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cond set condtion function
|
// Cond set condition function
|
||||||
// if cond return true can run this namespace, else can't
|
// if cond return true can run this namespace, else can't
|
||||||
// usage:
|
// usage:
|
||||||
// ns.Cond(func (ctx *context.Context) bool{
|
// ns.Cond(func (ctx *context.Context) bool{
|
||||||
@ -60,7 +60,7 @@ func (n *Namespace) Cond(cond namespaceCond) *Namespace {
|
|||||||
exception("405", ctx)
|
exception("405", ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if v, ok := n.handlers.filters[BeforeRouter]; ok {
|
if v := n.handlers.filters[BeforeRouter]; len(v) > 0 {
|
||||||
mr := new(FilterRouter)
|
mr := new(FilterRouter)
|
||||||
mr.tree = NewTree()
|
mr.tree = NewTree()
|
||||||
mr.pattern = "*"
|
mr.pattern = "*"
|
||||||
|
@ -181,7 +181,7 @@ func (d *dbBase) collectFieldValue(mi *modelInfo, fi *fieldInfo, ind reflect.Val
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
switch {
|
switch {
|
||||||
case fi.fieldType&IsPostiveIntegerField > 0:
|
case fi.fieldType&IsPositiveIntegerField > 0:
|
||||||
if field.Kind() == reflect.Ptr {
|
if field.Kind() == reflect.Ptr {
|
||||||
if field.IsNil() {
|
if field.IsNil() {
|
||||||
value = nil
|
value = nil
|
||||||
@ -516,7 +516,7 @@ func (d *dbBase) Delete(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.
|
|||||||
}
|
}
|
||||||
if num > 0 {
|
if num > 0 {
|
||||||
if mi.fields.pk.auto {
|
if mi.fields.pk.auto {
|
||||||
if mi.fields.pk.fieldType&IsPostiveIntegerField > 0 {
|
if mi.fields.pk.fieldType&IsPositiveIntegerField > 0 {
|
||||||
ind.FieldByIndex(mi.fields.pk.fieldIndex).SetUint(0)
|
ind.FieldByIndex(mi.fields.pk.fieldIndex).SetUint(0)
|
||||||
} else {
|
} else {
|
||||||
ind.FieldByIndex(mi.fields.pk.fieldIndex).SetInt(0)
|
ind.FieldByIndex(mi.fields.pk.fieldIndex).SetInt(0)
|
||||||
@ -1140,7 +1140,7 @@ setValue:
|
|||||||
tErr = err
|
tErr = err
|
||||||
goto end
|
goto end
|
||||||
}
|
}
|
||||||
if fieldType&IsPostiveIntegerField > 0 {
|
if fieldType&IsPositiveIntegerField > 0 {
|
||||||
v, _ := str.Uint64()
|
v, _ := str.Uint64()
|
||||||
value = v
|
value = v
|
||||||
} else {
|
} else {
|
||||||
@ -1292,7 +1292,7 @@ setValue:
|
|||||||
field.Set(reflect.ValueOf(&v))
|
field.Set(reflect.ValueOf(&v))
|
||||||
}
|
}
|
||||||
case fieldType&IsIntegerField > 0:
|
case fieldType&IsIntegerField > 0:
|
||||||
if fieldType&IsPostiveIntegerField > 0 {
|
if fieldType&IsPositiveIntegerField > 0 {
|
||||||
if isNative {
|
if isNative {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
value = uint64(0)
|
value = uint64(0)
|
||||||
|
@ -33,13 +33,13 @@ func getExistPk(mi *modelInfo, ind reflect.Value) (column string, value interfac
|
|||||||
fi := mi.fields.pk
|
fi := mi.fields.pk
|
||||||
|
|
||||||
v := ind.FieldByIndex(fi.fieldIndex)
|
v := ind.FieldByIndex(fi.fieldIndex)
|
||||||
if fi.fieldType&IsPostiveIntegerField > 0 {
|
if fi.fieldType&IsPositiveIntegerField > 0 {
|
||||||
vu := v.Uint()
|
vu := v.Uint()
|
||||||
exist = vu > 0
|
exist = vu > 0
|
||||||
value = vu
|
value = vu
|
||||||
} else if fi.fieldType&IsIntegerField > 0 {
|
} else if fi.fieldType&IsIntegerField > 0 {
|
||||||
vu := v.Int()
|
vu := v.Int()
|
||||||
exist = vu > 0
|
exist = true
|
||||||
value = vu
|
value = vu
|
||||||
} else {
|
} else {
|
||||||
vu := v.String()
|
vu := v.String()
|
||||||
|
@ -46,10 +46,10 @@ const (
|
|||||||
|
|
||||||
// Define some logic enum
|
// Define some logic enum
|
||||||
const (
|
const (
|
||||||
IsIntegerField = ^-TypePositiveBigIntegerField >> 4 << 5
|
IsIntegerField = ^-TypePositiveBigIntegerField >> 4 << 5
|
||||||
IsPostiveIntegerField = ^-TypePositiveBigIntegerField >> 8 << 9
|
IsPositiveIntegerField = ^-TypePositiveBigIntegerField >> 8 << 9
|
||||||
IsRelField = ^-RelReverseMany >> 14 << 15
|
IsRelField = ^-RelReverseMany >> 14 << 15
|
||||||
IsFieldType = ^-RelReverseMany<<1 + 1
|
IsFieldType = ^-RelReverseMany<<1 + 1
|
||||||
)
|
)
|
||||||
|
|
||||||
// BooleanField A true/false field.
|
// BooleanField A true/false field.
|
||||||
|
@ -387,6 +387,11 @@ func NewInLineOneToOne() *InLineOneToOne {
|
|||||||
return new(InLineOneToOne)
|
return new(InLineOneToOne)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type IntegerPk struct {
|
||||||
|
Id int64 `orm:"pk"`
|
||||||
|
Value string
|
||||||
|
}
|
||||||
|
|
||||||
var DBARGS = struct {
|
var DBARGS = struct {
|
||||||
Driver string
|
Driver string
|
||||||
Source string
|
Source string
|
||||||
|
@ -159,7 +159,7 @@ func (o *orm) Insert(md interface{}) (int64, error) {
|
|||||||
// set auto pk field
|
// set auto pk field
|
||||||
func (o *orm) setPk(mi *modelInfo, ind reflect.Value, id int64) {
|
func (o *orm) setPk(mi *modelInfo, ind reflect.Value, id int64) {
|
||||||
if mi.fields.pk.auto {
|
if mi.fields.pk.auto {
|
||||||
if mi.fields.pk.fieldType&IsPostiveIntegerField > 0 {
|
if mi.fields.pk.fieldType&IsPositiveIntegerField > 0 {
|
||||||
ind.FieldByIndex(mi.fields.pk.fieldIndex).SetUint(uint64(id))
|
ind.FieldByIndex(mi.fields.pk.fieldIndex).SetUint(uint64(id))
|
||||||
} else {
|
} else {
|
||||||
ind.FieldByIndex(mi.fields.pk.fieldIndex).SetInt(id)
|
ind.FieldByIndex(mi.fields.pk.fieldIndex).SetInt(id)
|
||||||
|
@ -50,7 +50,7 @@ func (o *insertSet) Insert(md interface{}) (int64, error) {
|
|||||||
}
|
}
|
||||||
if id > 0 {
|
if id > 0 {
|
||||||
if o.mi.fields.pk.auto {
|
if o.mi.fields.pk.auto {
|
||||||
if o.mi.fields.pk.fieldType&IsPostiveIntegerField > 0 {
|
if o.mi.fields.pk.fieldType&IsPositiveIntegerField > 0 {
|
||||||
ind.FieldByIndex(o.mi.fields.pk.fieldIndex).SetUint(uint64(id))
|
ind.FieldByIndex(o.mi.fields.pk.fieldIndex).SetUint(uint64(id))
|
||||||
} else {
|
} else {
|
||||||
ind.FieldByIndex(o.mi.fields.pk.fieldIndex).SetInt(id)
|
ind.FieldByIndex(o.mi.fields.pk.fieldIndex).SetInt(id)
|
||||||
|
@ -19,6 +19,7 @@ import (
|
|||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
@ -189,6 +190,7 @@ func TestSyncDb(t *testing.T) {
|
|||||||
RegisterModel(new(GroupPermissions))
|
RegisterModel(new(GroupPermissions))
|
||||||
RegisterModel(new(InLine))
|
RegisterModel(new(InLine))
|
||||||
RegisterModel(new(InLineOneToOne))
|
RegisterModel(new(InLineOneToOne))
|
||||||
|
RegisterModel(new(IntegerPk))
|
||||||
|
|
||||||
err := RunSyncdb("default", true, Debug)
|
err := RunSyncdb("default", true, Debug)
|
||||||
throwFail(t, err)
|
throwFail(t, err)
|
||||||
@ -210,6 +212,7 @@ func TestRegisterModels(t *testing.T) {
|
|||||||
RegisterModel(new(GroupPermissions))
|
RegisterModel(new(GroupPermissions))
|
||||||
RegisterModel(new(InLine))
|
RegisterModel(new(InLine))
|
||||||
RegisterModel(new(InLineOneToOne))
|
RegisterModel(new(InLineOneToOne))
|
||||||
|
RegisterModel(new(IntegerPk))
|
||||||
|
|
||||||
BootStrap()
|
BootStrap()
|
||||||
|
|
||||||
@ -1991,3 +1994,22 @@ func TestInLineOneToOne(t *testing.T) {
|
|||||||
throwFail(t, AssertIs(rinline.Name, name))
|
throwFail(t, AssertIs(rinline.Name, name))
|
||||||
throwFail(t, AssertIs(rinline.Email, email))
|
throwFail(t, AssertIs(rinline.Email, email))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIntegerPk(t *testing.T) {
|
||||||
|
its := []IntegerPk{
|
||||||
|
{Id: math.MinInt64, Value: "-"},
|
||||||
|
{Id: 0, Value: "0"},
|
||||||
|
{Id: math.MaxInt64, Value: "+"},
|
||||||
|
}
|
||||||
|
|
||||||
|
num, err := dORM.InsertMulti(len(its), its)
|
||||||
|
throwFail(t, err)
|
||||||
|
throwFail(t, AssertIs(num, len(its)))
|
||||||
|
|
||||||
|
for _, intPk := range its {
|
||||||
|
out := IntegerPk{Id: intPk.Id}
|
||||||
|
err = dORM.Read(&out)
|
||||||
|
throwFail(t, err)
|
||||||
|
throwFail(t, AssertIs(out.Value, intPk.Value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
97
router.go
97
router.go
@ -114,7 +114,7 @@ type controllerInfo struct {
|
|||||||
type ControllerRegister struct {
|
type ControllerRegister struct {
|
||||||
routers map[string]*Tree
|
routers map[string]*Tree
|
||||||
enableFilter bool
|
enableFilter bool
|
||||||
filters map[int][]*FilterRouter
|
filters [FinishRouter + 1][]*FilterRouter
|
||||||
pool sync.Pool
|
pool sync.Pool
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +122,6 @@ type ControllerRegister struct {
|
|||||||
func NewControllerRegister() *ControllerRegister {
|
func NewControllerRegister() *ControllerRegister {
|
||||||
cr := &ControllerRegister{
|
cr := &ControllerRegister{
|
||||||
routers: make(map[string]*Tree),
|
routers: make(map[string]*Tree),
|
||||||
filters: make(map[int][]*FilterRouter),
|
|
||||||
}
|
}
|
||||||
cr.pool.New = func() interface{} {
|
cr.pool.New = func() interface{} {
|
||||||
return beecontext.NewContext()
|
return beecontext.NewContext()
|
||||||
@ -408,7 +407,6 @@ func (p *ControllerRegister) AddAutoPrefix(prefix string, c ControllerInterface)
|
|||||||
// InsertFilter Add a FilterFunc with pattern rule and action constant.
|
// InsertFilter Add a FilterFunc with pattern rule and action constant.
|
||||||
// The bool params is for setting the returnOnOutput value (false allows multiple filters to execute)
|
// The bool params is for setting the returnOnOutput value (false allows multiple filters to execute)
|
||||||
func (p *ControllerRegister) InsertFilter(pattern string, pos int, filter FilterFunc, params ...bool) error {
|
func (p *ControllerRegister) InsertFilter(pattern string, pos int, filter FilterFunc, params ...bool) error {
|
||||||
|
|
||||||
mr := new(FilterRouter)
|
mr := new(FilterRouter)
|
||||||
mr.tree = NewTree()
|
mr.tree = NewTree()
|
||||||
mr.pattern = pattern
|
mr.pattern = pattern
|
||||||
@ -426,9 +424,13 @@ func (p *ControllerRegister) InsertFilter(pattern string, pos int, filter Filter
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add Filter into
|
// add Filter into
|
||||||
func (p *ControllerRegister) insertFilterRouter(pos int, mr *FilterRouter) error {
|
func (p *ControllerRegister) insertFilterRouter(pos int, mr *FilterRouter) (err error) {
|
||||||
p.filters[pos] = append(p.filters[pos], mr)
|
if pos < BeforeStatic || pos > FinishRouter {
|
||||||
|
err = fmt.Errorf("can not find your filter postion")
|
||||||
|
return
|
||||||
|
}
|
||||||
p.enableFilter = true
|
p.enableFilter = true
|
||||||
|
p.filters[pos] = append(p.filters[pos], mr)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -577,20 +579,16 @@ func (p *ControllerRegister) geturl(t *Tree, url, controllName, methodName strin
|
|||||||
return false, ""
|
return false, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ControllerRegister) execFilter(context *beecontext.Context, pos int, urlPath string) (started bool) {
|
func (p *ControllerRegister) execFilter(context *beecontext.Context, urlPath string, pos int) (started bool) {
|
||||||
if p.enableFilter {
|
for _, filterR := range p.filters[pos] {
|
||||||
if l, ok := p.filters[pos]; ok {
|
if filterR.returnOnOutput && context.ResponseWriter.Started {
|
||||||
for _, filterR := range l {
|
return true
|
||||||
if filterR.returnOnOutput && context.ResponseWriter.Started {
|
}
|
||||||
return true
|
if ok := filterR.ValidRouter(urlPath, context); ok {
|
||||||
}
|
filterR.filterFunc(context)
|
||||||
if ok := filterR.ValidRouter(urlPath, context); ok {
|
}
|
||||||
filterR.filterFunc(context)
|
if filterR.returnOnOutput && context.ResponseWriter.Started {
|
||||||
}
|
return true
|
||||||
if filterR.returnOnOutput && context.ResponseWriter.Started {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@ -617,11 +615,10 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
context.Output.Header("Server", BConfig.ServerName)
|
context.Output.Header("Server", BConfig.ServerName)
|
||||||
}
|
}
|
||||||
|
|
||||||
var urlPath string
|
var urlPath = r.URL.Path
|
||||||
|
|
||||||
if !BConfig.RouterCaseSensitive {
|
if !BConfig.RouterCaseSensitive {
|
||||||
urlPath = strings.ToLower(r.URL.Path)
|
urlPath = strings.ToLower(urlPath)
|
||||||
} else {
|
|
||||||
urlPath = r.URL.Path
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// filter wrong http method
|
// filter wrong http method
|
||||||
@ -631,11 +628,12 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// filter for static file
|
// filter for static file
|
||||||
if p.execFilter(context, BeforeStatic, urlPath) {
|
if len(p.filters[BeforeStatic]) > 0 && p.execFilter(context, urlPath, BeforeStatic) {
|
||||||
goto Admin
|
goto Admin
|
||||||
}
|
}
|
||||||
|
|
||||||
serverStaticRouter(context)
|
serverStaticRouter(context)
|
||||||
|
|
||||||
if context.ResponseWriter.Started {
|
if context.ResponseWriter.Started {
|
||||||
findRouter = true
|
findRouter = true
|
||||||
goto Admin
|
goto Admin
|
||||||
@ -655,7 +653,7 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
Error(err)
|
Error(err)
|
||||||
exception("503", context)
|
exception("503", context)
|
||||||
return
|
goto Admin
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if context.Input.CruSession != nil {
|
if context.Input.CruSession != nil {
|
||||||
@ -663,8 +661,7 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
if len(p.filters[BeforeRouter]) > 0 && p.execFilter(context, urlPath, BeforeRouter) {
|
||||||
if p.execFilter(context, BeforeRouter, urlPath) {
|
|
||||||
goto Admin
|
goto Admin
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -693,7 +690,7 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
|
|
||||||
if findRouter {
|
if findRouter {
|
||||||
//execute middleware filters
|
//execute middleware filters
|
||||||
if p.execFilter(context, BeforeExec, urlPath) {
|
if len(p.filters[BeforeExec]) > 0 && p.execFilter(context, urlPath, BeforeExec) {
|
||||||
goto Admin
|
goto Admin
|
||||||
}
|
}
|
||||||
isRunnable := false
|
isRunnable := false
|
||||||
@ -794,12 +791,13 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//execute middleware filters
|
//execute middleware filters
|
||||||
if p.execFilter(context, AfterExec, urlPath) {
|
if len(p.filters[AfterExec]) > 0 && p.execFilter(context, urlPath, AfterExec) {
|
||||||
goto Admin
|
goto Admin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if len(p.filters[FinishRouter]) > 0 && p.execFilter(context, urlPath, FinishRouter) {
|
||||||
p.execFilter(context, FinishRouter, urlPath)
|
goto Admin
|
||||||
|
}
|
||||||
|
|
||||||
Admin:
|
Admin:
|
||||||
//admin module record QPS
|
//admin module record QPS
|
||||||
@ -844,27 +842,26 @@ func (p *ControllerRegister) recoverPanic(context *beecontext.Context) {
|
|||||||
}
|
}
|
||||||
if !BConfig.RecoverPanic {
|
if !BConfig.RecoverPanic {
|
||||||
panic(err)
|
panic(err)
|
||||||
} else {
|
}
|
||||||
if BConfig.EnableErrorsShow {
|
if BConfig.EnableErrorsShow {
|
||||||
if _, ok := ErrorMaps[fmt.Sprint(err)]; ok {
|
if _, ok := ErrorMaps[fmt.Sprint(err)]; ok {
|
||||||
exception(fmt.Sprint(err), context)
|
exception(fmt.Sprint(err), context)
|
||||||
return
|
return
|
||||||
}
|
|
||||||
}
|
}
|
||||||
var stack string
|
}
|
||||||
Critical("the request url is ", context.Input.URL())
|
var stack string
|
||||||
Critical("Handler crashed with error", err)
|
Critical("the request url is ", context.Input.URL())
|
||||||
for i := 1; ; i++ {
|
Critical("Handler crashed with error", err)
|
||||||
_, file, line, ok := runtime.Caller(i)
|
for i := 1; ; i++ {
|
||||||
if !ok {
|
_, file, line, ok := runtime.Caller(i)
|
||||||
break
|
if !ok {
|
||||||
}
|
break
|
||||||
Critical(fmt.Sprintf("%s:%d", file, line))
|
|
||||||
stack = stack + fmt.Sprintln(fmt.Sprintf("%s:%d", file, line))
|
|
||||||
}
|
|
||||||
if BConfig.RunMode == DEV {
|
|
||||||
showErr(err, context, stack)
|
|
||||||
}
|
}
|
||||||
|
Critical(fmt.Sprintf("%s:%d", file, line))
|
||||||
|
stack = stack + fmt.Sprintln(fmt.Sprintf("%s:%d", file, line))
|
||||||
|
}
|
||||||
|
if BConfig.RunMode == DEV {
|
||||||
|
showErr(err, context, stack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user