|
| 1 | +package middleware |
| 2 | + |
| 3 | +import ( |
| 4 | + "bytes" |
| 5 | + "encoding/json" |
| 6 | + "fmt" |
| 7 | + "io" |
| 8 | + "net/http" |
| 9 | + "net/http/httptest" |
| 10 | + "testing" |
| 11 | + |
| 12 | + ce "github.com/content-services/content-sources-backend/pkg/errors" |
| 13 | + "github.com/labstack/echo/v4" |
| 14 | + "github.com/stretchr/testify/assert" |
| 15 | +) |
| 16 | + |
| 17 | +const TestBody = `{"limit": 100, "search": "random", "uuids": ["e88efd75-2b29-4b59-8867-bb60435b3742"]}` |
| 18 | +const LargeBody = `{"limit": 100, "search": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Integer pellentesque quam vel velit. Vivamus porttitor turpis ac leo. Ut tempus purus at lorem. Nullam justo enim, consectetuer nec, ullamcorper ac, vestibulum in, elit. Nulla pulvinar eleifend sem. Proin mattis lacinia justo. Integer malesuada. Etiam sapien elit, consequat eget, tristique non, venenatis quis, ante. Etiam dui sem, fermentum vitae, sagittis id, malesuada in, quam. Integer lacinia. Proin pede metus, vulputate nec, fermentum fringilla, vehicula vitae, justo. Curabitur bibendum justo non orci. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Etiam sapien elit, consequat eget, tristique non, venenatis quis, ante. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Maecenas sollicitudin. Quisque porta. Nullam sapien sem, ornare ac, nonummy non, lobortis a enim. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Maecenas sollicitudin. Quisque porta. Nullam sapien sem, ornare ac, nonummy non, lobortis a enim.", "uuids": ["e88efd75-2b29-4b59-8867-bb60435b3742"]}` |
| 19 | + |
| 20 | +func TestReadBodyStoreAndRestore(t *testing.T) { |
| 21 | + e := echo.New() |
| 22 | + req := httptest.NewRequest(http.MethodPost, "/", bytes.NewBufferString(TestBody)) |
| 23 | + rec := httptest.NewRecorder() |
| 24 | + c := e.NewContext(req, rec) |
| 25 | + h := LogServerErrorRequest(func(c echo.Context) error { |
| 26 | + return c.JSON(http.StatusInternalServerError, map[string]string{ |
| 27 | + "status": fmt.Sprintf("%d", http.StatusInternalServerError), |
| 28 | + "title": "testing error", |
| 29 | + }) |
| 30 | + }) |
| 31 | + |
| 32 | + _ = h(c) |
| 33 | + |
| 34 | + var reqBody []byte |
| 35 | + if c.Request().Body != nil { |
| 36 | + reqBody, _ = io.ReadAll(c.Request().Body) |
| 37 | + } |
| 38 | + |
| 39 | + storedBody := c.Get(BodyStoreKey) |
| 40 | + storedBodyBytes, ok := storedBody.([]byte) |
| 41 | + if !ok { |
| 42 | + assert.Fail(t, "Failed type assertion of stored body.") |
| 43 | + } |
| 44 | + |
| 45 | + assert.Equal(t, http.StatusInternalServerError, rec.Code) |
| 46 | + assert.Equal(t, TestBody, string(storedBodyBytes)) |
| 47 | + assert.Equal(t, TestBody, string(reqBody)) |
| 48 | +} |
| 49 | + |
| 50 | +func TestLargeBodyCutoff(t *testing.T) { |
| 51 | + e := echo.New() |
| 52 | + req := httptest.NewRequest(http.MethodPost, "/", bytes.NewBufferString(LargeBody)) |
| 53 | + rec := httptest.NewRecorder() |
| 54 | + c := e.NewContext(req, rec) |
| 55 | + h := LogServerErrorRequest(func(c echo.Context) error { |
| 56 | + return c.JSON(http.StatusInternalServerError, map[string]string{ |
| 57 | + "status": fmt.Sprintf("%d", http.StatusInternalServerError), |
| 58 | + "title": "testing error", |
| 59 | + }) |
| 60 | + }) |
| 61 | + |
| 62 | + _ = h(c) |
| 63 | + |
| 64 | + var reqBody []byte |
| 65 | + if c.Request().Body != nil { |
| 66 | + reqBody, _ = io.ReadAll(c.Request().Body) |
| 67 | + } |
| 68 | + |
| 69 | + storedBody := c.Get(BodyStoreKey) |
| 70 | + storedBodyBytes, ok := storedBody.([]byte) |
| 71 | + if !ok { |
| 72 | + assert.Fail(t, "Failed type assertion of stored body.") |
| 73 | + } |
| 74 | + |
| 75 | + assert.Equal(t, http.StatusInternalServerError, rec.Code) |
| 76 | + assert.Equal(t, LargeBody[:1000], string(storedBodyBytes)) |
| 77 | + assert.Equal(t, LargeBody, string(reqBody)) |
| 78 | +} |
| 79 | + |
| 80 | +func TestRequestBodyLogging(t *testing.T) { |
| 81 | + e := echo.New() |
| 82 | + req := httptest.NewRequest(http.MethodPost, "/", bytes.NewBufferString(TestBody)) |
| 83 | + rec := httptest.NewRecorder() |
| 84 | + c := e.NewContext(req, rec) |
| 85 | + c.Set(BodyStoreKey, []byte(TestBody)) |
| 86 | + buf := new(bytes.Buffer) |
| 87 | + c.Logger().SetOutput(buf) |
| 88 | + h := LogServerErrorRequest(func(c echo.Context) error { |
| 89 | + return ce.NewErrorResponse(http.StatusInternalServerError, "Test Error", "5xx testing error") |
| 90 | + }) |
| 91 | + |
| 92 | + _ = h(c) |
| 93 | + |
| 94 | + log := make(map[string]string) |
| 95 | + _ = json.Unmarshal(buf.Bytes(), &log) |
| 96 | + |
| 97 | + assert.True(t, bytes.Contains(buf.Bytes(), []byte("\"message\":\"Request body: {\\\"limit\\\": 100, \\\"search\\\": \\\"random\\\", \\\"uuids\\\": [\\\"e88efd75-2b29-4b59-8867-bb60435b3742\\\"]}\"}"))) |
| 98 | + assert.Equal(t, log["message"], fmt.Sprintf("Request body: %s", TestBody)) |
| 99 | + assert.Equal(t, log["level"], "ERROR") |
| 100 | +} |
| 101 | + |
| 102 | +func TestMethodWithoutBody(t *testing.T) { |
| 103 | + e := echo.New() |
| 104 | + req := httptest.NewRequest(http.MethodGet, "/", nil) |
| 105 | + rec := httptest.NewRecorder() |
| 106 | + c := e.NewContext(req, rec) |
| 107 | + buf := new(bytes.Buffer) |
| 108 | + c.Logger().SetOutput(buf) |
| 109 | + h := LogServerErrorRequest(func(c echo.Context) error { |
| 110 | + return ce.NewErrorResponse(http.StatusInternalServerError, "Test Error", "5xx testing error") |
| 111 | + }) |
| 112 | + |
| 113 | + _ = h(c) |
| 114 | + |
| 115 | + log := make(map[string]string) |
| 116 | + _ = json.Unmarshal(buf.Bytes(), &log) |
| 117 | + |
| 118 | + assert.Equal(t, []byte(nil), buf.Bytes()) |
| 119 | +} |
0 commit comments