110 lines
2.7 KiB
Go
110 lines
2.7 KiB
Go
|
package kmux
|
||
|
|
||
|
import (
|
||
|
"net/http"
|
||
|
|
||
|
"github.com/gorilla/mux"
|
||
|
"kumoly.io/core/log"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
DEFAULT_INFO = `[{{"KMUX"|cyan}}] {{Time}} {{with .Fields}}|{{printf " %3d " .Status|statcol .Status}}| ` +
|
||
|
`{{printf "%15s" .IP}} {{printf " %-7s " .Method|methcol .Method}} {{.URL}}{{"\n"}}{{end}}`
|
||
|
DEFAULT_ERR = `[{{"KMUX"|cyan}}] {{Time}} {{with .Fields}}|{{printf " %3d " .Status|statcol .Status}}| ` +
|
||
|
`{{printf "%15s" .IP}} {{printf " %-7s " .Method|methcol .Method}} {{.URL}}{{end}} {{.Message|red}}{{"\n"}}` +
|
||
|
`{{if .Stack}}{{.Stack|redl}}{{end}}`
|
||
|
)
|
||
|
|
||
|
type kmux struct {
|
||
|
mux.Router
|
||
|
l *log.Logger
|
||
|
}
|
||
|
|
||
|
func (k *kmux) SetLogger(l *log.Logger) {
|
||
|
k.l = l
|
||
|
}
|
||
|
|
||
|
func (k *kmux) GetLogger() *log.Logger {
|
||
|
return k.l
|
||
|
}
|
||
|
|
||
|
func (k *kmux) Server() *kserver {
|
||
|
return &kserver{
|
||
|
http.Server{
|
||
|
Handler: k.middleware(k),
|
||
|
Addr: "0.0.0.0:8080",
|
||
|
},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// NewRouter returns a extended gorilla mux
|
||
|
func NewRouter() *kmux {
|
||
|
l := log.Sub("KMUX")
|
||
|
tmpl := log.NewLogFormater()
|
||
|
tmpl.InfoTmplStr = DEFAULT_INFO
|
||
|
tmpl.ErrTmplStr = DEFAULT_ERR
|
||
|
|
||
|
fMap := log.DefaultFuncMap()
|
||
|
fMap["statcol"] = func(code int, s string) string {
|
||
|
switch {
|
||
|
case code >= http.StatusOK && code < http.StatusMultipleChoices:
|
||
|
return l.M(s, 97, 42)
|
||
|
case code >= http.StatusMultipleChoices && code < http.StatusBadRequest:
|
||
|
return l.M(s, 90, 47)
|
||
|
case code >= http.StatusBadRequest && code < http.StatusInternalServerError:
|
||
|
return l.M(s, 90, 43)
|
||
|
default:
|
||
|
return l.M(s, 97, 41)
|
||
|
}
|
||
|
}
|
||
|
fMap["methcol"] = func(method string, s string) string {
|
||
|
switch method {
|
||
|
case http.MethodGet:
|
||
|
return l.M(s, 97, 44)
|
||
|
case http.MethodPost:
|
||
|
return l.M(s, 97, 46)
|
||
|
case http.MethodPut:
|
||
|
return l.M(s, 90, 43)
|
||
|
case http.MethodDelete:
|
||
|
return l.M(s, 97, 41)
|
||
|
case http.MethodPatch:
|
||
|
return l.M(s, 97, 42)
|
||
|
case http.MethodHead:
|
||
|
return l.M(s, 97, 45)
|
||
|
case http.MethodOptions:
|
||
|
return l.M(s, 90, 47)
|
||
|
default:
|
||
|
return l.M(s, 0)
|
||
|
}
|
||
|
}
|
||
|
l.SetTmpl(tmpl, fMap)
|
||
|
err := l.Reload()
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
k := &kmux{*mux.NewRouter(), l}
|
||
|
return k
|
||
|
}
|
||
|
|
||
|
func (k *kmux) middleware(next http.Handler) http.Handler {
|
||
|
return http.HandlerFunc(
|
||
|
func(w http.ResponseWriter, r *http.Request) {
|
||
|
rw := &responseWriter{w, 0, ""}
|
||
|
defer k.catch(rw, r)
|
||
|
next.ServeHTTP(rw, r)
|
||
|
},
|
||
|
)
|
||
|
}
|
||
|
|
||
|
func (k *kmux) catch(rw *responseWriter, r *http.Request) {
|
||
|
ex := recover()
|
||
|
if ex != nil {
|
||
|
Abort(rw, ex)
|
||
|
k.l.ErrorF(log.H{"Status": rw.StatueCode, "IP": GetIP(r), "Method": r.Method, "URL": r.URL.Path}, ex)
|
||
|
} else if rw.StatueCode >= 500 {
|
||
|
k.l.ErrorF(log.H{"Status": rw.StatueCode, "IP": GetIP(r), "Method": r.Method, "URL": r.URL.Path}, rw.err)
|
||
|
} else {
|
||
|
k.l.InfoF(log.H{"Status": rw.StatueCode, "IP": GetIP(r), "Method": r.Method, "URL": r.URL.Path})
|
||
|
}
|
||
|
}
|