From 76c0636125ad757b0e5b4ac5faf62b7eabfda7e3 Mon Sep 17 00:00:00 2001 From: Pengfei Xue Date: Tue, 26 Nov 2013 08:46:46 +0800 Subject: [PATCH] beego.Context.Abort return immediately * add common 4XX/5XX HTTP exceptions --- context/context.go | 9 +++++++++ middleware/exceptions.go | 32 ++++++++++++++++++++++++++++++++ router.go | 38 +++++++++++++++++++++----------------- 3 files changed, 62 insertions(+), 17 deletions(-) create mode 100644 middleware/exceptions.go diff --git a/context/context.go b/context/context.go index b754966c..ba7eef47 100644 --- a/context/context.go +++ b/context/context.go @@ -2,6 +2,8 @@ package context import ( "net/http" + + "github.com/astaxie/beego/middleware" ) type Context struct { @@ -19,6 +21,13 @@ func (ctx *Context) Redirect(status int, localurl string) { func (ctx *Context) Abort(status int, body string) { ctx.Output.SetStatus(status) ctx.Output.Body([]byte(body)) + + if e, ok := middleware.HTTPExceptionMaps[status]; ok { + if len(body) >= 1 { + e.Description = body + } + panic(e) + } } func (ctx *Context) WriteString(content string) { diff --git a/middleware/exceptions.go b/middleware/exceptions.go new file mode 100644 index 00000000..5bf85956 --- /dev/null +++ b/middleware/exceptions.go @@ -0,0 +1,32 @@ +package middleware + +import "fmt" + +type HTTPException struct { + StatusCode int // http status code 4xx, 5xx + Description string +} + +func (e *HTTPException) Error() string { + // return `status description`, e.g. `400 Bad Request` + return fmt.Sprintf("%d %s", e.StatusCode, e.Description) +} + +var HTTPExceptionMaps map[int]HTTPException + +func init() { + HTTPExceptionMaps = make(map[int]HTTPException) + + // Normal 4XX HTTP Status + HTTPExceptionMaps[400] = HTTPException{400, "Bad Request"} + HTTPExceptionMaps[401] = HTTPException{401, "Unauthorized"} + HTTPExceptionMaps[403] = HTTPException{403, "Forbidden"} + HTTPExceptionMaps[404] = HTTPException{404, "Not Found"} + HTTPExceptionMaps[405] = HTTPException{405, "Method Not Allowed"} + + // Normal 5XX HTTP Status + HTTPExceptionMaps[500] = HTTPException{500, "Internal Server Error"} + HTTPExceptionMaps[502] = HTTPException{502, "Bad Gateway"} + HTTPExceptionMaps[503] = HTTPException{503, "Service Unavailable"} + HTTPExceptionMaps[504] = HTTPException{504, "Gateway Timeout"} +} diff --git a/router.go b/router.go index 05465ef2..39f6b2fc 100644 --- a/router.go +++ b/router.go @@ -407,29 +407,33 @@ func (p *ControllerRegistor) UrlFor(endpoint string, values ...string) string { func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) { defer func() { if err := recover(); err != nil { - errstr := fmt.Sprint(err) - if handler, ok := middleware.ErrorMaps[errstr]; ok && ErrorsShow { - handler(rw, r) + if _, ok := err.(middleware.HTTPException); ok { + // catch intented errors, only for HTTP 4XX and 5XX } else { - if !RecoverPanic { - // go back to panic - panic(err) + errstr := fmt.Sprint(err) + if handler, ok := middleware.ErrorMaps[errstr]; ok && ErrorsShow { + handler(rw, r) } else { - var stack string - Critical("Handler crashed with error", err) - for i := 1; ; i++ { - _, file, line, ok := runtime.Caller(i) - if !ok { - break + if !RecoverPanic { + // go back to panic + panic(err) + } else { + var stack string + Critical("Handler crashed with error", err) + for i := 1; ; i++ { + _, file, line, ok := runtime.Caller(i) + if !ok { + break + } + Critical(file, line) + if RunMode == "dev" { + stack = stack + fmt.Sprintln(file, line) + } } - Critical(file, line) if RunMode == "dev" { - stack = stack + fmt.Sprintln(file, line) + middleware.ShowErr(err, rw, r, stack) } } - if RunMode == "dev" { - middleware.ShowErr(err, rw, r, stack) - } } } }