goyave.dev/goyave/v5@v5.0.0-rc9.0.20240517145003-d3f977d0b9f3/middleware/parse/parse_test.go (about) 1 package parse 2 3 import ( 4 "bytes" 5 "mime/multipart" 6 "net/http" 7 "strings" 8 "testing" 9 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 "goyave.dev/goyave/v5" 13 "goyave.dev/goyave/v5/config" 14 "goyave.dev/goyave/v5/util/fsutil" 15 "goyave.dev/goyave/v5/util/fsutil/osfs" 16 "goyave.dev/goyave/v5/util/testutil" 17 ) 18 19 func TestParseMiddleware(t *testing.T) { 20 21 server := testutil.NewTestServerWithOptions(t, goyave.Options{Config: config.LoadDefault()}) 22 23 t.Run("Max Upload Size", func(t *testing.T) { 24 m := &Middleware{} 25 m.Init(server.Server) 26 assert.InEpsilon(t, 10.0, m.getMaxUploadSize(), 0) // Default 27 m.MaxUploadSize = 2.3 28 assert.InEpsilon(t, 2.3, m.getMaxUploadSize(), 0) 29 30 m = &Middleware{ 31 MaxUploadSize: 2.3, 32 } 33 m.Init(server.Server) 34 assert.InEpsilon(t, 2.3, m.getMaxUploadSize(), 0) 35 }) 36 37 t.Run("Parse Query", func(t *testing.T) { 38 request := testutil.NewTestRequest(http.MethodGet, "/parse?a=b&c=d&array=1&array=2", nil) 39 40 result := server.TestMiddleware(&Middleware{}, request, func(_ *goyave.Response, req *goyave.Request) { 41 expected := map[string]any{ 42 "a": "b", 43 "c": "d", 44 "array": []string{"1", "2"}, 45 } 46 assert.Equal(t, expected, req.Query) 47 }) 48 assert.NoError(t, result.Body.Close()) 49 }) 50 51 t.Run("Parse Query Error", func(t *testing.T) { 52 request := testutil.NewTestRequest(http.MethodGet, "/parse?inv;alid", nil) 53 54 result := server.TestMiddleware(&Middleware{}, request, func(_ *goyave.Response, req *goyave.Request) { 55 assert.Equal(t, map[string]any{}, req.Query) 56 }) 57 assert.NoError(t, result.Body.Close()) 58 assert.Equal(t, http.StatusBadRequest, result.StatusCode) 59 }) 60 61 t.Run("Entity Too Large", func(t *testing.T) { 62 request := testutil.NewTestRequest(http.MethodPost, "/parse", strings.NewReader(strings.Repeat("a", 1024*1024))) 63 request.Header().Set("Content-Type", "application/octet-stream") 64 65 result := server.TestMiddleware(&Middleware{MaxUploadSize: 0.01}, request, func(_ *goyave.Response, _ *goyave.Request) { 66 assert.Fail(t, "Middleware should not pass") 67 }) 68 assert.NoError(t, result.Body.Close()) 69 assert.Equal(t, http.StatusRequestEntityTooLarge, result.StatusCode) 70 }) 71 72 t.Run("JSON", func(t *testing.T) { 73 data := map[string]any{ 74 "a": "b", 75 "c": "d", 76 "e": map[string]any{ 77 "f": "g", 78 }, 79 "h": []string{"i", "j"}, 80 } 81 82 request := testutil.NewTestRequest(http.MethodPost, "/parse", testutil.ToJSON(data)) 83 request.Header().Set("Content-Type", "application/json") 84 85 result := server.TestMiddleware(&Middleware{}, request, func(resp *goyave.Response, req *goyave.Request) { 86 expected := map[string]any{ 87 "a": "b", 88 "c": "d", 89 "e": map[string]any{ 90 "f": "g", 91 }, 92 "h": []any{"i", "j"}, 93 } 94 assert.Equal(t, expected, req.Data) 95 resp.Status(http.StatusOK) 96 }) 97 98 assert.NoError(t, result.Body.Close()) 99 assert.Equal(t, http.StatusOK, result.StatusCode) 100 }) 101 102 t.Run("JSON Invalid", func(t *testing.T) { 103 request := testutil.NewTestRequest(http.MethodPost, "/parse", bytes.NewBuffer([]byte("{\"unclosed\""))) 104 request.Header().Set("Content-Type", "application/json") 105 106 result := server.TestMiddleware(&Middleware{MaxUploadSize: 0.01}, request, func(_ *goyave.Response, _ *goyave.Request) { 107 assert.Fail(t, "Middleware should not pass") 108 }) 109 assert.NoError(t, result.Body.Close()) 110 assert.Equal(t, http.StatusBadRequest, result.StatusCode) 111 }) 112 113 t.Run("Multipart", func(t *testing.T) { 114 body := &bytes.Buffer{} 115 writer := multipart.NewWriter(body) 116 require.NoError(t, testutil.WriteMultipartFile(writer, &osfs.FS{}, "../../resources/img/logo/goyave_16.png", "profile_picture", "goyave_16.png")) 117 require.NoError(t, writer.WriteField("email", "johndoe@example.org")) 118 119 request := testutil.NewTestRequest(http.MethodPost, "/parse", body) 120 request.Header().Set("Content-Type", writer.FormDataContentType()) 121 122 require.NoError(t, writer.Close()) 123 124 result := server.TestMiddleware(&Middleware{}, request, func(resp *goyave.Response, req *goyave.Request) { 125 data, ok := req.Data.(map[string]any) 126 if !assert.True(t, ok) { 127 return 128 } 129 assert.Equal(t, "johndoe@example.org", data["email"]) 130 131 picture, ok := data["profile_picture"].([]fsutil.File) 132 if !assert.True(t, ok) { 133 return 134 } 135 136 if !assert.Len(t, picture, 1) { 137 return 138 } 139 assert.Equal(t, "image/png", picture[0].MIMEType) 140 assert.Equal(t, "goyave_16.png", picture[0].Header.Filename) 141 assert.Equal(t, int64(716), picture[0].Header.Size) 142 143 resp.Status(http.StatusOK) 144 }) 145 146 assert.NoError(t, result.Body.Close()) 147 assert.Equal(t, http.StatusOK, result.StatusCode) 148 }) 149 150 t.Run("Form URL-encoded", func(t *testing.T) { 151 data := "a=b&c=d&h=i&h=j" 152 153 request := testutil.NewTestRequest(http.MethodPost, "/parse", strings.NewReader(data)) 154 request.Header().Set("Content-Type", "application/x-www-form-urlencoded; param=value") 155 156 result := server.TestMiddleware(&Middleware{}, request, func(resp *goyave.Response, req *goyave.Request) { 157 expected := map[string]any{ 158 "a": "b", 159 "c": "d", 160 "h": []string{"i", "j"}, 161 } 162 assert.Equal(t, expected, req.Data) 163 resp.Status(http.StatusOK) 164 }) 165 166 assert.NoError(t, result.Body.Close()) 167 assert.Equal(t, http.StatusOK, result.StatusCode) 168 }) 169 170 t.Run("Body already parsed", func(t *testing.T) { 171 data := map[string]any{ 172 "a": "b", 173 "c": "d", 174 "e": map[string]any{ 175 "f": "g", 176 }, 177 "h": []string{"i", "j"}, 178 } 179 request := testutil.NewTestRequest(http.MethodPost, "/parse?a=b&c=d&array=1&array=2", testutil.ToJSON(data)) 180 request.Data = map[string]any{"a": "b"} 181 182 result := server.TestMiddleware(&Middleware{}, request, func(_ *goyave.Response, req *goyave.Request) { 183 expectedQuery := map[string]any{ 184 "a": "b", 185 "c": "d", 186 "array": []string{"1", "2"}, 187 } 188 assert.Equal(t, expectedQuery, req.Query) // Query parsed but not body 189 assert.Equal(t, map[string]any{"a": "b"}, req.Data) 190 }) 191 assert.NoError(t, result.Body.Close()) 192 }) 193 }