From 127b79e14836e490cd210e64015a652931b26a15 Mon Sep 17 00:00:00 2001 From: jonaustin09 Date: Mon, 19 Jun 2023 23:18:16 +0400 Subject: [PATCH] feat: Logging system set up --- s3api/controllers/base.go | 23 +++++++++++------ s3api/controllers/base_test.go | 34 +++++++++++++++++++------ s3api/middlewares/logger.go | 42 +++++++++++++++++++++++++++++++ s3api/server.go | 8 +++++- s3api/utils/logger.go | 46 ++++++++++++++++++++++++++++++++++ 5 files changed, 137 insertions(+), 16 deletions(-) create mode 100644 s3api/middlewares/logger.go create mode 100644 s3api/utils/logger.go diff --git a/s3api/controllers/base.go b/s3api/controllers/base.go index 9d32cc5..7d2df77 100644 --- a/s3api/controllers/base.go +++ b/s3api/controllers/base.go @@ -20,8 +20,8 @@ import ( "errors" "fmt" "io" + "log" "net/http" - "os" "strconv" "strings" @@ -138,7 +138,7 @@ func (c S3ApiController) GetActions(ctx *fiber.Ctx) error { Value: lastmod, }, }) - return ctx.SendStatus(http.StatusOK) + return SendResponse(ctx, err) } func getstring(s *string) string { @@ -531,20 +531,23 @@ func (c S3ApiController) CreateActions(ctx *fiber.Ctx) error { } func SendResponse(ctx *fiber.Ctx, err error) error { + utils.LogPathParams(ctx) if err != nil { serr, ok := err.(s3err.APIError) if ok { ctx.Status(serr.HTTPStatusCode) + log.Printf("%s: %v", serr.Code, err) return ctx.Send(s3err.GetAPIErrorResponse(serr, "", "", "")) } - fmt.Fprintf(os.Stderr, "Internal Error, req:\n%v\nerr: %v\n", - ctx.Request().Header.String(), err) - + log.Printf("Internal Error, %v", err) + ctx.Status(http.StatusInternalServerError) return ctx.Send(s3err.GetAPIErrorResponse( s3err.GetAPIError(s3err.ErrInternalError), "", "", "")) } + utils.LogResponseHeaders(&ctx.Response().Header) + // https://github.com/gofiber/fiber/issues/2080 // ctx.SendStatus() sets incorrect content length on HEAD request ctx.Status(http.StatusOK) @@ -552,15 +555,17 @@ func SendResponse(ctx *fiber.Ctx, err error) error { } func SendXMLResponse(ctx *fiber.Ctx, resp any, err error) error { + utils.LogPathParams(ctx) if err != nil { serr, ok := err.(s3err.APIError) if ok { ctx.Status(serr.HTTPStatusCode) + log.Printf("%s: %v", serr.Code, err) return ctx.Send(s3err.GetAPIErrorResponse(serr, "", "", "")) } - fmt.Fprintf(os.Stderr, "Internal Error, req:\n%v\nerr: %v\n", - ctx.Request().Header.String(), err) + log.Printf("Internal Error, %v", err) + ctx.Status(http.StatusInternalServerError) return ctx.Send(s3err.GetAPIErrorResponse( s3err.GetAPIError(s3err.ErrInternalError), "", "", "")) @@ -578,5 +583,9 @@ func SendXMLResponse(ctx *fiber.Ctx, resp any, err error) error { } } + utils.LogResponseHeaders(&ctx.Response().Header) + fmt.Println() + log.Printf("Response Body: %s", b) + return ctx.Send(b) } diff --git a/s3api/controllers/base_test.go b/s3api/controllers/base_test.go index 229c84a..abf387a 100644 --- a/s3api/controllers/base_test.go +++ b/s3api/controllers/base_test.go @@ -26,7 +26,6 @@ import ( "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/aws/aws-sdk-go-v2/service/s3/types" "github.com/gofiber/fiber/v2" - "github.com/valyala/fasthttp" "github.com/versity/versitygw/backend" "github.com/versity/versitygw/backend/auth" "github.com/versity/versitygw/s3err" @@ -1106,6 +1105,15 @@ func Test_XMLresponse(t *testing.T) { } app := fiber.New() + var ctx fiber.Ctx + // Mocking the fiber ctx + app.Get("/:bucket/:key", func(c *fiber.Ctx) error { + ctx = *c + return nil + }) + + app.Test(httptest.NewRequest(http.MethodGet, "/my-bucket/my-key", nil)) + tests := []struct { name string args args @@ -1115,7 +1123,7 @@ func Test_XMLresponse(t *testing.T) { { name: "Internal-server-error", args: args{ - ctx: app.AcquireCtx(&fasthttp.RequestCtx{}), + ctx: &ctx, resp: nil, err: s3err.GetAPIError(16), }, @@ -1125,7 +1133,7 @@ func Test_XMLresponse(t *testing.T) { { name: "Error-not-implemented", args: args{ - ctx: app.AcquireCtx(&fasthttp.RequestCtx{}), + ctx: &ctx, resp: nil, err: s3err.GetAPIError(50), }, @@ -1135,7 +1143,7 @@ func Test_XMLresponse(t *testing.T) { { name: "Invalid-request-body", args: args{ - ctx: app.AcquireCtx(&fasthttp.RequestCtx{}), + ctx: &ctx, resp: make(chan int), err: nil, }, @@ -1145,7 +1153,7 @@ func Test_XMLresponse(t *testing.T) { { name: "Successful-response", args: args{ - ctx: app.AcquireCtx(&fasthttp.RequestCtx{}), + ctx: &ctx, resp: "Valid response", err: nil, }, @@ -1164,6 +1172,8 @@ func Test_XMLresponse(t *testing.T) { if statusCode != tt.statusCode { t.Errorf("response() %v code = %v, wantErr %v", tt.name, statusCode, tt.wantErr) } + + tt.args.ctx.Status(http.StatusOK) }) } } @@ -1175,6 +1185,14 @@ func Test_response(t *testing.T) { err error } app := fiber.New() + var ctx fiber.Ctx + // Mocking the fiber ctx + app.Get("/:bucket/:key", func(c *fiber.Ctx) error { + ctx = *c + return nil + }) + + app.Test(httptest.NewRequest(http.MethodGet, "/my-bucket/my-key", nil)) tests := []struct { name string @@ -1185,7 +1203,7 @@ func Test_response(t *testing.T) { { name: "Internal-server-error", args: args{ - ctx: app.AcquireCtx(&fasthttp.RequestCtx{}), + ctx: &ctx, resp: nil, err: s3err.GetAPIError(16), }, @@ -1195,7 +1213,7 @@ func Test_response(t *testing.T) { { name: "Error-not-implemented", args: args{ - ctx: app.AcquireCtx(&fasthttp.RequestCtx{}), + ctx: &ctx, resp: nil, err: s3err.GetAPIError(50), }, @@ -1205,7 +1223,7 @@ func Test_response(t *testing.T) { { name: "Successful-response", args: args{ - ctx: app.AcquireCtx(&fasthttp.RequestCtx{}), + ctx: &ctx, resp: "Valid response", err: nil, }, diff --git a/s3api/middlewares/logger.go b/s3api/middlewares/logger.go new file mode 100644 index 0000000..217641b --- /dev/null +++ b/s3api/middlewares/logger.go @@ -0,0 +1,42 @@ +// Copyright 2023 Versity Software +// This file is licensed under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package middlewares + +import ( + "fmt" + "log" + + "github.com/gofiber/fiber/v2" + "github.com/versity/versitygw/s3api/utils" +) + +func RequestLogger(ctx *fiber.Ctx) error { + utils.LogRequestHeaders(&ctx.Request().Header) + + if len(ctx.Body()) > 0 { + fmt.Println() + log.Printf("Request Body: %s", ctx.Request().Body()) + } + + if ctx.Request().URI().QueryArgs().Len() != 0 { + fmt.Println() + log.Println("Request query arguments: ") + ctx.Request().URI().QueryArgs().VisitAll(func(key, val []byte) { + log.Printf("%s: %s", key, val) + }) + } + + return ctx.Next() +} diff --git a/s3api/server.go b/s3api/server.go index 1588dab..0f33db2 100644 --- a/s3api/server.go +++ b/s3api/server.go @@ -45,10 +45,16 @@ func New(app *fiber.App, be backend.Backend, root middlewares.RootUserConfig, po opt(server) } - app.Use(middlewares.VerifyV4Signature(root, iam, server.debug)) + // Logging middlewares app.Use(logger.New()) + app.Use(middlewares.RequestLogger) + + // Authentication middlewares + app.Use(middlewares.VerifyV4Signature(root, iam, server.debug)) app.Use(middlewares.VerifyMD5Body()) + server.router.Init(app, be, iam) + return server, nil } diff --git a/s3api/utils/logger.go b/s3api/utils/logger.go new file mode 100644 index 0000000..2ed8f95 --- /dev/null +++ b/s3api/utils/logger.go @@ -0,0 +1,46 @@ +// Copyright 2023 Versity Software +// This file is licensed under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package utils + +import ( + "fmt" + "log" + + "github.com/gofiber/fiber/v2" + "github.com/valyala/fasthttp" +) + +func LogRequestHeaders(headers *fasthttp.RequestHeader) { + log.Println("Request Headers: ") + headers.VisitAll(func(key, val []byte) { + log.Printf("%s: %s", key, val) + }) +} + +func LogResponseHeaders(headers *fasthttp.ResponseHeader) { + fmt.Println() + log.Println("Response Headers: ") + headers.VisitAll(func(key, val []byte) { + log.Printf("%s: %s", key, val) + }) +} + +func LogPathParams(ctx *fiber.Ctx) { + fmt.Println() + log.Println("Path parameters: ") + for key, val := range ctx.AllParams() { + log.Printf("%s: %s", key, val) + } +}