package webroot import ( "fmt" "log" "path" "regexp" "strconv" "github.com/eternal-flame-AD/yoake/internal/auth" "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" ) type logEntry struct { middleware.RequestLoggerValues Categories []string CleanPath string Auth auth.RequestAuth } func processLoggerValues(c echo.Context, values middleware.RequestLoggerValues) logEntry { status := values.Status statusString := []byte(strconv.Itoa(status)) for i := len(statusString) - 1; i >= 0; i-- { logSetRequestCategory(c, fmt.Sprintf("status_%s", statusString)) statusString[i] = 'x' } return logEntry{ RequestLoggerValues: values, Categories: logGetCategories(c), CleanPath: path.Clean(c.Request().URL.Path), Auth: auth.GetRequestAuth(c), } } type logCompiledFilter struct { Negate bool Pattern *regexp.Regexp } func logGetCategories(c echo.Context) []string { if existingCates, err := c.Get("log_request_categories").([]string); err { return existingCates } else { return []string{} } } func logCompileFilters(filters []string) []logCompiledFilter { var compiledFilters []logCompiledFilter for _, filter := range filters { negate := false if filter[0] == '!' { negate = true filter = filter[1:] } log.Printf("Compiling filter: %s negate=%v", filter, negate) compiledFilters = append(compiledFilters, logCompiledFilter{negate, regexp.MustCompile(filter)}) } return compiledFilters } func logFilterCategories(c echo.Context, filters []logCompiledFilter) bool { if filters == nil { return true } for _, category := range logGetCategories(c) { for _, filter := range filters { matches := filter.Pattern.MatchString(category) negate := filter.Negate // log.Printf("Checking category %s against filter %s negate=%v matches=%v", category, filter.Pattern, negate, matches) if matches { return !negate } } } return true } func logSetRequestCategory(c echo.Context, category string) { if existingCates, ok := c.Get("log_request_categories").([]string); !ok { c.Set("log_request_categories", []string{category}) } else { c.Set("log_request_categories", append(existingCates, category)) } } func logRemoveRequestCategory(c echo.Context, category string) { if existingCates, ok := c.Get("log_request_categories").([]string); ok { for i, existingCate := range existingCates { if existingCate == category { c.Set("log_request_categories", append(existingCates[:i], existingCates[i+1:]...)) return } } } } func logMiddleware(category string, backend echo.MiddlewareFunc) echo.MiddlewareFunc { return func(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { logSetRequestCategory(c, category) wrappedNext := func(c echo.Context) error { logRemoveRequestCategory(c, category) return next(c) } return backend(wrappedNext)(c) } } } var ( loggerConfig = middleware.RequestLoggerConfig{ LogLatency: true, LogProtocol: true, LogRemoteIP: true, LogHost: true, LogMethod: true, LogURI: true, LogURIPath: true, LogRoutePath: true, LogRequestID: true, LogReferer: true, LogUserAgent: true, LogStatus: true, LogError: true, LogContentLength: true, LogResponseSize: true, LogHeaders: []string{}, LogQueryParams: []string{}, LogFormValues: []string{}, } )