package ksrv import ( "fmt" "io" "net/http" "kumoly.io/lib/klog" "kumoly.io/lib/klog/color" ) const ( DEFAULT_ERR = `[{{"KSRV"|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}}` ) func (k *kserver) SetLogger(l *klog.Logger) { k.l = l } func (k *kserver) GetLogger() *klog.Logger { return k.l } // New returns a extended http.Server func New() *kserver { l := klog.Sub("KSRV") l.SetPrinter(func(w io.Writer, d *klog.Ldata, l2 *klog.Logger) { msg := "" if d.Fields["Message"] != nil { msg = l.M(d.Fields["Message"], color.FgHiRed) } fmt.Fprintf(w, "[%s] %s |%s| %15s %s %s %s\n%s", l.M("KSRV ", color.FgHiCyan), d.Time.Format("2006/01/02 15:04:05"), StatusColor(d.Fields["Status"].(int), l), d.Fields["IP"], MethodColor(d.Fields["Method"], l), d.Fields["URL"], msg, l.M(d.Stack, color.FgRed), ) }) k := &kserver{ l: l, nolog: func(r *http.Request) bool { return false }, } return k } func (k *kserver) 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 *kserver) SetNoLogCondition(nolog func(r *http.Request) bool) *kserver { k.nolog = nolog return k } func (k *kserver) catch(rw *responseWriter, r *http.Request) { ex := recover() if ex != nil { Abort(rw, ex) k.l.ErrorF(klog.H{"Status": rw.StatueCode, "IP": GetIP(r), "Method": r.Method, "URL": r.URL.Path, "Agent": r.Header.Get("User-Agent")}, ex) } else if rw.StatueCode >= 500 { k.l.ErrorF(klog.H{"Status": rw.StatueCode, "IP": GetIP(r), "Method": r.Method, "URL": r.URL.Path, "Agent": r.Header.Get("User-Agent")}, rw.err) } else if k.nolog == nil || !k.nolog(r) { k.l.InfoF(klog.H{"Status": rw.StatueCode, "IP": GetIP(r), "Method": r.Method, "URL": r.URL.Path, "Agent": r.Header.Get("User-Agent")}) } } func MethodColor(method interface{}, l *klog.Logger) string { show := fmt.Sprintf(" %-7s", method) switch method { case http.MethodGet: return l.M(show, 97, 44) case http.MethodPost: return l.M(show, 97, 46) case http.MethodPut: return l.M(show, 90, 43) case http.MethodDelete: return l.M(show, 97, 41) case http.MethodPatch: return l.M(show, 97, 42) case http.MethodHead: return l.M(show, 97, 45) case http.MethodOptions: return l.M(show, 90, 47) default: return l.M(show, 0) } } func StatusColor(code int, l *klog.Logger) string { s := fmt.Sprintf(" %d ", code) 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) } }