Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
B
beego
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
beego
Commits
3aceaf88
Commit
3aceaf88
authored
Feb 26, 2015
by
astaxie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
error support controller
parent
71b9854f
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
136 additions
and
139 deletions
+136
-139
beego.go
beego.go
+1
-13
config.go
config.go
+1
-0
context.go
context/context.go
+4
-12
error.go
error.go
+111
-38
exceptions.go
middleware/exceptions.go
+0
-49
namespace.go
namespace.go
+1
-2
router.go
router.go
+17
-23
staticfile.go
staticfile.go
+1
-2
No files found.
beego.go
View file @
3aceaf88
...
...
@@ -33,7 +33,6 @@ import (
"strconv"
"strings"
"github.com/astaxie/beego/middleware"
"github.com/astaxie/beego/session"
)
...
...
@@ -280,15 +279,6 @@ func Handler(rootpath string, h http.Handler, options ...interface{}) *App {
return
BeeApp
}
// ErrorHandler registers http.HandlerFunc to each http err code string.
// usage:
// beego.ErrorHandler("404",NotFound)
// beego.ErrorHandler("500",InternalServerError)
func
Errorhandler
(
err
string
,
h
http
.
HandlerFunc
)
*
App
{
middleware
.
Errorhandler
(
err
,
h
)
return
BeeApp
}
// SetViewsPath sets view directory path in beego application.
func
SetViewsPath
(
path
string
)
*
App
{
ViewsPath
=
path
...
...
@@ -402,9 +392,7 @@ func initBeforeHttpRun() {
}
}
middleware
.
VERSION
=
VERSION
middleware
.
AppName
=
AppName
middleware
.
RegisterErrorHandler
()
registerDefaultErrorHandler
()
if
EnableDocs
{
Get
(
"/docs"
,
serverDocs
)
...
...
config.go
View file @
3aceaf88
...
...
@@ -81,6 +81,7 @@ var (
AppConfigProvider
string
// config provider
EnableDocs
bool
// enable generate docs & server docs API Swagger
RouterCaseSensitive
bool
// router case sensitive default is true
AccessLogs
bool
// print access logs, default is false
)
type
beegoAppConfig
struct
{
...
...
context/context.go
View file @
3aceaf88
...
...
@@ -31,7 +31,7 @@ import (
"strings"
"time"
"github.com/astaxie/beego
/middleware
"
"github.com/astaxie/beego"
"github.com/astaxie/beego/utils"
)
...
...
@@ -53,24 +53,16 @@ func (ctx *Context) Redirect(status int, localurl string) {
}
// Abort stops this request.
// if middleware.ErrorMaps exists, panic body.
// if middleware.HTTPExceptionMaps exists, panic HTTPException struct with status and body string.
// if beego.ErrorMaps exists, panic body.
func
(
ctx
*
Context
)
Abort
(
status
int
,
body
string
)
{
ctx
.
ResponseWriter
.
WriteHeader
(
status
)
// first panic from ErrorMaps, is is user defined error functions.
if
_
,
ok
:=
middleware
.
ErrorMaps
[
body
];
ok
{
if
_
,
ok
:=
beego
.
ErrorMaps
[
body
];
ok
{
panic
(
body
)
}
// second panic from HTTPExceptionMaps, it is system defined functions.
if
e
,
ok
:=
middleware
.
HTTPExceptionMaps
[
status
];
ok
{
if
len
(
body
)
>=
1
{
e
.
Description
=
body
}
panic
(
e
)
}
// last panic user string
ctx
.
ResponseWriter
.
Write
([]
byte
(
body
))
panic
(
"User stop run"
)
panic
(
beego
.
USERSTOPRUN
)
}
// Write string to response body.
...
...
middleware/
error.go
→
error.go
View file @
3aceaf88
...
...
@@ -12,20 +12,26 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package
middleware
package
beego
import
(
"fmt"
"html/template"
"net/http"
"reflect"
"runtime"
"strconv"
"strings"
"github.com/astaxie/beego/context"
"github.com/astaxie/beego/utils"
)
var
(
AppName
string
VERSION
string
const
(
errorTypeHandler
=
iota
errorTypeController
)
var
tpl
=
`
<!DOCTYPE html>
<html>
...
...
@@ -76,18 +82,18 @@ var tpl = `
`
// render default application error page with error and stack string.
func
ShowErr
(
err
interface
{},
rw
http
.
ResponseWriter
,
r
*
http
.
Reques
t
,
Stack
string
)
{
func
showErr
(
err
interface
{},
ctx
*
context
.
Contex
t
,
Stack
string
)
{
t
,
_
:=
template
.
New
(
"beegoerrortemp"
)
.
Parse
(
tpl
)
data
:=
make
(
map
[
string
]
string
)
data
[
"AppError"
]
=
AppName
+
":"
+
fmt
.
Sprint
(
err
)
data
[
"RequestMethod"
]
=
r
.
Method
data
[
"RequestURL"
]
=
r
.
RequestURI
data
[
"RemoteAddr"
]
=
r
.
RemoteAddr
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
()
rw
.
WriteHeader
(
500
)
t
.
Execute
(
rw
,
data
)
ctx
.
Output
.
SetStatus
(
500
)
t
.
Execute
(
ctx
.
ResponseWriter
,
data
)
}
var
errtpl
=
`
...
...
@@ -190,11 +196,18 @@ var errtpl = `
</html>
`
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
]
http
.
HandlerFunc
var
ErrorMaps
map
[
string
]
*
errorInfo
func
init
()
{
ErrorMaps
=
make
(
map
[
string
]
http
.
HandlerFunc
)
ErrorMaps
=
make
(
map
[
string
]
*
errorInfo
)
}
// show 404 notfound error.
...
...
@@ -283,55 +296,115 @@ func SimpleServerError(rw http.ResponseWriter, r *http.Request) {
http
.
Error
(
rw
,
http
.
StatusText
(
http
.
StatusInternalServerError
),
http
.
StatusInternalServerError
)
}
// add http handler for given error string.
func
Errorhandler
(
err
string
,
h
http
.
HandlerFunc
)
{
ErrorMaps
[
err
]
=
h
}
// register default error http handlers, 404,401,403,500 and 503.
func
Register
ErrorHandler
()
{
func
registerDefault
ErrorHandler
()
{
if
_
,
ok
:=
ErrorMaps
[
"404"
];
!
ok
{
Error
Maps
[
"404"
]
=
NotFound
Error
handler
(
"404"
,
NotFound
)
}
if
_
,
ok
:=
ErrorMaps
[
"401"
];
!
ok
{
Error
Maps
[
"401"
]
=
Unauthorized
Error
handler
(
"401"
,
Unauthorized
)
}
if
_
,
ok
:=
ErrorMaps
[
"403"
];
!
ok
{
Error
Maps
[
"403"
]
=
Forbidden
Error
handler
(
"403"
,
Forbidden
)
}
if
_
,
ok
:=
ErrorMaps
[
"503"
];
!
ok
{
Error
Maps
[
"503"
]
=
ServiceUnavailable
Error
handler
(
"503"
,
ServiceUnavailable
)
}
if
_
,
ok
:=
ErrorMaps
[
"500"
];
!
ok
{
Error
Maps
[
"500"
]
=
InternalServerError
Error
handler
(
"500"
,
InternalServerError
)
}
}
// 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
,
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
msg
string
)
{
if
h
,
ok
:=
ErrorMaps
[
errcode
];
ok
{
isint
,
err
:=
strconv
.
Atoi
(
errcode
)
func
exception
(
errcode
string
,
ctx
*
context
.
Context
)
{
code
,
err
:=
strconv
.
Atoi
(
errcode
)
if
err
!=
nil
{
isint
=
500
code
=
503
}
w
.
Header
()
.
Set
(
"Content-Type"
,
"text/html; charset=utf-8"
)
w
.
WriteHeader
(
isint
)
h
(
w
,
r
)
ctx
.
ResponseWriter
.
WriteHeader
(
code
)
if
h
,
ok
:=
ErrorMaps
[
errcode
];
ok
{
executeError
(
h
,
ctx
)
return
}
else
if
h
,
ok
:=
ErrorMaps
[
"503"
];
ok
{
executeError
(
h
,
ctx
)
return
}
else
{
ctx
.
WriteString
(
errcode
)
}
isint
,
err
:=
strconv
.
Atoi
(
errcode
)
if
err
!=
nil
{
isint
=
500
}
func
executeError
(
err
*
errorInfo
,
ctx
*
context
.
Context
)
{
if
err
.
errorType
==
errorTypeHandler
{
err
.
handler
(
ctx
.
ResponseWriter
,
ctx
.
Request
)
return
}
if
err
.
errorType
==
errorTypeController
{
//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
ctx
.
Output
.
Status
==
0
{
if
AutoRender
{
if
err
:=
execController
.
Render
();
err
!=
nil
{
panic
(
err
)
}
if
isint
==
404
{
msg
=
"404 page not found"
}
w
.
Header
()
.
Set
(
"Content-Type"
,
"text/plain; charset=utf-8"
)
w
.
WriteHeader
(
isint
)
fmt
.
Fprintln
(
w
,
msg
)
}
// finish all runrouter. release resource
execController
.
Finish
()
}
}
middleware/exceptions.go
deleted
100644 → 0
View file @
71b9854f
// 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
middleware
import
"fmt"
// http exceptions
type
HTTPException
struct
{
StatusCode
int
// http status code 4xx, 5xx
Description
string
}
// return http exception error string, e.g. "400 Bad Request".
func
(
e
*
HTTPException
)
Error
()
string
{
return
fmt
.
Sprintf
(
"%d %s"
,
e
.
StatusCode
,
e
.
Description
)
}
// map of http exceptions for each http status code int.
// defined 400,401,403,404,405,500,502,503 and 504 default.
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"
}
}
namespace.go
View file @
3aceaf88
...
...
@@ -19,7 +19,6 @@ import (
"strings"
beecontext
"github.com/astaxie/beego/context"
"github.com/astaxie/beego/middleware"
)
type
namespaceCond
func
(
*
beecontext
.
Context
)
bool
...
...
@@ -57,7 +56,7 @@ func NewNamespace(prefix string, params ...innnerNamespace) *Namespace {
func
(
n
*
Namespace
)
Cond
(
cond
namespaceCond
)
*
Namespace
{
fn
:=
func
(
ctx
*
beecontext
.
Context
)
{
if
!
cond
(
ctx
)
{
middleware
.
Exception
(
"405"
,
ctx
.
ResponseWriter
,
ctx
.
Request
,
"Method not allowed"
)
exception
(
"405"
,
ctx
)
}
}
if
v
,
ok
:=
n
.
handlers
.
filters
[
BeforeRouter
];
ok
{
...
...
router.go
View file @
3aceaf88
...
...
@@ -30,7 +30,6 @@ import (
"time"
beecontext
"github.com/astaxie/beego/context"
"github.com/astaxie/beego/middleware"
"github.com/astaxie/beego/toolbox"
"github.com/astaxie/beego/utils"
)
...
...
@@ -577,7 +576,6 @@ func (p *ControllerRegistor) geturl(t *Tree, url, controllName, methodName strin
// Implement http.Handler interface.
func
(
p
*
ControllerRegistor
)
ServeHTTP
(
rw
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
defer
p
.
recoverPanic
(
rw
,
r
)
starttime
:=
time
.
Now
()
var
runrouter
reflect
.
Type
var
findrouter
bool
...
...
@@ -600,6 +598,8 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
context
.
Output
.
Context
=
context
context
.
Output
.
EnableGzip
=
EnableGzip
defer
p
.
recoverPanic
(
context
)
var
urlPath
string
if
!
RouterCaseSensitive
{
urlPath
=
strings
.
ToLower
(
r
.
URL
.
Path
)
...
...
@@ -648,7 +648,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
context
.
Input
.
CruSession
,
err
=
GlobalSessions
.
SessionStart
(
w
,
r
)
if
err
!=
nil
{
Error
(
err
)
middleware
.
Exception
(
"503"
,
rw
,
r
,
""
)
exception
(
"503"
,
context
)
return
}
defer
func
()
{
...
...
@@ -703,7 +703,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
//if no matches to url, throw a not found exception
if
!
findrouter
{
middleware
.
Exception
(
"404"
,
rw
,
r
,
""
)
exception
(
"404"
,
context
)
goto
Admin
}
...
...
@@ -719,7 +719,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
isRunable
=
true
routerInfo
.
runfunction
(
context
)
}
else
{
middleware
.
Exception
(
"405"
,
rw
,
r
,
"Method Not Allowed"
)
exception
(
"405"
,
context
)
goto
Admin
}
}
else
if
routerInfo
.
routerType
==
routerTypeHandler
{
...
...
@@ -830,7 +830,7 @@ Admin:
}
}
if
RunMode
==
"dev"
{
if
RunMode
==
"dev"
||
AccessLogs
{
var
devinfo
string
if
findrouter
{
if
routerInfo
!=
nil
{
...
...
@@ -852,27 +852,23 @@ Admin:
}
}
func
(
p
*
ControllerRegistor
)
recoverPanic
(
rw
http
.
ResponseWriter
,
r
*
http
.
Reques
t
)
{
func
(
p
*
ControllerRegistor
)
recoverPanic
(
context
*
beecontext
.
Contex
t
)
{
if
err
:=
recover
();
err
!=
nil
{
if
err
==
USERSTOPRUN
{
return
}
if
he
,
ok
:=
err
.
(
middleware
.
HTTPException
);
ok
{
rw
.
Write
([]
byte
(
he
.
Description
))
// catch intented errors, only for HTTP 4XX and 5XX
}
else
{
if
RunMode
==
"dev"
{
if
!
RecoverPanic
{
panic
(
err
)
}
else
{
if
ErrorsShow
{
if
handler
,
ok
:=
middleware
.
ErrorMaps
[
fmt
.
Sprint
(
err
)];
ok
{
handler
(
rw
,
r
)
if
handler
,
ok
:=
ErrorMaps
[
fmt
.
Sprint
(
err
)];
ok
{
executeError
(
handler
,
context
)
return
}
}
var
stack
string
Critical
(
"the request url is "
,
r
.
URL
.
Path
)
Critical
(
"the request url is "
,
context
.
Input
.
Url
()
)
Critical
(
"Handler crashed with error"
,
err
)
for
i
:=
1
;
;
i
++
{
_
,
file
,
line
,
ok
:=
runtime
.
Caller
(
i
)
...
...
@@ -882,7 +878,7 @@ func (p *ControllerRegistor) recoverPanic(rw http.ResponseWriter, r *http.Reques
Critical
(
fmt
.
Sprintf
(
"%s:%d"
,
file
,
line
))
stack
=
stack
+
fmt
.
Sprintln
(
fmt
.
Sprintf
(
"%s:%d"
,
file
,
line
))
}
middleware
.
ShowErr
(
err
,
rw
,
r
,
stack
)
showErr
(
err
,
context
,
stack
)
}
}
else
{
if
!
RecoverPanic
{
...
...
@@ -890,17 +886,17 @@ func (p *ControllerRegistor) recoverPanic(rw http.ResponseWriter, r *http.Reques
}
else
{
// in production model show all infomation
if
ErrorsShow
{
if
handler
,
ok
:=
middleware
.
ErrorMaps
[
fmt
.
Sprint
(
err
)];
ok
{
handler
(
rw
,
r
)
if
handler
,
ok
:=
ErrorMaps
[
fmt
.
Sprint
(
err
)];
ok
{
executeError
(
handler
,
context
)
return
}
else
if
handler
,
ok
:=
middleware
.
ErrorMaps
[
"503"
];
ok
{
handler
(
rw
,
r
)
}
else
if
handler
,
ok
:=
ErrorMaps
[
"503"
];
ok
{
executeError
(
handler
,
context
)
return
}
else
{
rw
.
Write
([]
byte
(
fmt
.
Sprint
(
err
)
))
context
.
WriteString
(
fmt
.
Sprint
(
err
))
}
}
else
{
Critical
(
"the request url is "
,
r
.
URL
.
Path
)
Critical
(
"the request url is "
,
context
.
Input
.
Url
()
)
Critical
(
"Handler crashed with error"
,
err
)
for
i
:=
1
;
;
i
++
{
_
,
file
,
line
,
ok
:=
runtime
.
Caller
(
i
)
...
...
@@ -912,8 +908,6 @@ func (p *ControllerRegistor) recoverPanic(rw http.ResponseWriter, r *http.Reques
}
}
}
}
}
}
...
...
staticfile.go
View file @
3aceaf88
...
...
@@ -22,7 +22,6 @@ import (
"strings"
"github.com/astaxie/beego/context"
"github.com/astaxie/beego/middleware"
"github.com/astaxie/beego/utils"
)
...
...
@@ -67,7 +66,7 @@ func serverStaticRouter(ctx *context.Context) {
//if the request is dir and DirectoryIndex is false then
if
finfo
.
IsDir
()
{
if
!
DirectoryIndex
{
middleware
.
Exception
(
"403"
,
ctx
.
ResponseWriter
,
ctx
.
Request
,
"403 Forbidden"
)
exception
(
"403"
,
ctx
)
return
}
else
if
ctx
.
Input
.
Request
.
URL
.
Path
[
len
(
ctx
.
Input
.
Request
.
URL
.
Path
)
-
1
]
!=
'/'
{
http
.
Redirect
(
ctx
.
ResponseWriter
,
ctx
.
Request
,
ctx
.
Input
.
Request
.
URL
.
Path
+
"/"
,
302
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment