177 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			177 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Go
		
	
	
	
package main
 | 
						|
 | 
						|
import (
 | 
						|
	"net"
 | 
						|
	"net/http"
 | 
						|
	"reflect"
 | 
						|
	"testing"
 | 
						|
 | 
						|
	"github.com/stretchr/testify/assert"
 | 
						|
)
 | 
						|
 | 
						|
func TestGetRealClientIPParser(t *testing.T) {
 | 
						|
	forwardedForType := reflect.TypeOf((*xForwardedForClientIPParser)(nil))
 | 
						|
 | 
						|
	tests := []struct {
 | 
						|
		header     string
 | 
						|
		errString  string
 | 
						|
		parserType reflect.Type
 | 
						|
	}{
 | 
						|
		{"X-Forwarded-For", "", forwardedForType},
 | 
						|
		{"X-REAL-IP", "", forwardedForType},
 | 
						|
		{"x-proxyuser-ip", "", forwardedForType},
 | 
						|
		{"", "the http header key () is either invalid or unsupported", nil},
 | 
						|
		{"Forwarded", "the http header key (Forwarded) is either invalid or unsupported", nil},
 | 
						|
		{"2#* @##$$:kd", "the http header key (2#* @##$$:kd) is either invalid or unsupported", nil},
 | 
						|
	}
 | 
						|
 | 
						|
	for _, test := range tests {
 | 
						|
		p, err := getRealClientIPParser(test.header)
 | 
						|
 | 
						|
		if test.errString == "" {
 | 
						|
			assert.Nil(t, err)
 | 
						|
		} else {
 | 
						|
			assert.NotNil(t, err)
 | 
						|
			assert.Equal(t, test.errString, err.Error())
 | 
						|
		}
 | 
						|
 | 
						|
		if test.parserType == nil {
 | 
						|
			assert.Nil(t, p)
 | 
						|
		} else {
 | 
						|
			assert.NotNil(t, p)
 | 
						|
			assert.Equal(t, test.parserType, reflect.TypeOf(p))
 | 
						|
		}
 | 
						|
 | 
						|
		if xp, ok := p.(*xForwardedForClientIPParser); ok {
 | 
						|
			assert.Equal(t, http.CanonicalHeaderKey(test.header), xp.header)
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestXForwardedForClientIPParser(t *testing.T) {
 | 
						|
	p := &xForwardedForClientIPParser{header: http.CanonicalHeaderKey("X-Forwarded-For")}
 | 
						|
 | 
						|
	tests := []struct {
 | 
						|
		headerValue string
 | 
						|
		errString   string
 | 
						|
		expectedIP  net.IP
 | 
						|
	}{
 | 
						|
		{"", "", nil},
 | 
						|
		{"1.2.3.4", "", net.ParseIP("1.2.3.4")},
 | 
						|
		{"10::23", "", net.ParseIP("10::23")},
 | 
						|
		{"::1", "", net.ParseIP("::1")},
 | 
						|
		{"[::1]:1234", "", net.ParseIP("::1")},
 | 
						|
		{"10.0.10.11:1234", "", net.ParseIP("10.0.10.11")},
 | 
						|
		{"192.168.10.50, 10.0.0.1, 1.2.3.4", "", net.ParseIP("192.168.10.50")},
 | 
						|
		{"nil", "unable to parse ip (nil) from X-Forwarded-For header", nil},
 | 
						|
		{"10000.10000.10000.10000", "unable to parse ip (10000.10000.10000.10000) from X-Forwarded-For header", nil},
 | 
						|
	}
 | 
						|
 | 
						|
	for _, test := range tests {
 | 
						|
		h := http.Header{}
 | 
						|
		h.Add("X-Forwarded-For", test.headerValue)
 | 
						|
 | 
						|
		ip, err := p.GetRealClientIP(h)
 | 
						|
 | 
						|
		if test.errString == "" {
 | 
						|
			assert.Nil(t, err)
 | 
						|
		} else {
 | 
						|
			assert.NotNil(t, err)
 | 
						|
			assert.Equal(t, test.errString, err.Error())
 | 
						|
		}
 | 
						|
 | 
						|
		if test.expectedIP == nil {
 | 
						|
			assert.Nil(t, ip)
 | 
						|
		} else {
 | 
						|
			assert.NotNil(t, ip)
 | 
						|
			assert.Equal(t, test.expectedIP, ip)
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestXForwardedForClientIPParserIgnoresOthers(t *testing.T) {
 | 
						|
	p := &xForwardedForClientIPParser{header: http.CanonicalHeaderKey("X-Forwarded-For")}
 | 
						|
 | 
						|
	h := http.Header{}
 | 
						|
	expectedIPString := "192.168.10.50"
 | 
						|
	h.Add("X-Real-IP", "10.0.0.1")
 | 
						|
	h.Add("X-ProxyUser-IP", "10.0.0.1")
 | 
						|
	h.Add("X-Forwarded-For", expectedIPString)
 | 
						|
	ip, err := p.GetRealClientIP(h)
 | 
						|
	assert.Nil(t, err)
 | 
						|
	assert.NotNil(t, ip)
 | 
						|
	assert.Equal(t, ip, net.ParseIP(expectedIPString))
 | 
						|
}
 | 
						|
 | 
						|
func TestGetRemoteIP(t *testing.T) {
 | 
						|
	tests := []struct {
 | 
						|
		remoteAddr string
 | 
						|
		errString  string
 | 
						|
		expectedIP net.IP
 | 
						|
	}{
 | 
						|
		{"", "unable to get ip and port from http.RemoteAddr ()", nil},
 | 
						|
		{"nil", "unable to get ip and port from http.RemoteAddr (nil)", nil},
 | 
						|
		{"235.28.129.186", "unable to get ip and port from http.RemoteAddr (235.28.129.186)", nil},
 | 
						|
		{"90::45", "unable to get ip and port from http.RemoteAddr (90::45)", nil},
 | 
						|
		{"192.168.73.165:14976, 10.4.201.15:18453", "unable to get ip and port from http.RemoteAddr (192.168.73.165:14976, 10.4.201.15:18453)", nil},
 | 
						|
		{"10000.10000.10000.10000:8080", "unable to parse ip (10000.10000.10000.10000)", nil},
 | 
						|
		{"[::1]:48290", "", net.ParseIP("::1")},
 | 
						|
		{"10.254.244.165:62750", "", net.ParseIP("10.254.244.165")},
 | 
						|
	}
 | 
						|
 | 
						|
	for _, test := range tests {
 | 
						|
		req := &http.Request{RemoteAddr: test.remoteAddr}
 | 
						|
 | 
						|
		ip, err := getRemoteIP(req)
 | 
						|
 | 
						|
		if test.errString == "" {
 | 
						|
			assert.Nil(t, err)
 | 
						|
		} else {
 | 
						|
			assert.NotNil(t, err)
 | 
						|
			assert.Equal(t, test.errString, err.Error())
 | 
						|
		}
 | 
						|
 | 
						|
		if test.expectedIP == nil {
 | 
						|
			assert.Nil(t, ip)
 | 
						|
		} else {
 | 
						|
			assert.NotNil(t, ip)
 | 
						|
			assert.Equal(t, test.expectedIP, ip)
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestGetClientString(t *testing.T) {
 | 
						|
	p := &xForwardedForClientIPParser{header: http.CanonicalHeaderKey("X-Forwarded-For")}
 | 
						|
 | 
						|
	tests := []struct {
 | 
						|
		parser             realClientIPParser
 | 
						|
		remoteAddr         string
 | 
						|
		headerValue        string
 | 
						|
		expectedClient     string
 | 
						|
		expectedClientFull string
 | 
						|
	}{
 | 
						|
		// Should fail quietly, only printing warnings to the log
 | 
						|
		{nil, "", "", "", ""},
 | 
						|
		{p, "127.0.0.1:11950", "", "127.0.0.1", "127.0.0.1"},
 | 
						|
		{p, "[::1]:28660", "99.103.56.12", "99.103.56.12", "::1 (99.103.56.12)"},
 | 
						|
		{nil, "10.254.244.165:62750", "", "10.254.244.165", "10.254.244.165"},
 | 
						|
		// Parser is nil, the contents of X-Forwarded-For should be ignored in all cases.
 | 
						|
		{nil, "[2001:470:26:307:a5a1:1177:2ae3:e9c3]:48290", "127.0.0.1", "2001:470:26:307:a5a1:1177:2ae3:e9c3", "2001:470:26:307:a5a1:1177:2ae3:e9c3"},
 | 
						|
	}
 | 
						|
 | 
						|
	for _, test := range tests {
 | 
						|
		h := http.Header{}
 | 
						|
		h.Add("X-Forwarded-For", test.headerValue)
 | 
						|
		req := &http.Request{
 | 
						|
			Header:     h,
 | 
						|
			RemoteAddr: test.remoteAddr,
 | 
						|
		}
 | 
						|
 | 
						|
		client := getClientString(test.parser, req, false)
 | 
						|
		assert.Equal(t, test.expectedClient, client)
 | 
						|
 | 
						|
		clientFull := getClientString(test.parser, req, true)
 | 
						|
		assert.Equal(t, test.expectedClientFull, clientFull)
 | 
						|
	}
 | 
						|
}
 |