github.com/avenga/couper@v1.12.2/server/multi_files_test.go (about) 1 package server_test 2 3 import ( 4 "fmt" 5 "io" 6 "net/http" 7 "path/filepath" 8 "strings" 9 "testing" 10 11 "github.com/avenga/couper/config/configload" 12 "github.com/avenga/couper/internal/test" 13 ) 14 15 func TestMultiFiles_Server(t *testing.T) { 16 helper := test.New(t) 17 client := newClient() 18 19 shutdown, hook := newCouperMultiFiles( 20 "testdata/multi/server/couper.hcl", 21 "testdata/multi/server/couper.d", 22 helper, 23 ) 24 defer shutdown() 25 26 for _, entry := range hook.AllEntries() { 27 t.Log(entry.String()) 28 } 29 30 req, err := http.NewRequest(http.MethodGet, "http://example.com:8080/", nil) 31 helper.Must(err) 32 33 _, err = client.Do(req) 34 if err == nil || err.Error() != `Get "http://example.com:8080/": dial tcp4 127.0.0.1:8080: connect: connection refused` { 35 t.Error("Expected hosts port override to 9080") 36 } 37 38 type testcase struct { 39 url string 40 header test.Header 41 expStatus int 42 expBody string 43 } 44 45 token := "eyJhbGciOiJSUzI1NiIsImtpZCI6InJzMjU2IiwidHlwIjoiSldUIn0.eyJzdWIiOjEyMzQ1Njc4OTB9.AZ0gZVqPe9TjjjJO0GnlTvERBXhPyxW_gTn050rCoEkseFRlp4TYry7WTQ7J4HNrH3btfxaEQLtTv7KooVLXQyMDujQbKU6cyuYH6MZXaM0Co3Bhu0awoX-2GVk997-7kMZx2yvwIR5ypd1CERIbNs5QcQaI4sqx_8oGrjO5ZmOWRqSpi4Mb8gJEVVccxurPu65gPFq9esVWwTf4cMQ3GGzijatnGDbRWs_igVGf8IAfmiROSVd17fShQtfthOFd19TGUswVAleOftC7-DDeJgAK8Un5xOHGRjv3ypK_6ZLRonhswaGXxovE0kLq4ZSzumQY2hOFE6x_BbrR1WKtGw" 46 47 for _, tc := range []testcase{ 48 {"http://example.com:9080/", nil, http.StatusOK, "<body>RIGHT INCLUDE</body>\n"}, 49 {"http://example.com:9080/free", nil, http.StatusForbidden, ""}, 50 {"http://example.com:9080/errors/", test.Header{"Authorization": "Bearer " + token}, http.StatusTeapot, ""}, 51 {"http://example.com:9080/api-111", nil, http.StatusUnauthorized, ""}, 52 {"http://example.com:9080/api-3", nil, http.StatusTeapot, ""}, 53 {"http://example.com:9080/api-4/ep", nil, http.StatusNoContent, ""}, 54 {"http://example.com:9081/", nil, http.StatusOK, ""}, 55 {"http://example.com:8082/", nil, http.StatusOK, ""}, 56 {"http://example.com:8083/", nil, http.StatusNotFound, ""}, 57 {"http://example.com:9084/", nil, http.StatusNotFound, ""}, 58 } { 59 req, err = http.NewRequest(http.MethodGet, tc.url, nil) 60 helper.Must(err) 61 62 for k, v := range tc.header { 63 req.Header.Set(k, v) 64 } 65 66 res, err := client.Do(req) 67 helper.Must(err) 68 69 if res.StatusCode != tc.expStatus { 70 t.Errorf("request %q: want status %d, got %d", tc.url, tc.expStatus, res.StatusCode) 71 } 72 73 if tc.expBody == "" { 74 continue 75 } 76 77 var resBytes []byte 78 resBytes, err = io.ReadAll(res.Body) 79 helper.Must(err) 80 _ = res.Body.Close() 81 82 if string(resBytes) != tc.expBody { 83 t.Errorf("request %q unexpected content: %s", tc.url, resBytes) 84 } 85 } 86 } 87 88 func TestMultiFiles_SettingsAndDefaults(t *testing.T) { 89 helper := test.New(t) 90 client := newClient() 91 92 shutdown, _ := newCouperMultiFiles( 93 "testdata/multi/settings/couper.hcl", 94 "testdata/multi/settings/couper.d", 95 helper, 96 ) 97 defer shutdown() 98 99 req, err := http.NewRequest(http.MethodGet, "http://example.com:8080/", nil) 100 helper.Must(err) 101 102 res, err := client.Do(req) 103 helper.Must(err) 104 105 resBytes, err := io.ReadAll(res.Body) 106 helper.Must(err) 107 _ = res.Body.Close() 108 109 if !strings.Contains(string(resBytes), `"Req-Id-Be-Hdr":["`) { 110 t.Errorf("%s", resBytes) 111 } 112 113 if res.Header.Get("Req-Id-Cl-Hdr") == "" { 114 t.Errorf("Missing 'Req-Id-Cl-Hdr' header") 115 } 116 117 if res.Header.Get("X") != "X" { 118 t.Errorf("Invalid 'X' header given") 119 } 120 121 if res.Header.Get("Y") != "Y" { 122 t.Errorf("Invalid 'Y' header given") 123 } 124 125 // Call health route 126 req, err = http.NewRequest(http.MethodGet, "http://example.com:8080/xyz", nil) 127 helper.Must(err) 128 129 res, err = client.Do(req) 130 helper.Must(err) 131 132 resBytes, err = io.ReadAll(res.Body) 133 helper.Must(err) 134 _ = res.Body.Close() 135 136 if s := string(resBytes); s != "healthy" { 137 t.Errorf("Unexpected body given: %s", s) 138 } 139 } 140 141 func TestMultiFiles_Definitions(t *testing.T) { 142 helper := test.New(t) 143 client := newClient() 144 145 shutdown, _ := newCouperMultiFiles( 146 "testdata/multi/definitions/couper.hcl", 147 "testdata/multi/definitions/couper.d", 148 helper, 149 ) 150 defer shutdown() 151 152 req, err := http.NewRequest(http.MethodGet, "http://example.com:8080/", nil) 153 helper.Must(err) 154 155 res, err := client.Do(req) 156 helper.Must(err) 157 158 resBytes, err := io.ReadAll(res.Body) 159 helper.Must(err) 160 _ = res.Body.Close() 161 162 if s := string(resBytes); s != "1234567890" { 163 t.Errorf("Unexpected body given: %s", s) 164 } 165 166 // Call protected route 167 req, err = http.NewRequest(http.MethodGet, "http://example.com:8080/added", nil) 168 helper.Must(err) 169 170 res, err = client.Do(req) 171 helper.Must(err) 172 173 resBytes, err = io.ReadAll(res.Body) 174 helper.Must(err) 175 _ = res.Body.Close() 176 177 if s := string(resBytes); !strings.Contains(s, "401 access control error") { 178 t.Errorf("Unexpected body given: %s", s) 179 } 180 } 181 182 func TestMultiFiles_MultipleBackends(t *testing.T) { 183 type testCase struct { 184 config string 185 blType string 186 } 187 188 for _, tc := range []testCase{ 189 {"testdata/multi/backends/errors/jwt.hcl", "jwt"}, 190 {"testdata/multi/backends/errors/beta_oauth2.hcl", "beta_oauth2"}, 191 {"testdata/multi/backends/errors/oidc.hcl", "oidc"}, 192 {"testdata/multi/backends/errors/ac_eh.hcl", "proxy"}, 193 {"testdata/multi/backends/errors/ep_proxy.hcl", "proxy"}, 194 {"testdata/multi/backends/errors/ep_request.hcl", "request"}, 195 {"testdata/multi/backends/errors/api_ep.hcl", "proxy"}, 196 {"testdata/multi/backends/errors/defined_backend_oauth2.hcl", "oauth2"}, 197 {"testdata/multi/backends/errors/defined_backend_token_request.hcl", "beta_token_request"}, 198 {"testdata/multi/backends/errors/anonymous_backend_oauth2.hcl", "oauth2"}, 199 {"testdata/multi/backends/errors/anonymous_backend_token_request.hcl", "beta_token_request"}, 200 } { 201 t.Run(tc.config, func(st *testing.T) { 202 _, err := configload.LoadFile(filepath.Join(testWorkingDir, tc.config), "") 203 204 if !strings.Contains(err.Error(), tc.config+":") { 205 st.Errorf("Missing config file path: %s", err.Error()) 206 } 207 208 if !strings.HasSuffix(err.Error(), fmt.Sprintf(": Multiple definitions of backend are not allowed in %s.; ", tc.blType)) { 209 st.Errorf("Unexpected error: %s", err.Error()) 210 } 211 }) 212 } 213 } 214 215 func Test_MultipleLabels(t *testing.T) { 216 type testCase struct { 217 name string 218 configPath string 219 expError string 220 } 221 222 for _, tc := range []testCase{ 223 { 224 "server with multiple labels", 225 "testdata/multi/errors/couper_01.hcl", 226 "testdata/multi/errors/couper_01.hcl:1,12-15: Extraneous label for server; Only 1 labels (name) are expected for server blocks.", 227 }, 228 { 229 "api with multiple labels", 230 "testdata/multi/errors/couper_02.hcl", 231 "testdata/multi/errors/couper_02.hcl:2,11-14: Extraneous label for api; Only 1 labels (name) are expected for api blocks.", 232 }, 233 { 234 "spa with multiple labels", 235 "testdata/multi/errors/couper_04.hcl", 236 "testdata/multi/errors/couper_04.hcl:2,11-14: Extraneous label for spa; Only 1 labels (name) are expected for spa blocks.", 237 }, 238 { 239 "files with multiple labels", 240 "testdata/multi/errors/couper_05.hcl", 241 "testdata/multi/errors/couper_05.hcl:2,13-16: Extraneous label for files; Only 1 labels (name) are expected for files blocks.", 242 }, 243 { 244 "api, spa, files and server without labels", 245 "testdata/multi/errors/couper_03.hcl", 246 "", 247 }, 248 } { 249 t.Run(tc.name, func(st *testing.T) { 250 _, err := configload.LoadFile(filepath.Join(testWorkingDir, tc.configPath), "") 251 252 if (err != nil && tc.expError == "") || 253 (tc.expError != "" && (err == nil || !strings.Contains(err.Error(), tc.expError))) { 254 st.Errorf("Unexpected error: %v", err) 255 } 256 }) 257 } 258 } 259 260 func TestMultiFiles_SPAs(t *testing.T) { 261 helper := test.New(t) 262 client := newClient() 263 264 shutdown, _ := newCouperMultiFiles("", "testdata/multi/server/spa.d", helper) 265 defer shutdown() 266 267 type testcase struct { 268 path string 269 expStatus int 270 expContains string 271 } 272 273 for _, tc := range []testcase{ 274 {"/", http.StatusNotFound, ""}, 275 {"/app", http.StatusOK, "02_spa.hcl"}, 276 {"/another", http.StatusOK, "03_spa.hcl"}, 277 } { 278 t.Run(tc.path, func(st *testing.T) { 279 h := test.New(st) 280 req, err := http.NewRequest(http.MethodGet, "http://couper.local:8080"+tc.path, nil) 281 h.Must(err) 282 283 res, err := client.Do(req) 284 h.Must(err) 285 286 if res.StatusCode != tc.expStatus { 287 st.Errorf("want status: %d, got: %d", tc.expStatus, res.StatusCode) 288 } 289 290 b, err := io.ReadAll(res.Body) 291 h.Must(err) 292 293 h.Must(res.Body.Close()) 294 295 if tc.expContains != "" && !strings.Contains(string(b), tc.expContains) { 296 st.Errorf("want %q, got:\n%q", tc.expContains, string(b)) 297 } 298 }) 299 } 300 } 301 302 func TestMultiFiles_Files(t *testing.T) { 303 helper := test.New(t) 304 client := newClient() 305 306 shutdown, _ := newCouperMultiFiles("", "testdata/multi/server/files.d", helper) 307 defer shutdown() 308 309 type testcase struct { 310 path string 311 expStatus int 312 expContains string 313 } 314 315 for _, tc := range []testcase{ 316 {"/", http.StatusNotFound, ""}, 317 {"/app", http.StatusOK, "<app/>\n"}, 318 {"/another", http.StatusOK, "<another/>\n"}, 319 } { 320 t.Run(tc.path, func(st *testing.T) { 321 h := test.New(st) 322 req, err := http.NewRequest(http.MethodGet, "http://couper.local:8080"+tc.path, nil) 323 h.Must(err) 324 325 res, err := client.Do(req) 326 h.Must(err) 327 328 if res.StatusCode != tc.expStatus { 329 st.Errorf("want status: %d, got: %d", tc.expStatus, res.StatusCode) 330 } 331 332 b, err := io.ReadAll(res.Body) 333 h.Must(err) 334 335 h.Must(res.Body.Close()) 336 337 if tc.expContains != "" && !strings.Contains(string(b), tc.expContains) { 338 st.Errorf("want %q, got:\n%q", tc.expContains, string(b)) 339 } 340 }) 341 } 342 }