Skip to content

Commit 53b7420

Browse files
authored
Release/0.9.0 (#129)
* Added support of the YAML configuration file * Added support of the endpoint-related response actions * Replaced the Logrus logging library with ZeroLog
1 parent f57f9a2 commit 53b7420

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+2656
-1515
lines changed

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
VERSION := 0.8.9
1+
VERSION := 0.9.0
22
NAMESPACE := github.com/wallarm/api-firewall
33

44
.DEFAULT_GOAL := build
@@ -43,7 +43,7 @@ stop_k6_tests:
4343

4444
run_k6_tests: stop_k6_tests
4545
@docker compose -f resources/test/docker-compose-api-mode.yml up --build --detach --force-recreate
46-
docker run --rm -i --network host grafana/k6 run -v - <resources/test/specification/script.js || true
46+
docker run --rm -i --network host grafana/k6 run --vus 100 --iterations 1200 -v - <resources/test/specification/script.js || true
4747
$(MAKE) stop_k6_tests
4848

4949
.PHONY: lint tidy test fmt build genmocks vulncheck run_k6_tests stop_k6_tests

cmd/api-firewall/internal/handlers/api/app.go

Lines changed: 46 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import (
1111
"syscall"
1212

1313
"github.com/google/uuid"
14+
"github.com/rs/zerolog"
1415
"github.com/savsgio/gotils/strconv"
15-
"github.com/sirupsen/logrus"
1616
"github.com/valyala/fasthttp"
1717

1818
"github.com/wallarm/api-firewall/internal/platform/router"
@@ -31,7 +31,7 @@ var (
3131
// data/logic on this App struct
3232
type App struct {
3333
Routers map[int]*router.Mux
34-
Log *logrus.Logger
34+
Log zerolog.Logger
3535
passOPTIONS bool
3636
shutdown chan os.Signal
3737
mw []web.Middleware
@@ -40,7 +40,7 @@ type App struct {
4040
}
4141

4242
// NewApp creates an App value that handle a set of routes for the set of application.
43-
func NewApp(lock *sync.RWMutex, passOPTIONS bool, storedSpecs storage.DBOpenAPILoader, shutdown chan os.Signal, logger *logrus.Logger, mw ...web.Middleware) *App {
43+
func NewApp(lock *sync.RWMutex, passOPTIONS bool, storedSpecs storage.DBOpenAPILoader, shutdown chan os.Signal, logger zerolog.Logger, mw ...web.Middleware) *App {
4444

4545
schemaIDs := storedSpecs.SchemaIDs()
4646

@@ -136,10 +136,10 @@ func (a *App) APIModeMainHandler(ctx *fasthttp.RequestCtx) {
136136
// handle panic
137137
defer func() {
138138
if r := recover(); r != nil {
139-
a.Log.Errorf("panic: %v", r)
139+
a.Log.Error().Msgf("panic: %v", r)
140140

141141
// Log the Go stack trace for this panic'd goroutine.
142-
a.Log.Debugf("%s", debug.Stack())
142+
a.Log.Debug().Msgf("%s", debug.Stack())
143143
return
144144
}
145145
}()
@@ -151,22 +151,22 @@ func (a *App) APIModeMainHandler(ctx *fasthttp.RequestCtx) {
151151
if err != nil {
152152
defer web.LogRequestResponseAtTraceLevel(ctx, a.Log)
153153

154-
a.Log.WithFields(logrus.Fields{
155-
"error": err,
156-
"host": strconv.B2S(ctx.Request.Header.Host()),
157-
"path": strconv.B2S(ctx.Path()),
158-
"method": strconv.B2S(ctx.Request.Header.Method()),
159-
"request_id": ctx.UserValue(web.RequestID),
160-
}).Error("error while getting schema ID")
154+
a.Log.Error().
155+
Err(err).
156+
Bytes("host", ctx.Request.Header.Host()).
157+
Bytes("path", ctx.Path()).
158+
Bytes("method", ctx.Request.Header.Method()).
159+
Interface("request_id", ctx.UserValue(web.RequestID)).
160+
Msg("error while getting schema ID")
161161

162162
if err := web.RespondError(ctx, fasthttp.StatusInternalServerError, ""); err != nil {
163-
a.Log.WithFields(logrus.Fields{
164-
"error": err,
165-
"host": strconv.B2S(ctx.Request.Header.Host()),
166-
"path": strconv.B2S(ctx.Path()),
167-
"method": strconv.B2S(ctx.Request.Header.Method()),
168-
"request_id": ctx.UserValue(web.RequestID),
169-
}).Error("error while sending response")
163+
a.Log.Error().
164+
Err(err).
165+
Bytes("host", ctx.Request.Header.Host()).
166+
Bytes("path", ctx.Path()).
167+
Bytes("method", ctx.Request.Header.Method()).
168+
Interface("request_id", ctx.UserValue(web.RequestID)).
169+
Msg("error while sending response")
170170
}
171171

172172
return
@@ -196,22 +196,23 @@ func (a *App) APIModeMainHandler(ctx *fasthttp.RequestCtx) {
196196
// OPTIONS methods are passed if the passOPTIONS is set to true
197197
if a.passOPTIONS && strconv.B2S(ctx.Method()) == fasthttp.MethodOptions {
198198
ctx.SetUserValue(keyStatusCode, fasthttp.StatusOK)
199-
a.Log.WithFields(logrus.Fields{
200-
"host": strconv.B2S(ctx.Request.Header.Host()),
201-
"path": strconv.B2S(ctx.Path()),
202-
"method": strconv.B2S(ctx.Request.Header.Method()),
203-
"request_id": ctx.UserValue(web.RequestID),
204-
}).Debug("Pass request with OPTIONS method")
199+
a.Log.Debug().
200+
Bytes("host", ctx.Request.Header.Host()).
201+
Bytes("path", ctx.Path()).
202+
Bytes("method", ctx.Request.Header.Method()).
203+
Interface("request_id", ctx.UserValue(web.RequestID)).
204+
Msg("pass request with OPTIONS method")
205205
continue
206206
}
207207

208208
// Method or Path were not found
209-
a.Log.WithFields(logrus.Fields{
210-
"host": strconv.B2S(ctx.Request.Header.Host()),
211-
"path": strconv.B2S(ctx.Path()),
212-
"method": strconv.B2S(ctx.Request.Header.Method()),
213-
"request_id": ctx.UserValue(web.RequestID),
214-
}).Debug("Method or path were not found")
209+
a.Log.Debug().
210+
Bytes("host", ctx.Request.Header.Host()).
211+
Bytes("path", ctx.Path()).
212+
Bytes("method", ctx.Request.Header.Method()).
213+
Interface("request_id", ctx.UserValue(web.RequestID)).
214+
Msg("method or path were not found")
215+
215216
ctx.SetUserValue(keyValidationErrors, []*validator.ValidationError{{Message: validator.ErrMethodAndPathNotFound.Error(), Code: validator.ErrCodeMethodAndPathNotFound, SchemaID: &schemaID}})
216217
ctx.SetUserValue(keyStatusCode, fasthttp.StatusForbidden)
217218
continue
@@ -221,13 +222,13 @@ func (a *App) APIModeMainHandler(ctx *fasthttp.RequestCtx) {
221222
ctx.SetUserValue(router.RouteCtxKey, rctx)
222223

223224
if err := handler(ctx); err != nil {
224-
a.Log.WithFields(logrus.Fields{
225-
"error": err,
226-
"host": strconv.B2S(ctx.Request.Header.Host()),
227-
"path": strconv.B2S(ctx.Path()),
228-
"method": strconv.B2S(ctx.Request.Header.Method()),
229-
"request_id": ctx.UserValue(web.RequestID),
230-
}).Error("error in the request handler")
225+
a.Log.Error().
226+
Err(err).
227+
Bytes("host", ctx.Request.Header.Host()).
228+
Bytes("path", ctx.Path()).
229+
Bytes("method", ctx.Request.Header.Method()).
230+
Interface("request_id", ctx.UserValue(web.RequestID)).
231+
Msg("error in the request handler")
231232
}
232233
}
233234

@@ -286,13 +287,13 @@ func (a *App) APIModeMainHandler(ctx *fasthttp.RequestCtx) {
286287
}
287288

288289
if err := web.Respond(ctx, validator.ValidationResponse{Summary: responseSummary, Errors: responseErrors}, fasthttp.StatusOK); err != nil {
289-
a.Log.WithFields(logrus.Fields{
290-
"request_id": ctx.UserValue(web.RequestID),
291-
"host": strconv.B2S(ctx.Request.Header.Host()),
292-
"path": strconv.B2S(ctx.Path()),
293-
"method": strconv.B2S(ctx.Request.Header.Method()),
294-
"error": err,
295-
}).Error("respond error")
290+
a.Log.Error().
291+
Err(err).
292+
Bytes("host", ctx.Request.Header.Host()).
293+
Bytes("path", ctx.Path()).
294+
Bytes("method", ctx.Request.Header.Method()).
295+
Interface("request_id", ctx.UserValue(web.RequestID)).
296+
Msg("respond error")
296297
}
297298
}
298299

cmd/api-firewall/internal/handlers/api/handler.go

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ import (
44
"runtime/debug"
55
strconv2 "strconv"
66

7-
"github.com/savsgio/gotils/strconv"
8-
"github.com/sirupsen/logrus"
7+
"github.com/rs/zerolog"
98
"github.com/valyala/fasthttp"
109
"github.com/valyala/fastjson"
1110

@@ -19,7 +18,7 @@ import (
1918
type RequestValidator struct {
2019
CustomRoute *loader.CustomRoute
2120
OpenAPIRouter *loader.Router
22-
Log *logrus.Logger
21+
Log zerolog.Logger
2322
Cfg *config.APIMode
2423
ParserPool *fastjson.ParserPool
2524
SchemaID int
@@ -31,10 +30,10 @@ func (s *RequestValidator) Handler(ctx *fasthttp.RequestCtx) error {
3130
// handle panic
3231
defer func() {
3332
if r := recover(); r != nil {
34-
s.Log.Errorf("panic: %v", r)
33+
s.Log.Error().Msgf("panic: %v", r)
3534

3635
// Log the Go stack trace for this panic'd goroutine.
37-
s.Log.Debugf("%s", debug.Stack())
36+
s.Log.Debug().Msgf("%s", debug.Stack())
3837
return
3938
}
4039
}()
@@ -44,26 +43,28 @@ func (s *RequestValidator) Handler(ctx *fasthttp.RequestCtx) error {
4443

4544
// Route not found
4645
if s.CustomRoute == nil {
47-
s.Log.WithFields(logrus.Fields{
48-
"host": strconv.B2S(ctx.Request.Header.Host()),
49-
"path": strconv.B2S(ctx.Path()),
50-
"method": strconv.B2S(ctx.Request.Header.Method()),
51-
"request_id": ctx.UserValue(web.RequestID),
52-
}).Debug("Method or path were not found")
46+
s.Log.Debug().
47+
Interface("request_id", ctx.UserValue(web.RequestID)).
48+
Bytes("host", ctx.Request.Header.Host()).
49+
Bytes("path", ctx.Path()).
50+
Bytes("method", ctx.Request.Header.Method()).
51+
Msg("method or path were not found")
52+
5353
ctx.SetUserValue(keyValidationErrors, []*validator.ValidationError{{Message: validator.ErrMethodAndPathNotFound.Error(), Code: validator.ErrCodeMethodAndPathNotFound, SchemaID: &s.SchemaID}})
5454
ctx.SetUserValue(keyStatusCode, fasthttp.StatusForbidden)
5555
return nil
5656
}
5757

5858
validationErrors, err := apiMode.APIModeValidateRequest(ctx, s.ParserPool, s.CustomRoute, s.Cfg.UnknownParametersDetection)
5959
if err != nil {
60-
s.Log.WithFields(logrus.Fields{
61-
"error": err,
62-
"host": strconv.B2S(ctx.Request.Header.Host()),
63-
"path": strconv.B2S(ctx.Path()),
64-
"method": strconv.B2S(ctx.Request.Header.Method()),
65-
"request_id": ctx.UserValue(web.RequestID),
66-
}).Error("request validation error")
60+
s.Log.Error().
61+
Err(err).
62+
Interface("request_id", ctx.UserValue(web.RequestID)).
63+
Bytes("host", ctx.Request.Header.Host()).
64+
Bytes("path", ctx.Path()).
65+
Bytes("method", ctx.Request.Header.Method()).
66+
Msg("request validation error")
67+
6768
ctx.SetUserValue(keyStatusCode, fasthttp.StatusInternalServerError)
6869
return nil
6970
}
@@ -76,13 +77,13 @@ func (s *RequestValidator) Handler(ctx *fasthttp.RequestCtx) error {
7677
r.SchemaVersion = s.OpenAPIRouter.SchemaVersion
7778
}
7879

79-
s.Log.WithFields(logrus.Fields{
80-
"error": validationErrors,
81-
"host": strconv.B2S(ctx.Request.Header.Host()),
82-
"path": strconv.B2S(ctx.Path()),
83-
"method": strconv.B2S(ctx.Request.Header.Method()),
84-
"request_id": ctx.UserValue(web.RequestID),
85-
}).Debug("request validation error")
80+
s.Log.Debug().
81+
Interface("error", validationErrors).
82+
Interface("request_id", ctx.UserValue(web.RequestID)).
83+
Bytes("host", ctx.Request.Header.Host()).
84+
Bytes("path", ctx.Path()).
85+
Bytes("method", ctx.Request.Header.Method()).
86+
Msg("request validation error")
8687

8788
ctx.SetUserValue(keyValidationErrors, validationErrors)
8889
ctx.SetUserValue(keyStatusCode, fasthttp.StatusForbidden)

cmd/api-firewall/internal/handlers/api/health.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,13 @@ package api
33
import (
44
"os"
55

6-
"github.com/sirupsen/logrus"
76
"github.com/valyala/fasthttp"
87
"github.com/wallarm/api-firewall/internal/platform/storage"
98
"github.com/wallarm/api-firewall/internal/platform/web"
109
"github.com/wallarm/api-firewall/internal/version"
1110
)
1211

1312
type Health struct {
14-
Logger *logrus.Logger
1513
OpenAPIDB storage.DBOpenAPILoader
1614
}
1715

cmd/api-firewall/internal/handlers/api/routes.go

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
package api
22

33
import (
4+
"github.com/rs/zerolog"
45
"net/url"
56
"os"
67
"runtime/debug"
78
"sync"
89

910
"github.com/corazawaf/coraza/v3"
10-
"github.com/sirupsen/logrus"
11+
"github.com/rs/zerolog/log"
1112
"github.com/valyala/fasthttp"
1213
"github.com/valyala/fastjson"
1314

@@ -19,15 +20,15 @@ import (
1920
"github.com/wallarm/api-firewall/internal/platform/web"
2021
)
2122

22-
func Handlers(lock *sync.RWMutex, cfg *config.APIMode, shutdown chan os.Signal, logger *logrus.Logger, storedSpecs storage.DBOpenAPILoader, AllowedIPCache *allowiplist.AllowedIPsType, waf coraza.WAF) fasthttp.RequestHandler {
23+
func Handlers(lock *sync.RWMutex, cfg *config.APIMode, shutdown chan os.Signal, logger zerolog.Logger, storedSpecs storage.DBOpenAPILoader, AllowedIPCache *allowiplist.AllowedIPsType, waf coraza.WAF) fasthttp.RequestHandler {
2324

2425
// handle panic
2526
defer func() {
2627
if r := recover(); r != nil {
27-
logger.Errorf("panic: %v", r)
28+
log.Error().Msgf("panic: %v", r)
2829

2930
// Log the Go stack trace for this panic'd goroutine.
30-
logger.Debugf("%s", debug.Stack())
31+
log.Debug().Msgf("%s", debug.Stack())
3132
return
3233
}
3334
}()
@@ -61,13 +62,13 @@ func Handlers(lock *sync.RWMutex, cfg *config.APIMode, shutdown chan os.Signal,
6162
if servers != nil {
6263
var err error
6364
if serverURLStr, err = servers.BasePath(); err != nil {
64-
logger.Errorf("getting server URL from OpenAPI specification: %v", err)
65+
log.Error().Msgf("getting server URL from OpenAPI specification: %v", err)
6566
}
6667
}
6768

6869
serverURL, err := url.Parse(serverURLStr)
6970
if err != nil {
70-
logger.Errorf("parsing server URL from OpenAPI specification: %v", err)
71+
log.Error().Msgf("parsing server URL from OpenAPI specification: %v", err)
7172
}
7273

7374
if serverURL.Path == "" {
@@ -77,35 +78,36 @@ func Handlers(lock *sync.RWMutex, cfg *config.APIMode, shutdown chan os.Signal,
7778
// get new router
7879
newSwagRouter, err := loader.NewRouterDBLoader(storedSpecs.SpecificationVersion(schemaID), storedSpecs.Specification(schemaID))
7980
if err != nil {
80-
logger.WithFields(logrus.Fields{"error": err}).Error("New router creation failed")
81+
log.Fatal().Err(err).Msg("new router creation failed")
8182
}
8283

8384
for i := 0; i < len(newSwagRouter.Routes); i++ {
8485

8586
s := RequestValidator{
8687
CustomRoute: &newSwagRouter.Routes[i],
87-
Log: logger,
8888
Cfg: cfg,
8989
ParserPool: &parserPool,
9090
OpenAPIRouter: newSwagRouter,
9191
SchemaID: schemaID,
9292
}
9393
updRoutePathEsc, err := url.JoinPath(serverURL.Path, newSwagRouter.Routes[i].Path)
9494
if err != nil {
95-
s.Log.Errorf("url parse error: Schema ID %d: OpenAPI version %s: Loaded path %s - %v", schemaID, storedSpecs.SpecificationVersion(schemaID), newSwagRouter.Routes[i].Path, err)
95+
log.Error().Msgf("url parse error: Schema ID %d: openAPI version %s: loaded path %s - %v", schemaID, storedSpecs.SpecificationVersion(schemaID), newSwagRouter.Routes[i].Path, err)
9696
continue
9797
}
9898

9999
updRoutePath, err := url.PathUnescape(updRoutePathEsc)
100100
if err != nil {
101-
s.Log.Errorf("url unescape error: Schema ID %d: OpenAPI version %s: Loaded path %s - %v", schemaID, storedSpecs.SpecificationVersion(schemaID), newSwagRouter.Routes[i].Path, err)
101+
log.Error().Msgf("url unescape error: schema ID %d: openAPI version %s: loaded path %s - %v", schemaID, storedSpecs.SpecificationVersion(schemaID), newSwagRouter.Routes[i].Path, err)
102102
continue
103103
}
104104

105-
s.Log.Debugf("handler: Schema ID %d: OpenAPI version %s: Loaded path %s - %s", schemaID, storedSpecs.SpecificationVersion(schemaID), newSwagRouter.Routes[i].Method, updRoutePath)
105+
log.Debug().Msgf("handler: schema ID %d: openAPI version %s: loaded path %s - %s", schemaID, storedSpecs.SpecificationVersion(schemaID), newSwagRouter.Routes[i].Method, updRoutePath)
106106

107107
if err := apps.Handle(schemaID, newSwagRouter.Routes[i].Method, updRoutePath, s.Handler); err != nil {
108-
logger.WithFields(logrus.Fields{"error": err, "schema_id": schemaID}).Errorf("The OAS endpoint registration failed: method %s, path %s", newSwagRouter.Routes[i].Method, updRoutePath)
108+
log.Error().Err(err).
109+
Int("schema_id", schemaID).
110+
Msgf("the OAS endpoint registration failed: method %s, path %s", newSwagRouter.Routes[i].Method, updRoutePath)
109111
}
110112
}
111113

0 commit comments

Comments
 (0)