feat: adding filters
This commit is contained in:
@@ -78,6 +78,46 @@ router.Run(":1234")
|
||||
// time=2023-04-10T14:00:0.000000Z level=INFO msg="Incoming request" status=200 method=GET path=/pong ip=127.0.0.1 latency=25.5µs user-agent=curl/7.77.0 time=2023-04-10T14:00:00.000Z
|
||||
```
|
||||
|
||||
### Filters
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
sloggin "github.com/samber/slog-gin"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
||||
|
||||
router := gin.New()
|
||||
router.Use(
|
||||
sloggin.NewWithFilters(
|
||||
logger,
|
||||
sloggin.Accept(func (c *gin.Context) bool {
|
||||
return xxx
|
||||
}),
|
||||
sloggin.IgnoreStatus(401, 404),
|
||||
),
|
||||
)
|
||||
```
|
||||
|
||||
Available filters:
|
||||
- Accept / Ignore
|
||||
- AcceptMethod / IgnoreMethod
|
||||
- AcceptStatus / IgnoreStatus
|
||||
- AcceptStatusGreaterThan / IgnoreStatusLessThan
|
||||
- AcceptStatusGreaterThanOrEqual / IgnoreStatusLessThanOrEqual
|
||||
- AcceptPath / IgnorePath
|
||||
- AcceptPathContains / IgnorePathContains
|
||||
- AcceptPathPrefix / IgnorePathPrefix
|
||||
- AcceptPathSuffix / IgnorePathSuffix
|
||||
- AcceptPathMatch / IgnorePathMatch
|
||||
- AcceptHost / IgnoreHost
|
||||
- AcceptHostContains / IgnoreHostContains
|
||||
- AcceptHostPrefix / IgnoreHostPrefix
|
||||
- AcceptHostSuffix / IgnoreHostSuffix
|
||||
- AcceptHostMatch / IgnoreHostMatch
|
||||
|
||||
### Using custom time formatters
|
||||
|
||||
```go
|
||||
|
||||
+334
@@ -0,0 +1,334 @@
|
||||
package sloggin
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type Filter func(ctx *gin.Context) bool
|
||||
|
||||
// Basic
|
||||
func Accept(filter Filter) Filter { return filter }
|
||||
func Ignore(filter Filter) Filter { return filter }
|
||||
|
||||
// Method
|
||||
func AcceptMethod(methods ...string) Filter {
|
||||
return func(c *gin.Context) bool {
|
||||
reqMethod := strings.ToLower(c.Request.Method)
|
||||
|
||||
for _, method := range methods {
|
||||
if strings.ToLower(method) == reqMethod {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func IgnoreMethod(methods ...string) Filter {
|
||||
return func(c *gin.Context) bool {
|
||||
reqMethod := strings.ToLower(c.Request.Method)
|
||||
|
||||
for _, method := range methods {
|
||||
if strings.ToLower(method) == reqMethod {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// Status
|
||||
func AcceptStatus(statuses ...int) Filter {
|
||||
return func(c *gin.Context) bool {
|
||||
for _, status := range statuses {
|
||||
if status == c.Writer.Status() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func IgnoreStatus(statuses ...int) Filter {
|
||||
return func(c *gin.Context) bool {
|
||||
for _, status := range statuses {
|
||||
if status == c.Writer.Status() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func AcceptStatusGreaterThan(status int) Filter {
|
||||
return func(c *gin.Context) bool {
|
||||
return c.Writer.Status() > status
|
||||
}
|
||||
}
|
||||
|
||||
func IgnoreStatusLessThan(status int) Filter {
|
||||
return func(c *gin.Context) bool {
|
||||
return c.Writer.Status() < status
|
||||
}
|
||||
}
|
||||
|
||||
func AcceptStatusGreaterThanOrEqual(status int) Filter {
|
||||
return func(c *gin.Context) bool {
|
||||
return c.Writer.Status() >= status
|
||||
}
|
||||
}
|
||||
|
||||
func IgnoreStatusLessThanOrEqual(status int) Filter {
|
||||
return func(c *gin.Context) bool {
|
||||
return c.Writer.Status() <= status
|
||||
}
|
||||
}
|
||||
|
||||
// Path
|
||||
func AcceptPath(urls ...string) Filter {
|
||||
return func(c *gin.Context) bool {
|
||||
for _, url := range urls {
|
||||
if c.Request.URL.Path == url {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func IgnorePath(urls ...string) Filter {
|
||||
return func(c *gin.Context) bool {
|
||||
for _, url := range urls {
|
||||
if c.Request.URL.Path == url {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func AcceptPathContains(parts ...string) Filter {
|
||||
return func(c *gin.Context) bool {
|
||||
for _, part := range parts {
|
||||
if strings.Contains(c.Request.URL.Path, part) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func IgnorePathContains(parts ...string) Filter {
|
||||
return func(c *gin.Context) bool {
|
||||
for _, part := range parts {
|
||||
if strings.Contains(c.Request.URL.Path, part) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func AcceptPathPrefix(prefixs ...string) Filter {
|
||||
return func(c *gin.Context) bool {
|
||||
for _, prefix := range prefixs {
|
||||
if strings.HasPrefix(c.Request.URL.Path, prefix) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func IgnorePathPrefix(prefixs ...string) Filter {
|
||||
return func(c *gin.Context) bool {
|
||||
for _, prefix := range prefixs {
|
||||
if strings.HasPrefix(c.Request.URL.Path, prefix) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func AcceptPathSuffix(prefixs ...string) Filter {
|
||||
return func(c *gin.Context) bool {
|
||||
for _, prefix := range prefixs {
|
||||
if strings.HasPrefix(c.Request.URL.Path, prefix) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func IgnorePathSuffix(suffixs ...string) Filter {
|
||||
return func(c *gin.Context) bool {
|
||||
for _, suffix := range suffixs {
|
||||
if strings.HasSuffix(c.Request.URL.Path, suffix) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func AcceptPathMatch(regs ...regexp.Regexp) Filter {
|
||||
return func(c *gin.Context) bool {
|
||||
for _, reg := range regs {
|
||||
if reg.Match([]byte(c.Request.URL.Path)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func IgnorePathMatch(regs ...regexp.Regexp) Filter {
|
||||
return func(c *gin.Context) bool {
|
||||
for _, reg := range regs {
|
||||
if reg.Match([]byte(c.Request.URL.Path)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// Host
|
||||
func AcceptHost(hosts ...string) Filter {
|
||||
return func(c *gin.Context) bool {
|
||||
for _, host := range hosts {
|
||||
if c.Request.URL.Host == host {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func IgnoreHost(hosts ...string) Filter {
|
||||
return func(c *gin.Context) bool {
|
||||
for _, host := range hosts {
|
||||
if c.Request.URL.Host == host {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func AcceptHostContains(parts ...string) Filter {
|
||||
return func(c *gin.Context) bool {
|
||||
for _, part := range parts {
|
||||
if strings.Contains(c.Request.URL.Host, part) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func IgnoreHostContains(parts ...string) Filter {
|
||||
return func(c *gin.Context) bool {
|
||||
for _, part := range parts {
|
||||
if strings.Contains(c.Request.URL.Host, part) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func AcceptHostPrefix(prefixs ...string) Filter {
|
||||
return func(c *gin.Context) bool {
|
||||
for _, prefix := range prefixs {
|
||||
if strings.HasPrefix(c.Request.URL.Host, prefix) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func IgnoreHostPrefix(prefixs ...string) Filter {
|
||||
return func(c *gin.Context) bool {
|
||||
for _, prefix := range prefixs {
|
||||
if strings.HasPrefix(c.Request.URL.Host, prefix) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func AcceptHostSuffix(prefixs ...string) Filter {
|
||||
return func(c *gin.Context) bool {
|
||||
for _, prefix := range prefixs {
|
||||
if strings.HasPrefix(c.Request.URL.Host, prefix) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func IgnoreHostSuffix(suffixs ...string) Filter {
|
||||
return func(c *gin.Context) bool {
|
||||
for _, suffix := range suffixs {
|
||||
if strings.HasSuffix(c.Request.URL.Host, suffix) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func AcceptHostMatch(regs ...regexp.Regexp) Filter {
|
||||
return func(c *gin.Context) bool {
|
||||
for _, reg := range regs {
|
||||
if reg.Match([]byte(c.Request.URL.Host)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func IgnoreHostMatch(regs ...regexp.Regexp) Filter {
|
||||
return func(c *gin.Context) bool {
|
||||
for _, reg := range regs {
|
||||
if reg.Match([]byte(c.Request.URL.Host)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,8 @@ type Config struct {
|
||||
ServerErrorLevel slog.Level
|
||||
|
||||
WithRequestID bool
|
||||
|
||||
Filters []Filter
|
||||
}
|
||||
|
||||
// New returns a gin.HandlerFunc (middleware) that logs requests using slog.
|
||||
@@ -32,6 +34,24 @@ func New(logger *slog.Logger) gin.HandlerFunc {
|
||||
ServerErrorLevel: slog.LevelError,
|
||||
|
||||
WithRequestID: true,
|
||||
|
||||
Filters: []Filter{},
|
||||
})
|
||||
}
|
||||
|
||||
// NewWithFilters returns a gin.HandlerFunc (middleware) that logs requests using slog.
|
||||
//
|
||||
// Requests with errors are logged using slog.Error().
|
||||
// Requests without errors are logged using slog.Info().
|
||||
func NewWithFilters(logger *slog.Logger, filters ...Filter) gin.HandlerFunc {
|
||||
return NewWithConfig(logger, Config{
|
||||
DefaultLevel: slog.LevelInfo,
|
||||
ClientErrorLevel: slog.LevelWarn,
|
||||
ServerErrorLevel: slog.LevelError,
|
||||
|
||||
WithRequestID: true,
|
||||
|
||||
Filters: filters,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -66,6 +86,12 @@ func NewWithConfig(logger *slog.Logger, config Config) gin.HandlerFunc {
|
||||
attributes = append(attributes, slog.String("request-id", requestID))
|
||||
}
|
||||
|
||||
for _, filter := range config.Filters {
|
||||
if !filter(c) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
switch {
|
||||
case c.Writer.Status() >= http.StatusBadRequest && c.Writer.Status() < http.StatusInternalServerError:
|
||||
logger.LogAttrs(context.Background(), config.ClientErrorLevel, c.Errors.String(), attributes...)
|
||||
|
||||
Reference in New Issue
Block a user