123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381 |
- package upstream
- import (
- "testing"
- )
- func TestParseProxyTargetsFromRawContent(t *testing.T) {
- config := `map $http_upgrade $connection_upgrade {
- default upgrade;
- '' close;
- }
- upstream api-1 {
- server 127.0.0.1:9000;
- server 127.0.0.1:443;
- }
- upstream api-2 {
- server 127.0.0.1:9003;
- server 127.0.0.1:9005;
- }
- server {
- listen 80;
- listen [::]:80;
- server_name test.jackyu.cn;
- location / {
- # First attempt to serve request as file, then
- # as directory, then fall back to displaying a 404.
- index index.html;
- try_files $uri $uri/ /index.html;
- }
- location /admin {
- index admin.html;
- try_files $uri $uri/ /admin.html;
- }
- location /user {
- index user.html;
- try_files $uri $uri/ /user.html;
- }
- location /api/ {
- proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection $connection_upgrade;
- proxy_pass http://api-1/;
- proxy_redirect off;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto $scheme;
- client_max_body_size 1000m;
- }
- }
- server {
- listen 443 ssl;
- listen [::]:443 ssl;
- server_name test.jackyu.cn;
- ssl_certificate /etc/nginx/ssl/test.jackyu.cn_P256/fullchain.cer;
- ssl_certificate_key /etc/nginx/ssl/test.jackyu.cn_P256/private.key;
- root /var/www/ibeta/html;
- index index.html;
- http2 on;
- access_log /var/log/nginx/test.jackyu.cn.log main;
- location / {
- # First attempt to serve request as file, then
- # as directory, then fall back to displaying a 404.
- index index.html;
- try_files $uri $uri/ /index.html;
- }
- location /admin {
- index admin.html;
- try_files $uri $uri/ /admin.html;
- }
- location /user {
- index user.html;
- try_files $uri $uri/ /user.html;
- }
- location /api/ {
- proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection $connection_upgrade;
- proxy_pass http://api-1/;
- proxy_redirect off;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto $scheme;
- client_max_body_size 100m;
- }
- }`
- targets := ParseProxyTargetsFromRawContent(config)
- // Expected targets: 4 upstream servers (2 from api-1, 2 from api-2)
- // proxy_pass http://api-1/ should be ignored since it references an upstream
- expectedTargets := []ProxyTarget{
- {Host: "127.0.0.1", Port: "9000", Type: "upstream"},
- {Host: "127.0.0.1", Port: "443", Type: "upstream"},
- {Host: "127.0.0.1", Port: "9003", Type: "upstream"},
- {Host: "127.0.0.1", Port: "9005", Type: "upstream"},
- }
- if len(targets) != len(expectedTargets) {
- t.Errorf("Expected %d targets, got %d", len(expectedTargets), len(targets))
- for i, target := range targets {
- t.Logf("Target %d: %+v", i, target)
- }
- return
- }
- // Create a map for easier comparison
- targetMap := make(map[string]ProxyTarget)
- for _, target := range targets {
- key := target.Host + ":" + target.Port + ":" + target.Type
- targetMap[key] = target
- }
- for _, expected := range expectedTargets {
- key := expected.Host + ":" + expected.Port + ":" + expected.Type
- if _, found := targetMap[key]; !found {
- t.Errorf("Expected target not found: %+v", expected)
- }
- }
- }
- func TestIsUpstreamReference(t *testing.T) {
- upstreamNames := map[string]bool{
- "api-1": true,
- "api-2": true,
- "backend": true,
- }
- tests := []struct {
- proxyPass string
- expected bool
- }{
- {"http://api-1/", true},
- {"http://api-1", true},
- {"https://api-2/path", true},
- {"http://backend", true},
- {"http://127.0.0.1:8080", false},
- {"https://example.com", false},
- {"http://unknown-upstream", false},
- }
- for _, test := range tests {
- result := isUpstreamReference(test.proxyPass, upstreamNames)
- if result != test.expected {
- t.Errorf("isUpstreamReference(%q) = %v, expected %v", test.proxyPass, result, test.expected)
- }
- }
- }
- func TestParseProxyTargetsWithDirectProxyPass(t *testing.T) {
- config := `upstream api-1 {
- server 127.0.0.1:9000;
- server 127.0.0.1:443;
- }
- server {
- listen 80;
- server_name test.jackyu.cn;
- location /api/ {
- proxy_pass http://api-1/;
- }
- location /external/ {
- proxy_pass http://external.example.com:8080/;
- }
- location /another/ {
- proxy_pass https://another.example.com/;
- }
- }`
- targets := ParseProxyTargetsFromRawContent(config)
- // Expected targets:
- // - 2 upstream servers from api-1
- // - 2 direct proxy_pass targets (external.example.com:8080, another.example.com:443)
- // - proxy_pass http://api-1/ should be ignored since it references an upstream
- expectedTargets := []ProxyTarget{
- {Host: "127.0.0.1", Port: "9000", Type: "upstream"},
- {Host: "127.0.0.1", Port: "443", Type: "upstream"},
- {Host: "external.example.com", Port: "8080", Type: "proxy_pass"},
- {Host: "another.example.com", Port: "443", Type: "proxy_pass"},
- }
- if len(targets) != len(expectedTargets) {
- t.Errorf("Expected %d targets, got %d", len(expectedTargets), len(targets))
- for i, target := range targets {
- t.Logf("Target %d: %+v", i, target)
- }
- return
- }
- // Create a map for easier comparison
- targetMap := make(map[string]ProxyTarget)
- for _, target := range targets {
- key := target.Host + ":" + target.Port + ":" + target.Type
- targetMap[key] = target
- }
- for _, expected := range expectedTargets {
- key := expected.Host + ":" + expected.Port + ":" + expected.Type
- if _, found := targetMap[key]; !found {
- t.Errorf("Expected target not found: %+v", expected)
- }
- }
- }
- func TestParseProxyTargetsFromStreamConfig(t *testing.T) {
- config := `upstream backend {
- server 127.0.0.1:9000;
- server 127.0.0.1:9001;
- }
- server {
- listen 12345;
- proxy_pass backend;
- }
- server {
- listen 12346;
- proxy_pass 192.168.1.100:8080;
- }
- server {
- listen 12347;
- proxy_pass example.com:3306;
- }`
- targets := ParseProxyTargetsFromRawContent(config)
- // Expected targets:
- // - 2 upstream servers from backend
- // - 2 direct proxy_pass targets (192.168.1.100:8080, example.com:3306)
- // - proxy_pass backend should be ignored since it references an upstream
- expectedTargets := []ProxyTarget{
- {Host: "127.0.0.1", Port: "9000", Type: "upstream"},
- {Host: "127.0.0.1", Port: "9001", Type: "upstream"},
- {Host: "192.168.1.100", Port: "8080", Type: "proxy_pass"},
- {Host: "example.com", Port: "3306", Type: "proxy_pass"},
- }
- if len(targets) != len(expectedTargets) {
- t.Errorf("Expected %d targets, got %d", len(expectedTargets), len(targets))
- for i, target := range targets {
- t.Logf("Target %d: %+v", i, target)
- }
- return
- }
- // Create a map for easier comparison
- targetMap := make(map[string]ProxyTarget)
- for _, target := range targets {
- key := target.Host + ":" + target.Port + ":" + target.Type
- targetMap[key] = target
- }
- for _, expected := range expectedTargets {
- key := expected.Host + ":" + expected.Port + ":" + expected.Type
- if _, found := targetMap[key]; !found {
- t.Errorf("Expected target not found: %+v", expected)
- }
- }
- }
- func TestParseProxyTargetsFromMixedConfig(t *testing.T) {
- config := `upstream web_backend {
- server web1.example.com:80;
- server web2.example.com:80;
- }
- upstream stream_backend {
- server stream1.example.com:12345;
- server stream2.example.com:12345;
- }
- # HTTP server block
- server {
- listen 80;
- server_name example.com;
- location / {
- proxy_pass http://web_backend/;
- }
- location /api {
- proxy_pass http://api.example.com:8080/;
- }
- }
- # Stream server blocks
- server {
- listen 12345;
- proxy_pass stream_backend;
- }
- server {
- listen 3306;
- proxy_pass mysql.example.com:3306;
- }`
- targets := ParseProxyTargetsFromRawContent(config)
- // Expected targets:
- // - 2 upstream servers from web_backend
- // - 2 upstream servers from stream_backend
- // - 1 direct HTTP proxy_pass (api.example.com:8080)
- // - 1 direct stream proxy_pass (mysql.example.com:3306)
- // - proxy_pass http://web_backend/ and proxy_pass stream_backend should be ignored
- expectedTargets := []ProxyTarget{
- {Host: "web1.example.com", Port: "80", Type: "upstream"},
- {Host: "web2.example.com", Port: "80", Type: "upstream"},
- {Host: "stream1.example.com", Port: "12345", Type: "upstream"},
- {Host: "stream2.example.com", Port: "12345", Type: "upstream"},
- {Host: "api.example.com", Port: "8080", Type: "proxy_pass"},
- {Host: "mysql.example.com", Port: "3306", Type: "proxy_pass"},
- }
- if len(targets) != len(expectedTargets) {
- t.Errorf("Expected %d targets, got %d", len(expectedTargets), len(targets))
- for i, target := range targets {
- t.Logf("Target %d: %+v", i, target)
- }
- return
- }
- // Create a map for easier comparison
- targetMap := make(map[string]ProxyTarget)
- for _, target := range targets {
- key := target.Host + ":" + target.Port + ":" + target.Type
- targetMap[key] = target
- }
- for _, expected := range expectedTargets {
- key := expected.Host + ":" + expected.Port + ":" + expected.Type
- if _, found := targetMap[key]; !found {
- t.Errorf("Expected target not found: %+v", expected)
- }
- }
- }
- func TestParseProxyTargetsFromUserConfig(t *testing.T) {
- config := `upstream my-tcp {
- server 127.0.0.1:9000;
- }
- server {
- listen 1234-1236;
- resolver 8.8.8.8 valid=1s;
- proxy_pass example.com:$server_port;
- }`
- targets := ParseProxyTargetsFromRawContent(config)
- // Print actual results for debugging
- t.Logf("Found %d targets:", len(targets))
- for i, target := range targets {
- t.Logf("Target %d: Host=%s, Port=%s, Type=%s", i+1, target.Host, target.Port, target.Type)
- }
- // Expected targets:
- // - 1 upstream server from my-tcp
- // - 1 proxy_pass target (example.com with variable port should still be parsed)
- expectedTargets := []ProxyTarget{
- {Host: "127.0.0.1", Port: "9000", Type: "upstream"},
- {Host: "example.com", Port: "$server_port", Type: "proxy_pass"},
- }
- if len(targets) != len(expectedTargets) {
- t.Errorf("Expected %d targets, got %d", len(expectedTargets), len(targets))
- return
- }
- // Create a map for easier comparison
- targetMap := make(map[string]ProxyTarget)
- for _, target := range targets {
- key := target.Host + ":" + target.Port + ":" + target.Type
- targetMap[key] = target
- }
- for _, expected := range expectedTargets {
- key := expected.Host + ":" + expected.Port + ":" + expected.Type
- if _, found := targetMap[key]; !found {
- t.Errorf("Expected target not found: %+v", expected)
- }
- }
- }
|