Skip to content

Commit

Permalink
rest: update middleware
Browse files Browse the repository at this point in the history
  • Loading branch information
agungdwiprasetyo committed Mar 3, 2023
1 parent 7f0cc97 commit 513910d
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 109 deletions.
174 changes: 71 additions & 103 deletions codebase/app/rest_server/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,10 @@ import (
"github.com/golangid/candi/tracer"
"github.com/golangid/candi/wrapper"
"github.com/labstack/echo"
"github.com/labstack/gommon/color"
"github.com/valyala/fasttemplate"
)

// echoRestTracerMiddleware for wrap from http inbound (request from client)
func (h *restServer) echoRestTracerMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
// tracerMiddleware for wrap from http inbound (request from client)
func (h *restServer) tracerMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
req := c.Request()

Expand All @@ -47,6 +45,11 @@ func (h *restServer) echoRestTracerMiddleware(next echo.HandlerFunc) echo.Handle
logger.LogGreen("rest_api > trace_url: " + tracer.GetTraceURL(ctx))
}()

httpDump, _ := httputil.DumpRequest(req, false)
trace.SetTag("http.url_path", req.URL.Path)
trace.SetTag("http.method", req.Method)
trace.Log("http.request", httpDump)

body, _ := io.ReadAll(req.Body)
if len(body) < h.opt.jaegerMaxPacketSize { // limit request body size to 65000 bytes (if higher tracer cannot show root span)
trace.Log("request.body", body)
Expand All @@ -55,11 +58,6 @@ func (h *restServer) echoRestTracerMiddleware(next echo.HandlerFunc) echo.Handle
}
req.Body = io.NopCloser(bytes.NewBuffer(body)) // reuse body

httpDump, _ := httputil.DumpRequest(req, false)
trace.SetTag("http.request", string(httpDump))
trace.SetTag("http.url_path", req.URL.Path)
trace.SetTag("http.method", req.Method)

resBody := new(bytes.Buffer)
mw := io.MultiWriter(c.Response().Writer, resBody)
c.Response().Writer = wrapper.NewWrapHTTPResponseWriter(mw, c.Response().Writer)
Expand All @@ -81,7 +79,8 @@ func (h *restServer) echoRestTracerMiddleware(next echo.HandlerFunc) echo.Handle
}
}

