@@ -125,6 +125,7 @@ func TestIsUpstreamReference(t *testing.T) {
125125 "api-1" : true ,
126126 "api-2" : true ,
127127 "backend" : true ,
128+ "myUpStr" : true ,
128129 }
129130
130131 tests := []struct {
@@ -138,6 +139,15 @@ func TestIsUpstreamReference(t *testing.T) {
138139 {"http://127.0.0.1:8080" , false },
139140 {"https://example.com" , false },
140141 {"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 },
141151 }
142152
143153 for _ , test := range tests {
@@ -379,3 +389,147 @@ server {
379389 }
380390 }
381391}
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