@@ -125,6 +125,7 @@ func TestIsUpstreamReference(t *testing.T) {
125
125
"api-1" : true ,
126
126
"api-2" : true ,
127
127
"backend" : true ,
128
+ "myUpStr" : true ,
128
129
}
129
130
130
131
tests := []struct {
@@ -138,6 +139,15 @@ func TestIsUpstreamReference(t *testing.T) {
138
139
{"http://127.0.0.1:8080" , false },
139
140
{"https://example.com" , false },
140
141
{"http://unknown-upstream" , false },
142
+ // Test cases for nginx variables
143
+ {"https://myUpStr$request_uri" , true },
144
+ {"http://api-1$request_uri" , true },
145
+ {"https://backend$server_name" , true },
146
+ {"http://unknown-upstream$request_uri" , false },
147
+ {"https://example.com$request_uri" , false },
148
+ // Test cases for URLs with variables and paths
149
+ {"https://myUpStr/api$request_uri" , true },
150
+ {"http://api-1:8080$request_uri" , true },
141
151
}
142
152
143
153
for _ , test := range tests {
@@ -379,3 +389,147 @@ server {
379
389
}
380
390
}
381
391
}
392
+
393
+ func TestParseProxyTargetsWithNginxVariables (t * testing.T ) {
394
+ config := `map $http_upgrade $connection_upgrade {
395
+ default upgrade;
396
+ '' close;
397
+ }
398
+ upstream myUpStr {
399
+ keepalive 32;
400
+ keepalive_timeout 600s;
401
+ server 192.168.1.100:8080;
402
+ }
403
+ server {
404
+ listen 80;
405
+ listen [::]:80;
406
+ server_name my.domain.tld;
407
+ return 307 https://$server_name$request_uri;
408
+ }
409
+ server {
410
+ listen 443 ssl http2;
411
+ listen [::]:443 ssl http2;
412
+ server_name my.domain.tld;
413
+ ssl_certificate /path/to/cert;
414
+ ssl_certificate_key /path/to/key;
415
+ location / {
416
+ proxy_http_version 1.1;
417
+ proxy_set_header Upgrade $http_upgrade;
418
+ proxy_set_header Connection $connection_upgrade;
419
+ client_max_body_size 1000m;
420
+ proxy_redirect off;
421
+ add_header X-Served-By $host;
422
+ proxy_set_header Host $host;
423
+ proxy_set_header X-Forwarded-Scheme $scheme;
424
+ proxy_set_header X-Forwarded-Proto $scheme;
425
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
426
+ proxy_set_header X-Real-IP $remote_addr;
427
+ proxy_set_header X-Forwarded-Host $host:$server_port;
428
+ proxy_set_header X-Forwarded-Server $host;
429
+ proxy_pass https://myUpStr$request_uri;
430
+ }
431
+ }`
432
+
433
+ targets := ParseProxyTargetsFromRawContent (config )
434
+
435
+ // Expected targets:
436
+ // - 1 upstream server from myUpStr
437
+ // - proxy_pass https://myUpStr$request_uri should be ignored since it references an upstream
438
+ expectedTargets := []ProxyTarget {
439
+ {Host : "192.168.1.100" , Port : "8080" , Type : "upstream" },
440
+ }
441
+
442
+ if len (targets ) != len (expectedTargets ) {
443
+ t .Errorf ("Expected %d targets, got %d" , len (expectedTargets ), len (targets ))
444
+ for i , target := range targets {
445
+ t .Logf ("Target %d: %+v" , i , target )
446
+ }
447
+ return
448
+ }
449
+
450
+ // Create a map for easier comparison
451
+ targetMap := make (map [string ]ProxyTarget )
452
+ for _ , target := range targets {
453
+ key := target .Host + ":" + target .Port + ":" + target .Type
454
+ targetMap [key ] = target
455
+ }
456
+
457
+ for _ , expected := range expectedTargets {
458
+ key := expected .Host + ":" + expected .Port + ":" + expected .Type
459
+ if _ , found := targetMap [key ]; ! found {
460
+ t .Errorf ("Expected target not found: %+v" , expected )
461
+ }
462
+ }
463
+ }
464
+
465
+ func TestParseProxyTargetsWithComplexNginxVariables (t * testing.T ) {
466
+ config := `upstream backend_api {
467
+ server api1.example.com:8080;
468
+ server api2.example.com:8080;
469
+ }
470
+
471
+ upstream backend_ws {
472
+ server ws1.example.com:9000;
473
+ server ws2.example.com:9000;
474
+ }
475
+
476
+ server {
477
+ listen 80;
478
+ server_name example.com;
479
+
480
+ location /api/ {
481
+ proxy_pass http://backend_api$request_uri;
482
+ }
483
+
484
+ location /ws/ {
485
+ proxy_pass http://backend_ws/websocket$request_uri;
486
+ }
487
+
488
+ location /external/ {
489
+ proxy_pass https://external.example.com:8443$request_uri;
490
+ }
491
+
492
+ location /static/ {
493
+ proxy_pass http://static.example.com$uri;
494
+ }
495
+ }`
496
+
497
+ targets := ParseProxyTargetsFromRawContent (config )
498
+
499
+ // Expected targets:
500
+ // - 2 upstream servers from backend_api
501
+ // - 2 upstream servers from backend_ws
502
+ // - 1 direct proxy_pass (external.example.com:8443)
503
+ // - 1 direct proxy_pass (static.example.com:80)
504
+ // - proxy_pass with upstream references should be ignored
505
+ expectedTargets := []ProxyTarget {
506
+ {Host : "api1.example.com" , Port : "8080" , Type : "upstream" },
507
+ {Host : "api2.example.com" , Port : "8080" , Type : "upstream" },
508
+ {Host : "ws1.example.com" , Port : "9000" , Type : "upstream" },
509
+ {Host : "ws2.example.com" , Port : "9000" , Type : "upstream" },
510
+ {Host : "external.example.com" , Port : "8443" , Type : "proxy_pass" },
511
+ {Host : "static.example.com" , Port : "80" , Type : "proxy_pass" },
512
+ }
513
+
514
+ if len (targets ) != len (expectedTargets ) {
515
+ t .Errorf ("Expected %d targets, got %d" , len (expectedTargets ), len (targets ))
516
+ for i , target := range targets {
517
+ t .Logf ("Target %d: %+v" , i , target )
518
+ }
519
+ return
520
+ }
521
+
522
+ // Create a map for easier comparison
523
+ targetMap := make (map [string ]ProxyTarget )
524
+ for _ , target := range targets {
525
+ key := target .Host + ":" + target .Port + ":" + target .Type
526
+ targetMap [key ] = target
527
+ }
528
+
529
+ for _ , expected := range expectedTargets {
530
+ key := expected .Host + ":" + expected .Port + ":" + expected .Type
531
+ if _ , found := targetMap [key ]; ! found {
532
+ t .Errorf ("Expected target not found: %+v" , expected )
533
+ }
534
+ }
535
+ }
0 commit comments