package gateway import ( "bytes" "encoding/json" "net/http" "net/http/httptest" "testing" "github.com/DeBrosOfficial/network/pkg/logging" ) func newTestGateway(t *testing.T) *Gateway { logger, err := logging.NewColoredLogger(logging.ComponentGeneral, true) if err != nil { t.Fatalf("Failed to create logger: %v", err) } return &Gateway{logger: logger} } func TestAnonProxyHandler_MethodValidation(t *testing.T) { gw := newTestGateway(t) // Test GET request (should fail - only POST allowed) req := httptest.NewRequest(http.MethodGet, "/v1/proxy/anon", nil) w := httptest.NewRecorder() gw.anonProxyHandler(w, req) if w.Code != http.StatusMethodNotAllowed { t.Errorf("Expected status %d, got %d", http.StatusMethodNotAllowed, w.Code) } } func TestAnonProxyHandler_InvalidJSON(t *testing.T) { gw := newTestGateway(t) // Test invalid JSON req := httptest.NewRequest(http.MethodPost, "/v1/proxy/anon", bytes.NewBufferString("invalid json")) w := httptest.NewRecorder() gw.anonProxyHandler(w, req) if w.Code != http.StatusBadRequest { t.Errorf("Expected status %d, got %d", http.StatusBadRequest, w.Code) } } func TestAnonProxyHandler_InvalidURL(t *testing.T) { gw := newTestGateway(t) tests := []struct { name string payload anonProxyRequest }{ { name: "invalid URL scheme", payload: anonProxyRequest{ URL: "ftp://example.com", Method: "GET", }, }, { name: "malformed URL", payload: anonProxyRequest{ URL: "://invalid", Method: "GET", }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { body, _ := json.Marshal(tt.payload) req := httptest.NewRequest(http.MethodPost, "/v1/proxy/anon", bytes.NewBuffer(body)) w := httptest.NewRecorder() gw.anonProxyHandler(w, req) if w.Code != http.StatusBadRequest { t.Errorf("Expected status %d, got %d", http.StatusBadRequest, w.Code) } }) } } func TestAnonProxyHandler_PrivateAddressBlocking(t *testing.T) { gw := newTestGateway(t) tests := []struct { name string url string }{ {"localhost", "http://localhost/test"}, {"localhost", "http://localhost/test"}, {"private 10.x", "http://10.0.0.1/test"}, {"private 192.168.x", "http://192.168.1.1/test"}, {"private 172.16.x", "http://172.16.0.1/test"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { payload := anonProxyRequest{ URL: tt.url, Method: "GET", } body, _ := json.Marshal(payload) req := httptest.NewRequest(http.MethodPost, "/v1/proxy/anon", bytes.NewBuffer(body)) w := httptest.NewRecorder() gw.anonProxyHandler(w, req) if w.Code != http.StatusForbidden { t.Errorf("Expected status %d for %s, got %d", http.StatusForbidden, tt.url, w.Code) } }) } } func TestAnonProxyHandler_InvalidMethod(t *testing.T) { gw := newTestGateway(t) payload := anonProxyRequest{ URL: "https://example.com", Method: "INVALID", } body, _ := json.Marshal(payload) req := httptest.NewRequest(http.MethodPost, "/v1/proxy/anon", bytes.NewBuffer(body)) w := httptest.NewRecorder() gw.anonProxyHandler(w, req) if w.Code != http.StatusBadRequest { t.Errorf("Expected status %d, got %d", http.StatusBadRequest, w.Code) } } func TestIsHopByHopHeader(t *testing.T) { tests := []struct { header string expected bool }{ {"Connection", true}, {"Keep-Alive", true}, {"Proxy-Authorization", true}, {"Transfer-Encoding", true}, {"Upgrade", true}, {"Content-Type", false}, {"Authorization", false}, {"User-Agent", false}, } for _, tt := range tests { t.Run(tt.header, func(t *testing.T) { result := isHopByHopHeader(tt.header) if result != tt.expected { t.Errorf("isHopByHopHeader(%s) = %v, want %v", tt.header, result, tt.expected) } }) } } func TestIsPrivateOrLocalHost(t *testing.T) { tests := []struct { host string expected bool }{ {"localhost", true}, {"localhost", true}, {"::1", true}, {"10.0.0.1", true}, {"192.168.1.1", true}, {"172.16.0.1", true}, {"172.31.255.255", true}, {"example.com", false}, {"8.8.8.8", false}, {"1.1.1.1", false}, {"172.32.0.1", false}, // Not in private range } for _, tt := range tests { t.Run(tt.host, func(t *testing.T) { result := isPrivateOrLocalHost(tt.host) if result != tt.expected { t.Errorf("isPrivateOrLocalHost(%s) = %v, want %v", tt.host, result, tt.expected) } }) } }