ksrv/kmux.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})
}
}