1
0
Fork 0

404 수정중

This commit is contained in:
tom.cat 2016-03-15 19:24:48 +09:00
parent 58b9fd6d82
commit 84ec23420d
3 changed files with 172 additions and 15 deletions

23
main.go
View File

@ -21,6 +21,7 @@ import (
"time" "time"
"amuz.es/go/mnemonics/middleware/logging" "amuz.es/go/mnemonics/middleware/logging"
"amuz.es/go/mnemonics/middleware/recovery"
"amuz.es/go/mnemonics/middleware/secure" "amuz.es/go/mnemonics/middleware/secure"
"amuz.es/go/mnemonics/middleware/session" "amuz.es/go/mnemonics/middleware/session"
"amuz.es/go/mnemonics/middleware/static" "amuz.es/go/mnemonics/middleware/static"
@ -41,29 +42,23 @@ func main() {
setMaxProcs() setMaxProcs()
store := session.NewCookieStore([]byte(util.GetRandomString(128))) store := session.NewCookieStore([]byte(util.GetRandomString(128)))
//gin.SetMode(gin.ReleaseMode) gin.SetMode(gin.ReleaseMode)
r := gin.New() r := gin.New()
// middleware settings // middleware settings
r.Use(logging.Ginrus(time.RFC3339, true)) r.Use(logging.Ginrus(time.RFC3339, true))
// r.Use(recovery.Recovery())
r.Use(gin.Recovery())
// not found handler // not found handler
r.NoRoute(func(c *gin.Context) { r.NoRoute(recovery.RecoveryHttpError(http.StatusNotFound))
code := http.StatusNotFound r.NoMethod(recovery.RecoveryHttpError(http.StatusMethodNotAllowed))
c.HTML(code, "page_404.html", template.Context{
"statusCode": code,
"statusMessage": http.StatusText(code),
"path": c.Request.URL.Path,
"method": c.Request.Method})
})
// suburl process // suburl process
path := r.Group("/") path := r.Group("/")
path.Use(recovery.RecoveryHTML())
// handlers // handlers
api := path.Group("/api") api := path.Group("/api")
api.Use(recovery.RecoveryJSON())
api.Use(secure.Secure(secure.Options{ api.Use(secure.Secure(secure.Options{
AllowedHosts: []string{}, AllowedHosts: []string{},
@ -78,9 +73,9 @@ func main() {
BrowserXssFilter: true, BrowserXssFilter: true,
ContentSecurityPolicy: "default-src 'self'", ContentSecurityPolicy: "default-src 'self'",
})) }))
api.Use(session.Sessions("mysession", store)) api.Use(session.Sessions("mnemonics", store))
api.GET("", route.Me)
api.GET("/auth", route.Me)
path.GET("/self", route.Self) path.GET("/self", route.Self)
path.GET("/metric", route.Metric) path.GET("/metric", route.Metric)
path.GET("/health", func(c *gin.Context) { path.GET("/health", func(c *gin.Context) {

View File

@ -0,0 +1,163 @@
package recovery
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"net/http/httputil"
"runtime"
"strings"
"amuz.es/go/mnemonics/middleware/template"
"amuz.es/go/mnemonics/util"
"github.com/Sirupsen/logrus"
"github.com/gin-gonic/gin"
)
var (
dunno = []byte("???")
centerDot = []byte("·")
dot = []byte(".")
slash = []byte("/")
)
func recoveryInternal(code int, c *gin.Context, err error) map[string]interface{} {
logger := util.Log()
stack := stack(3)
httprequest, _ := httputil.DumpRequest(c.Request, false)
path := c.Request.URL.Path
info := map[string]interface{}{
"statusCode": code,
"statusMessage": fmt.Sprintf("%s : %s", http.StatusText(code), err),
"path": path}
detailInfo := map[string]interface{}{
"statusCode": code,
"statusMessage": fmt.Sprintf("%s : %s", http.StatusText(code), err),
"path": path,
"method": c.Request.Method,
"request": string(httprequest),
"stack": string(stack),
"error": string(err.(error).Error())}
logger.WithFields(logrus.Fields(detailInfo)).Error("[Recovery] panic recovered:\n")
return info
}
func recoveryError(code int, c *gin.Context) map[string]interface{} {
path := c.Request.URL.Path
return map[string]interface{}{
"statusCode": code,
"statusMessage": http.StatusText(code),
"path": path}
}
func RecoveryHttpError(code int) gin.HandlerFunc {
return func(c *gin.Context) {
defer func() {
if err := recover(); err != nil {
info := recoveryError(code, c)
if strings.HasPrefix(c.Request.URL.Path, "/api") {
c.JSON(code, gin.H(info))
} else {
c.HTML(code, "page_404.html", template.Context(info))
}
c.Abort()
}
}()
c.Next()
}
}
func RecoveryJSON() gin.HandlerFunc {
return func(c *gin.Context) {
defer func() {
if err := recover(); err != nil {
code := http.StatusInternalServerError
info := recoveryInternal(code, c, err.(error))
c.JSON(code, gin.H(info))
c.Abort()
}
}()
c.Next()
}
}
func RecoveryHTML() gin.HandlerFunc {
return func(c *gin.Context) {
defer func() {
if err := recover(); err != nil {
code := http.StatusInternalServerError
info := recoveryInternal(code, c, err.(error))
c.HTML(code, "page_404.html", template.Context(info))
c.Abort()
}
}()
c.Next()
}
}
// stack returns a nicely formated stack frame, skipping skip frames
func stack(skip int) []byte {
buf := new(bytes.Buffer) // the returned data
// As we loop, we open files and read them. These variables record the currently
// loaded file.
var lines [][]byte
var lastFile string
for i := skip; ; i++ { // Skip the expected number of frames
pc, file, line, ok := runtime.Caller(i)
if !ok {
break
}
// Print this much at least. If we can't find the source, it won't show.
fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc)
if file != lastFile {
data, err := ioutil.ReadFile(file)
if err != nil {
continue
}
lines = bytes.Split(data, []byte{'\n'})
lastFile = file
}
fmt.Fprintf(buf, "\t%s: %s\n", function(pc), source(lines, line))
}
return buf.Bytes()
}
// source returns a space-trimmed slice of the n'th line.
func source(lines [][]byte, n int) []byte {
n-- // in stack trace, lines are 1-indexed but our array is 0-indexed
if n < 0 || n >= len(lines) {
return dunno
}
return bytes.TrimSpace(lines[n])
}
// function returns, if possible, the name of the function containing the PC.
func function(pc uintptr) []byte {
fn := runtime.FuncForPC(pc)
if fn == nil {
return dunno
}
name := []byte(fn.Name())
// The name includes the path name to the package, which is unnecessary
// since the file name is already included. Plus, it has center dots.
// That is, we see
// runtime/debug.*T·ptrmethod
// and want
// *T.ptrmethod
// Also the package path might contains dot (e.g. code.google.com/...),
// so first eliminate the path prefix
if lastslash := bytes.LastIndex(name, slash); lastslash >= 0 {
name = name[lastslash+1:]
}
if period := bytes.Index(name, dot); period >= 0 {
name = name[period+1:]
}
name = bytes.Replace(name, centerDot, dot, -1)
return name
}

View File

@ -142,7 +142,6 @@ func (l ldapSource) Bind(uid string, password pwdStor) {
dn := fmt.Sprintf("%s=%s,%s", l.user.uniqueAttributeName, uid, l.user.dn) dn := fmt.Sprintf("%s=%s,%s", l.user.uniqueAttributeName, uid, l.user.dn)
err := l.connection.Bind(dn, password.GetPlainPassword()).(*ldap.Error) err := l.connection.Bind(dn, password.GetPlainPassword()).(*ldap.Error)
if err != nil { if err != nil {
Log().Errorf("dddd %d", err.ResultCode)
panic(err) panic(err)
} }
} }