|
|
|
@ -1,6 +1,7 @@ |
|
|
|
package s3api |
|
|
|
|
|
|
|
import ( |
|
|
|
"net/http" |
|
|
|
"testing" |
|
|
|
) |
|
|
|
|
|
|
|
@ -89,3 +90,174 @@ func TestBuildPathWithForwardedPrefix(t *testing.T) { |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// TestExtractHostHeader tests the extractHostHeader function with various scenarios
|
|
|
|
func TestExtractHostHeader(t *testing.T) { |
|
|
|
tests := []struct { |
|
|
|
name string |
|
|
|
hostHeader string |
|
|
|
forwardedHost string |
|
|
|
forwardedPort string |
|
|
|
forwardedProto string |
|
|
|
expected string |
|
|
|
}{ |
|
|
|
{ |
|
|
|
name: "basic host without forwarding", |
|
|
|
hostHeader: "example.com", |
|
|
|
forwardedHost: "", |
|
|
|
forwardedPort: "", |
|
|
|
forwardedProto: "", |
|
|
|
expected: "example.com", |
|
|
|
}, |
|
|
|
{ |
|
|
|
name: "host with port without forwarding", |
|
|
|
hostHeader: "example.com:8080", |
|
|
|
forwardedHost: "", |
|
|
|
forwardedPort: "", |
|
|
|
forwardedProto: "", |
|
|
|
expected: "example.com:8080", |
|
|
|
}, |
|
|
|
{ |
|
|
|
name: "X-Forwarded-Host without port", |
|
|
|
hostHeader: "backend:8333", |
|
|
|
forwardedHost: "example.com", |
|
|
|
forwardedPort: "", |
|
|
|
forwardedProto: "", |
|
|
|
expected: "example.com", |
|
|
|
}, |
|
|
|
{ |
|
|
|
name: "X-Forwarded-Host with X-Forwarded-Port (HTTP non-standard)", |
|
|
|
hostHeader: "backend:8333", |
|
|
|
forwardedHost: "example.com", |
|
|
|
forwardedPort: "8080", |
|
|
|
forwardedProto: "http", |
|
|
|
expected: "example.com:8080", |
|
|
|
}, |
|
|
|
{ |
|
|
|
name: "X-Forwarded-Host with X-Forwarded-Port (HTTPS non-standard)", |
|
|
|
hostHeader: "backend:8333", |
|
|
|
forwardedHost: "example.com", |
|
|
|
forwardedPort: "8443", |
|
|
|
forwardedProto: "https", |
|
|
|
expected: "example.com:8443", |
|
|
|
}, |
|
|
|
{ |
|
|
|
name: "X-Forwarded-Host with X-Forwarded-Port (HTTP standard port 80)", |
|
|
|
hostHeader: "backend:8333", |
|
|
|
forwardedHost: "example.com", |
|
|
|
forwardedPort: "80", |
|
|
|
forwardedProto: "http", |
|
|
|
expected: "example.com", |
|
|
|
}, |
|
|
|
{ |
|
|
|
name: "X-Forwarded-Host with X-Forwarded-Port (HTTPS standard port 443)", |
|
|
|
hostHeader: "backend:8333", |
|
|
|
forwardedHost: "example.com", |
|
|
|
forwardedPort: "443", |
|
|
|
forwardedProto: "https", |
|
|
|
expected: "example.com", |
|
|
|
}, |
|
|
|
// Issue #6649: X-Forwarded-Host already contains port (Traefik/HAProxy style)
|
|
|
|
{ |
|
|
|
name: "X-Forwarded-Host with port already included (should not add port again)", |
|
|
|
hostHeader: "backend:8333", |
|
|
|
forwardedHost: "127.0.0.1:8433", |
|
|
|
forwardedPort: "8433", |
|
|
|
forwardedProto: "https", |
|
|
|
expected: "127.0.0.1:8433", |
|
|
|
}, |
|
|
|
{ |
|
|
|
name: "X-Forwarded-Host with port, no X-Forwarded-Port header", |
|
|
|
hostHeader: "backend:8333", |
|
|
|
forwardedHost: "example.com:9000", |
|
|
|
forwardedPort: "", |
|
|
|
forwardedProto: "http", |
|
|
|
expected: "example.com:9000", |
|
|
|
}, |
|
|
|
// IPv6 test cases
|
|
|
|
{ |
|
|
|
name: "IPv6 address with brackets and port in X-Forwarded-Host", |
|
|
|
hostHeader: "backend:8333", |
|
|
|
forwardedHost: "[::1]:8080", |
|
|
|
forwardedPort: "8080", |
|
|
|
forwardedProto: "http", |
|
|
|
expected: "[::1]:8080", |
|
|
|
}, |
|
|
|
{ |
|
|
|
name: "IPv6 address without brackets, should add brackets with port", |
|
|
|
hostHeader: "backend:8333", |
|
|
|
forwardedHost: "::1", |
|
|
|
forwardedPort: "8080", |
|
|
|
forwardedProto: "http", |
|
|
|
expected: "[::1]:8080", |
|
|
|
}, |
|
|
|
{ |
|
|
|
name: "IPv6 address without brackets and standard port, should return bracketed IPv6", |
|
|
|
hostHeader: "backend:8333", |
|
|
|
forwardedHost: "::1", |
|
|
|
forwardedPort: "80", |
|
|
|
forwardedProto: "http", |
|
|
|
expected: "[::1]", |
|
|
|
}, |
|
|
|
{ |
|
|
|
name: "IPv6 address without brackets and standard HTTPS port, should return bracketed IPv6", |
|
|
|
hostHeader: "backend:8333", |
|
|
|
forwardedHost: "2001:db8::1", |
|
|
|
forwardedPort: "443", |
|
|
|
forwardedProto: "https", |
|
|
|
expected: "[2001:db8::1]", |
|
|
|
}, |
|
|
|
{ |
|
|
|
name: "IPv6 address with brackets but no port, should add port", |
|
|
|
hostHeader: "backend:8333", |
|
|
|
forwardedHost: "[2001:db8::1]", |
|
|
|
forwardedPort: "8080", |
|
|
|
forwardedProto: "http", |
|
|
|
expected: "[2001:db8::1]:8080", |
|
|
|
}, |
|
|
|
{ |
|
|
|
name: "IPv6 full address with brackets and port", |
|
|
|
hostHeader: "backend:8333", |
|
|
|
forwardedHost: "[2001:db8:85a3::8a2e:370:7334]:443", |
|
|
|
forwardedPort: "443", |
|
|
|
forwardedProto: "https", |
|
|
|
expected: "[2001:db8:85a3::8a2e:370:7334]:443", |
|
|
|
}, |
|
|
|
{ |
|
|
|
name: "IPv4-mapped IPv6 address without brackets, should add brackets with port", |
|
|
|
hostHeader: "backend:8333", |
|
|
|
forwardedHost: "::ffff:127.0.0.1", |
|
|
|
forwardedPort: "8080", |
|
|
|
forwardedProto: "http", |
|
|
|
expected: "[::ffff:127.0.0.1]:8080", |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
for _, tt := range tests { |
|
|
|
t.Run(tt.name, func(t *testing.T) { |
|
|
|
// Create a mock request
|
|
|
|
req, err := http.NewRequest("GET", "http://"+tt.hostHeader+"/bucket/object", nil) |
|
|
|
if err != nil { |
|
|
|
t.Fatalf("Failed to create request: %v", err) |
|
|
|
} |
|
|
|
|
|
|
|
// Set headers
|
|
|
|
req.Host = tt.hostHeader |
|
|
|
if tt.forwardedHost != "" { |
|
|
|
req.Header.Set("X-Forwarded-Host", tt.forwardedHost) |
|
|
|
} |
|
|
|
if tt.forwardedPort != "" { |
|
|
|
req.Header.Set("X-Forwarded-Port", tt.forwardedPort) |
|
|
|
} |
|
|
|
if tt.forwardedProto != "" { |
|
|
|
req.Header.Set("X-Forwarded-Proto", tt.forwardedProto) |
|
|
|
} |
|
|
|
|
|
|
|
// Test the function
|
|
|
|
result := extractHostHeader(req) |
|
|
|
if result != tt.expected { |
|
|
|
t.Errorf("extractHostHeader() = %q, want %q", result, tt.expected) |
|
|
|
} |
|
|
|
}) |
|
|
|
} |
|
|
|
} |