// Copyright 2014 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 ( "fmt" "html/template" "net/http" "reflect" "runtime" "strconv" "strings" "github.com/astaxie/beego/context" "github.com/astaxie/beego/utils" ) const ( errorTypeHandler = iota errorTypeController ) var tpl = ` beego application error
Request Method: {{.RequestMethod}}
Request URL: {{.RequestURL}}
RemoteAddr: {{.RemoteAddr }}
Stack
{{.Stack}}
` // render default application error page with error and stack string. func showErr(err interface{}, ctx *context.Context, Stack string) { t, _ := template.New("beegoerrortemp").Parse(tpl) data := make(map[string]string) data["AppError"] = AppName + ":" + fmt.Sprint(err) data["RequestMethod"] = ctx.Input.Method() data["RequestURL"] = ctx.Input.Uri() data["RemoteAddr"] = ctx.Input.IP() data["Stack"] = Stack data["BeegoVersion"] = VERSION data["GoVersion"] = runtime.Version() ctx.ResponseWriter.WriteHeader(500) t.Execute(ctx.ResponseWriter, data) } var errtpl = ` {{.Title}}
{{.Content}} Go Home

Powered by beego {{.BeegoVersion}}
` type errorInfo struct { controllerType reflect.Type handler http.HandlerFunc method string errorType int } // map of http handlers for each error string. var ErrorMaps map[string]*errorInfo func init() { ErrorMaps = make(map[string]*errorInfo) } // show 401 unauthorized error. func unauthorized(rw http.ResponseWriter, r *http.Request) { t, _ := template.New("beegoerrortemp").Parse(errtpl) data := make(map[string]interface{}) data["Title"] = "Unauthorized" data["Content"] = template.HTML("
The page you have requested can't be authorized." + "
Perhaps you are here because:" + "

") data["BeegoVersion"] = VERSION t.Execute(rw, data) } // show 402 Payment Required func paymentRequired(rw http.ResponseWriter, r *http.Request) { t, _ := template.New("beegoerrortemp").Parse(errtpl) data := make(map[string]interface{}) data["Title"] = "Payment Required" data["Content"] = template.HTML("
The page you have requested Payment Required." + "
Perhaps you are here because:" + "

") data["BeegoVersion"] = VERSION t.Execute(rw, data) } // show 403 forbidden error. func forbidden(rw http.ResponseWriter, r *http.Request) { t, _ := template.New("beegoerrortemp").Parse(errtpl) data := make(map[string]interface{}) data["Title"] = "Forbidden" data["Content"] = template.HTML("
The page you have requested is forbidden." + "
Perhaps you are here because:" + "

") data["BeegoVersion"] = VERSION t.Execute(rw, data) } // show 404 notfound error. func notFound(rw http.ResponseWriter, r *http.Request) { t, _ := template.New("beegoerrortemp").Parse(errtpl) data := make(map[string]interface{}) data["Title"] = "Page Not Found" data["Content"] = template.HTML("
The page you have requested has flown the coop." + "
Perhaps you are here because:" + "

") data["BeegoVersion"] = VERSION t.Execute(rw, data) } // show 405 Method Not Allowed func methodNotAllowed(rw http.ResponseWriter, r *http.Request) { t, _ := template.New("beegoerrortemp").Parse(errtpl) data := make(map[string]interface{}) data["Title"] = "Method Not Allowed" data["Content"] = template.HTML("
The method you have requested Not Allowed." + "
Perhaps you are here because:" + "

") data["BeegoVersion"] = VERSION t.Execute(rw, data) } // show 500 internal server error. func internalServerError(rw http.ResponseWriter, r *http.Request) { t, _ := template.New("beegoerrortemp").Parse(errtpl) data := make(map[string]interface{}) data["Title"] = "Internal Server Error" data["Content"] = template.HTML("
The page you have requested is down right now." + "

") data["BeegoVersion"] = VERSION t.Execute(rw, data) } // show 501 Not Implemented. func notImplemented(rw http.ResponseWriter, r *http.Request) { t, _ := template.New("beegoerrortemp").Parse(errtpl) data := make(map[string]interface{}) data["Title"] = "Not Implemented" data["Content"] = template.HTML("
The page you have requested is Not Implemented." + "

") data["BeegoVersion"] = VERSION t.Execute(rw, data) } // show 502 Bad Gateway. func badGateway(rw http.ResponseWriter, r *http.Request) { t, _ := template.New("beegoerrortemp").Parse(errtpl) data := make(map[string]interface{}) data["Title"] = "Bad Gateway" data["Content"] = template.HTML("
The page you have requested is down right now." + "

") data["BeegoVersion"] = VERSION t.Execute(rw, data) } // show 503 service unavailable error. func serviceUnavailable(rw http.ResponseWriter, r *http.Request) { t, _ := template.New("beegoerrortemp").Parse(errtpl) data := make(map[string]interface{}) data["Title"] = "Service Unavailable" data["Content"] = template.HTML("
The page you have requested is unavailable." + "
Perhaps you are here because:" + "

") data["BeegoVersion"] = VERSION t.Execute(rw, data) } // show 504 Gateway Timeout. func gatewayTimeout(rw http.ResponseWriter, r *http.Request) { t, _ := template.New("beegoerrortemp").Parse(errtpl) data := make(map[string]interface{}) data["Title"] = "Gateway Timeout" data["Content"] = template.HTML("
The page you have requested is unavailable." + "
Perhaps you are here because:" + "

") data["BeegoVersion"] = VERSION t.Execute(rw, data) } // register default error http handlers, 404,401,403,500 and 503. func registerDefaultErrorHandler() { if _, ok := ErrorMaps["401"]; !ok { Errorhandler("401", unauthorized) } if _, ok := ErrorMaps["402"]; !ok { Errorhandler("402", paymentRequired) } if _, ok := ErrorMaps["403"]; !ok { Errorhandler("403", forbidden) } if _, ok := ErrorMaps["404"]; !ok { Errorhandler("404", notFound) } if _, ok := ErrorMaps["405"]; !ok { Errorhandler("405", methodNotAllowed) } if _, ok := ErrorMaps["500"]; !ok { Errorhandler("500", internalServerError) } if _, ok := ErrorMaps["501"]; !ok { Errorhandler("501", notImplemented) } if _, ok := ErrorMaps["502"]; !ok { Errorhandler("502", badGateway) } if _, ok := ErrorMaps["503"]; !ok { Errorhandler("503", serviceUnavailable) } if _, ok := ErrorMaps["504"]; !ok { Errorhandler("504", gatewayTimeout) } } // ErrorHandler registers http.HandlerFunc to each http err code string. // usage: // beego.ErrorHandler("404",NotFound) // beego.ErrorHandler("500",InternalServerError) func Errorhandler(code string, h http.HandlerFunc) *App { errinfo := &errorInfo{} errinfo.errorType = errorTypeHandler errinfo.handler = h errinfo.method = code ErrorMaps[code] = errinfo return BeeApp } // ErrorController registers ControllerInterface to each http err code string. // usage: // beego.ErrorHandler(&controllers.ErrorController{}) func ErrorController(c ControllerInterface) *App { reflectVal := reflect.ValueOf(c) rt := reflectVal.Type() ct := reflect.Indirect(reflectVal).Type() for i := 0; i < rt.NumMethod(); i++ { if !utils.InSlice(rt.Method(i).Name, exceptMethod) && strings.HasPrefix(rt.Method(i).Name, "Error") { errinfo := &errorInfo{} errinfo.errorType = errorTypeController errinfo.controllerType = ct errinfo.method = rt.Method(i).Name errname := strings.TrimPrefix(rt.Method(i).Name, "Error") ErrorMaps[errname] = errinfo } } return BeeApp } // show error string as simple text message. // if error string is empty, show 500 error as default. func exception(errcode string, ctx *context.Context) { code, err := strconv.Atoi(errcode) if err != nil { code = 503 } if h, ok := ErrorMaps[errcode]; ok { executeError(h, ctx, code) return } else if h, ok := ErrorMaps["503"]; ok { executeError(h, ctx, code) return } else { ctx.ResponseWriter.WriteHeader(code) ctx.WriteString(errcode) } } func executeError(err *errorInfo, ctx *context.Context, code int) { if err.errorType == errorTypeHandler { err.handler(ctx.ResponseWriter, ctx.Request) return } if err.errorType == errorTypeController { ctx.Output.SetStatus(code) //Invoke the request handler vc := reflect.New(err.controllerType) execController, ok := vc.Interface().(ControllerInterface) if !ok { panic("controller is not ControllerInterface") } //call the controller init function execController.Init(ctx, err.controllerType.Name(), err.method, vc.Interface()) //call prepare function execController.Prepare() execController.URLMapping() in := make([]reflect.Value, 0) method := vc.MethodByName(err.method) method.Call(in) //render template if AutoRender { if err := execController.Render(); err != nil { panic(err) } } // finish all runrouter. release resource execController.Finish() } }