mirror of
https://github.com/astaxie/beego.git
synced 2024-11-26 05:21:30 +00:00
Merge pull request #1805 from JessonChan/abort_panic_bug
Abort panic bug
This commit is contained in:
commit
6c0979c314
@ -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()
|
||||||
|
}
|
||||||
|
}
|
37
router.go
37
router.go
@ -842,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