func defaultCORS() echo.MiddlewareFunc {
// EchoDefaultCORSMiddleware middleware
func EchoDefaultCORSMiddleware() echo.MiddlewareFunc {
allowMethods := strings.Join(env.BaseEnv().CORSAllowMethods, ",")
allowHeaders := strings.Join(env.BaseEnv().CORSAllowHeaders, ",")
exposeHeaders := ""
Expand Down Expand Up @@ -135,14 +134,8 @@ func defaultCORS() echo.MiddlewareFunc {
}
}

func echoLogger() echo.MiddlewareFunc {
format := `{"time":"${time_rfc3339_nano}","id":"${id}","remote_ip":"${remote_ip}",` +
`"host":"${host}","method":"${method}","uri":"${uri}","user_agent":"${user_agent}",` +
`"status":${status},"error":"${error}","latency":${latency},"latency_human":"${latency_human}"` +
`,"bytes_in":${bytes_in},"bytes_out":${bytes_out}}` + "\n"
template := fasttemplate.New(format, "${", "}")
colorer := color.New()
colorer.SetOutput(os.Stdout)
// EchoLoggerMiddleware middleware
func EchoLoggerMiddleware() echo.MiddlewareFunc {
bPool := &sync.Pool{
New: func() interface{} {
return bytes.NewBuffer(make([]byte, 256))
Expand All @@ -163,92 +156,67 @@ func echoLogger() echo.MiddlewareFunc {
buf.Reset()
defer bPool.Put(buf)

if _, err = template.ExecuteFunc(buf, func(w io.Writer, tag string) (int, error) {
switch tag {
case "time_unix":
return buf.WriteString(strconv.FormatInt(time.Now().Unix(), 10))
case "time_unix_nano":
return buf.WriteString(strconv.FormatInt(time.Now().UnixNano(), 10))
case "time_rfc3339":
return buf.WriteString(time.Now().Format(time.RFC3339))
case "time_rfc3339_nano":
return buf.WriteString(time.Now().Format(time.RFC3339Nano))
case "time_custom":
return buf.WriteString(time.Now().Format(candihelper.TimeFormatLogger))
case "id":
id := req.Header.Get(echo.HeaderXRequestID)
if id == "" {
id = res.Header().Get(echo.HeaderXRequestID)
}
return buf.WriteString(id)
case "remote_ip":
return buf.WriteString(c.RealIP())
case "host":
return buf.WriteString(req.Host)
case "uri":
return buf.WriteString(req.RequestURI)
case "method":
return buf.WriteString(req.Method)
case "path":
p := req.URL.Path
if p == "" {
p = "/"
}
return buf.WriteString(p)
case "protocol":
return buf.WriteString(req.Proto)
case "referer":
return buf.WriteString(req.Referer())
case "user_agent":
return buf.WriteString(req.UserAgent())
case "status":
n := res.Status
s := colorer.Green(n)
switch {
case n >= 500:
s = colorer.Red(n)
case n >= 400:
s = colorer.Yellow(n)
case n >= 300:
s = colorer.Cyan(n)
}
return buf.WriteString(s)
case "error":
if err != nil {
return buf.WriteString(err.Error())
}
case "latency":
l := stop.Sub(start)
return buf.WriteString(strconv.FormatInt(int64(l), 10))
case "latency_human":
return buf.WriteString(stop.Sub(start).String())
case "bytes_in":
cl := req.Header.Get(echo.HeaderContentLength)
if cl == "" {
cl = "0"
}
return buf.WriteString(cl)
case "bytes_out":
return buf.WriteString(strconv.FormatInt(res.Size, 10))
default:
switch {
case strings.HasPrefix(tag, "header:"):
return buf.Write([]byte(c.Request().Header.Get(tag[7:])))
case strings.HasPrefix(tag, "query:"):
return buf.Write([]byte(c.QueryParam(tag[6:])))
case strings.HasPrefix(tag, "form:"):
return buf.Write([]byte(c.FormValue(tag[5:])))
case strings.HasPrefix(tag, "cookie:"):
cookie, err := c.Cookie(tag[7:])
if err == nil {
return buf.Write([]byte(cookie.Value))
}
}
}
return 0, nil
}); err != nil {
return
buf.WriteString(`{"time":"`)
buf.WriteString(time.Now().Format(time.RFC3339Nano))

buf.WriteString(`","id":"`)
id := req.Header.Get(echo.HeaderXRequestID)
if id == "" {
id = res.Header().Get(echo.HeaderXRequestID)
}
buf.WriteString(id)

buf.WriteString(`","remote_ip":"`)
buf.WriteString(c.RealIP())

buf.WriteString(`","host":"`)
buf.WriteString(req.Host)

buf.WriteString(`","method":"`)
buf.WriteString(req.Method)

buf.WriteString(`","uri":"`)
buf.WriteString(req.RequestURI)

buf.WriteString(`","user_agent":"`)
buf.WriteString(req.UserAgent())

buf.WriteString(`","status":`)
n := res.Status
s := logger.GreenColor(n)
switch {
case n >= 500:
s = logger.RedColor(n)
case n >= 400:
s = logger.YellowColor(n)
case n >= 300:
s = logger.CyanColor(n)
}
buf.WriteString(s)

buf.WriteString(`,"error":"`)
if err != nil {
buf.WriteString(err.Error())
}

buf.WriteString(`","latency":`)
l := stop.Sub(start)
buf.WriteString(strconv.FormatInt(int64(l), 10))

buf.WriteString(`,"latency_human":"`)
buf.WriteString(stop.Sub(start).String())

buf.WriteString(`","bytes_in":`)
cl := req.Header.Get(echo.HeaderContentLength)
if cl == "" {
cl = "0"
}
buf.WriteString(cl)

buf.WriteString(`,"bytes_out":`)
buf.WriteString(strconv.FormatInt(res.Size, 10))

buf.WriteString("}\n")

_, err = os.Stdout.Write(buf.Bytes())
return
Expand Down
2 changes: 1 addition & 1 deletion codebase/app/rest_server/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func getDefaultOption() option {
httpPort: ":8000",
rootPath: "",
debugMode: true,
rootMiddlewares: []echo.MiddlewareFunc{defaultCORS()},
rootMiddlewares: []echo.MiddlewareFunc{EchoDefaultCORSMiddleware()},
rootHandler: http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
rw.Write([]byte("REST Server up and running"))
}),
Expand Down
4 changes: 2 additions & 2 deletions codebase/app/rest_server/rest_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ func NewServer(service factory.ServiceFactory, opts ...OptionFunc) factory.AppSe
echo.WrapMiddleware(service.GetDependency().GetMiddleware().HTTPBasicAuth),
)

restRootPath := server.serverEngine.Group(server.opt.rootPath, server.echoRestTracerMiddleware)
restRootPath := server.serverEngine.Group(server.opt.rootPath, server.tracerMiddleware)
if server.opt.debugMode {
restRootPath.Use(echoLogger())
restRootPath.Use(EchoLoggerMiddleware())
}
for _, m := range service.GetModules() {
if h := m.RESTHandler(); h != nil {
Expand Down
26 changes: 23 additions & 3 deletions logger/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,40 @@ func LogWithDefer(str string) (deferFunc func()) {
// LogYellow log with yellow color
func LogYellow(str string) {
if env.BaseEnv().DebugMode {
fmt.Printf("\x1b[33;5m%s\x1b[0m\n", str)
fmt.Printf("%s\n", YellowColor(str))
}
}

// LogRed log with red color
func LogRed(str string) {
if env.BaseEnv().DebugMode {
fmt.Printf("\x1b[31;5m%s\x1b[0m\n", str)
fmt.Printf("%s\n", RedColor(str))
}
}

// LogGreen log with green color
func LogGreen(str string) {
if env.BaseEnv().DebugMode {
fmt.Printf("\x1b[32;5m%s\x1b[0m\n", str)
fmt.Printf("%s\n", GreenColor(str))
}
}

// RedColor func
func RedColor(str interface{}) string {
return fmt.Sprintf("\x1b[31;5m%v\x1b[0m", str)
}

// GreenColor func
func GreenColor(str interface{}) string {
return fmt.Sprintf("\x1b[32;5m%v\x1b[0m", str)
}

// YellowColor func
func YellowColor(str interface{}) string {
return fmt.Sprintf("\x1b[33;5m%v\x1b[0m", str)
}

// CyanColor func
func CyanColor(str interface{}) string {
return fmt.Sprintf("\x1b[36;5m%v\x1b[0m", str)
}

0 comments on commit 513910d

Please sign in to comment.