diff --git a/context/context.go b/context/context.go
index ab3a3d3f..fee5e1c5 100644
--- a/context/context.go
+++ b/context/context.go
@@ -77,6 +77,7 @@ func (ctx *Context) Redirect(status int, localurl string) {
// Abort stops this request.
// if beego.ErrorMaps exists, panic body.
func (ctx *Context) Abort(status int, body string) {
+ ctx.Output.SetStatus(status)
panic(body)
}
diff --git a/controller.go b/controller.go
index 85894275..9d265758 100644
--- a/controller.go
+++ b/controller.go
@@ -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.
func (c *Controller) CustomAbort(status int, body string) {
- c.Ctx.Output.Status = status
// first panic from ErrorMaps, is is user defined error functions.
if _, ok := ErrorMaps[body]; ok {
+ c.Ctx.Output.Status = status
panic(body)
}
// last panic user string
+ c.Ctx.ResponseWriter.WriteHeader(status)
c.Ctx.ResponseWriter.Write([]byte(body))
panic(ErrAbort)
}
diff --git a/error.go b/error.go
index 4f48fab2..8cfa0c67 100644
--- a/error.go
+++ b/error.go
@@ -210,159 +210,139 @@ var ErrorMaps = make(map[string]*errorInfo, 10)
// show 401 unauthorized error.
func unauthorized(rw http.ResponseWriter, r *http.Request) {
- t, _ := template.New("beegoerrortemp").Parse(errtpl)
- data := map[string]interface{}{
- "Title": http.StatusText(401),
- "BeegoVersion": VERSION,
- }
- data["Content"] = template.HTML("
The page you have requested can't be authorized." +
- "
Perhaps you are here because:" +
- "
" +
- "
The credentials you supplied are incorrect" +
- "
There are errors in the website address" +
- "
")
- t.Execute(rw, data)
+ responseError(rw, r,
+ 401,
+ "
The page you have requested can't be authorized."+
+ "
Perhaps you are here because:"+
+ "
"+
+ "
The credentials you supplied are incorrect"+
+ "
There are errors in the website address"+
+ "
",
+ )
}
// show 402 Payment Required
func paymentRequired(rw http.ResponseWriter, r *http.Request) {
- t, _ := template.New("beegoerrortemp").Parse(errtpl)
- data := map[string]interface{}{
- "Title": http.StatusText(402),
- "BeegoVersion": VERSION,
- }
- data["Content"] = template.HTML("
The page you have requested Payment Required." +
- "
Perhaps you are here because:" +
- "
" +
- "
The credentials you supplied are incorrect" +
- "
There are errors in the website address" +
- "
")
- t.Execute(rw, data)
+ responseError(rw, r,
+ 402,
+ "
The page you have requested Payment Required."+
+ "
Perhaps you are here because:"+
+ "
"+
+ "
The credentials you supplied are incorrect"+
+ "
There are errors in the website address"+
+ "
",
+ )
}
// show 403 forbidden error.
func forbidden(rw http.ResponseWriter, r *http.Request) {
- t, _ := template.New("beegoerrortemp").Parse(errtpl)
- data := map[string]interface{}{
- "Title": http.StatusText(403),
- "BeegoVersion": VERSION,
- }
- data["Content"] = template.HTML("
The page you have requested is forbidden." +
- "
Perhaps you are here because:" +
- "
" +
- "
Your address may be blocked" +
- "
The site may be disabled" +
- "
You need to log in" +
- "
")
- t.Execute(rw, data)
+ responseError(rw, r,
+ 403,
+ "
The page you have requested is forbidden."+
+ "
Perhaps you are here because:"+
+ "
"+
+ "
Your address may be blocked"+
+ "
The site may be disabled"+
+ "
You need to log in"+
+ "
",
+ )
}
-// show 404 notfound error.
+// show 404 not found error.
func notFound(rw http.ResponseWriter, r *http.Request) {
- t, _ := template.New("beegoerrortemp").Parse(errtpl)
- data := map[string]interface{}{
- "Title": http.StatusText(404),
- "BeegoVersion": VERSION,
- }
- data["Content"] = template.HTML("
The page you have requested has flown the coop." +
- "
Perhaps you are here because:" +
- "
" +
- "
The page has moved" +
- "
The page no longer exists" +
- "
You were looking for your puppy and got lost" +
- "
You like 404 pages" +
- "
")
- t.Execute(rw, data)
+ responseError(rw, r,
+ 404,
+ "
The page you have requested has flown the coop."+
+ "
Perhaps you are here because:"+
+ "
"+
+ "
The page has moved"+
+ "
The page no longer exists"+
+ "
You were looking for your puppy and got lost"+
+ "
You like 404 pages"+
+ "
",
+ )
}
// show 405 Method Not Allowed
func methodNotAllowed(rw http.ResponseWriter, r *http.Request) {
- t, _ := template.New("beegoerrortemp").Parse(errtpl)
- data := map[string]interface{}{
- "Title": http.StatusText(405),
- "BeegoVersion": VERSION,
- }
- data["Content"] = template.HTML("
The method you have requested Not Allowed." +
- "
Perhaps you are here because:" +
- "
" +
- "
The method specified in the Request-Line is not allowed for the resource identified by the Request-URI" +
- "
The response MUST include an Allow header containing a list of valid methods for the requested resource." +
- "
")
- t.Execute(rw, data)
+ responseError(rw, r,
+ 405,
+ "
The method you have requested Not Allowed."+
+ "
Perhaps you are here because:"+
+ "
"+
+ "
The method specified in the Request-Line is not allowed for the resource identified by the Request-URI"+
+ "
The response MUST include an Allow header containing a list of valid methods for the requested resource."+
+ "
",
+ )
}
// show 500 internal server error.
func internalServerError(rw http.ResponseWriter, r *http.Request) {
- t, _ := template.New("beegoerrortemp").Parse(errtpl)
- data := map[string]interface{}{
- "Title": http.StatusText(500),
- "BeegoVersion": VERSION,
- }
- data["Content"] = template.HTML("
The page you have requested is down right now." +
- "
" +
- "
Please try again later and report the error to the website administrator" +
- "
")
- t.Execute(rw, data)
+ responseError(rw, r,
+ 500,
+ "
The page you have requested is down right now."+
+ "
"+
+ "
Please try again later and report the error to the website administrator"+
+ "
",
+ )
}
// show 501 Not Implemented.
func notImplemented(rw http.ResponseWriter, r *http.Request) {
- t, _ := template.New("beegoerrortemp").Parse(errtpl)
- data := map[string]interface{}{
- "Title": http.StatusText(504),
- "BeegoVersion": VERSION,
- }
- data["Content"] = template.HTML("
The page you have requested is Not Implemented." +
- "
" +
- "
Please try again later and report the error to the website administrator" +
- "
")
- t.Execute(rw, data)
+ responseError(rw, r,
+ 501,
+ "
The page you have requested is Not Implemented."+
+ "
"+
+ "
Please try again later and report the error to the website administrator"+
+ "
",
+ )
}
// show 502 Bad Gateway.
func badGateway(rw http.ResponseWriter, r *http.Request) {
- t, _ := template.New("beegoerrortemp").Parse(errtpl)
- data := map[string]interface{}{
- "Title": http.StatusText(502),
- "BeegoVersion": VERSION,
- }
- data["Content"] = template.HTML("
The page you have requested is down right now." +
- "
" +
- "
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." +
- "
Please try again later and report the error to the website administrator" +
- "
")
- t.Execute(rw, data)
+ responseError(rw, r,
+ 502,
+ "
The page you have requested is down right now."+
+ "
"+
+ "
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."+
+ "
Please try again later and report the error to the website administrator"+
+ "
",
+ )
}
// show 503 service unavailable error.
func serviceUnavailable(rw http.ResponseWriter, r *http.Request) {
- t, _ := template.New("beegoerrortemp").Parse(errtpl)
- data := map[string]interface{}{
- "Title": http.StatusText(503),
- "BeegoVersion": VERSION,
- }
- data["Content"] = template.HTML("
The page you have requested is unavailable." +
- "
Perhaps you are here because:" +
- "
" +
- "
The page is overloaded" +
- "
Please try again later." +
- "
")
- t.Execute(rw, data)
+ responseError(rw, r,
+ 503,
+ "
The page you have requested is unavailable."+
+ "
Perhaps you are here because:"+
+ "
"+
+ "
The page is overloaded"+
+ "
Please try again later."+
+ "
",
+ )
}
// show 504 Gateway Timeout.
func gatewayTimeout(rw http.ResponseWriter, r *http.Request) {
+ responseError(rw, r,
+ 504,
+ "
The page you have requested is unavailable"+
+ "
Perhaps you are here because:"+
+ "
"+
+ "
The server, while acting as a gateway or proxy, did not receive a timely response from the upstream server specified by the URI."+
+ "
Please try again later."+
+ "
",
+ )
+}
+
+func responseError(rw http.ResponseWriter, r *http.Request, errCode int, errContent string) {
t, _ := template.New("beegoerrortemp").Parse(errtpl)
data := map[string]interface{}{
- "Title": http.StatusText(504),
+ "Title": http.StatusText(errCode),
"BeegoVersion": VERSION,
+ "Content": errContent,
}
- data["Content"] = template.HTML("
The page you have requested is unavailable." +
- "
Perhaps you are here because:" +
- "
" +
- "
The server, while acting as a gateway or proxy, did not receive a timely response from the upstream server specified by the URI." +
- "
Please try again later." +
- "
")
t.Execute(rw, data)
}
@@ -408,7 +388,10 @@ func exception(errCode string, ctx *context.Context) {
if err == nil {
return v
}
- return 503
+ if ctx.Output.Status == 0 {
+ return 503
+ }
+ return ctx.Output.Status
}
for _, ec := range []string{errCode, "503", "500"} {
diff --git a/error_test.go b/error_test.go
new file mode 100644
index 00000000..f6e40c80
--- /dev/null
+++ b/error_test.go
@@ -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()
+ }
+}
diff --git a/router.go b/router.go
index 71be4c16..5516ecda 100644
--- a/router.go
+++ b/router.go
@@ -842,27 +842,26 @@ func (p *ControllerRegister) recoverPanic(context *beecontext.Context) {
}
if !BConfig.RecoverPanic {
panic(err)
- } else {
- if BConfig.EnableErrorsShow {
- if _, ok := ErrorMaps[fmt.Sprint(err)]; ok {
- exception(fmt.Sprint(err), context)
- return
- }
+ }
+ if BConfig.EnableErrorsShow {
+ if _, ok := ErrorMaps[fmt.Sprint(err)]; ok {
+ exception(fmt.Sprint(err), context)
+ return
}
- var stack string
- Critical("the request url is ", context.Input.URL())
- Critical("Handler crashed with error", err)
- for i := 1; ; i++ {
- _, file, line, ok := runtime.Caller(i)
- 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)
+ }
+ var stack string
+ Critical("the request url is ", context.Input.URL())
+ Critical("Handler crashed with error", err)
+ for i := 1; ; i++ {
+ _, file, line, ok := runtime.Caller(i)
+ 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)
}
}
}