github.com/ulule/limiter/v3@v3.11.3-0.20230613131926-4cb9c1da4633/network_test.go (about)

     1  package limiter_test
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  	"net/http"
     7  	"net/url"
     8  	"testing"
     9  
    10  	"github.com/stretchr/testify/require"
    11  
    12  	"github.com/ulule/limiter/v3"
    13  )
    14  
    15  func TestGetIP(t *testing.T) {
    16  	is := require.New(t)
    17  
    18  	limiter1 := New(limiter.WithTrustForwardHeader(false))
    19  	limiter2 := New(limiter.WithTrustForwardHeader(true))
    20  	limiter3 := New(limiter.WithIPv4Mask(net.CIDRMask(24, 32)))
    21  	limiter4 := New(limiter.WithIPv6Mask(net.CIDRMask(48, 128)))
    22  
    23  	request1 := &http.Request{
    24  		URL:        &url.URL{Path: "/"},
    25  		Header:     http.Header{},
    26  		RemoteAddr: "8.8.8.8:8888",
    27  	}
    28  
    29  	request2 := &http.Request{
    30  		URL:        &url.URL{Path: "/foo"},
    31  		Header:     http.Header{},
    32  		RemoteAddr: "8.8.8.8:8888",
    33  	}
    34  	request2.Header.Add("X-Forwarded-For", "9.9.9.9, 7.7.7.7, 6.6.6.6")
    35  
    36  	request3 := &http.Request{
    37  		URL:        &url.URL{Path: "/bar"},
    38  		Header:     http.Header{},
    39  		RemoteAddr: "8.8.8.8:8888",
    40  	}
    41  	request3.Header.Add("X-Real-IP", "6.6.6.6")
    42  
    43  	request4 := &http.Request{
    44  		URL:        &url.URL{Path: "/"},
    45  		Header:     http.Header{},
    46  		RemoteAddr: "[2001:db8:cafe:1234:beef::fafa]:8888",
    47  	}
    48  
    49  	scenarios := []struct {
    50  		request  *http.Request
    51  		limiter  *limiter.Limiter
    52  		expected net.IP
    53  	}{
    54  		{
    55  			//
    56  			// Scenario #1 : RemoteAddr without proxy.
    57  			//
    58  			request:  request1,
    59  			limiter:  limiter1,
    60  			expected: net.ParseIP("8.8.8.8").To4(),
    61  		},
    62  		{
    63  			//
    64  			// Scenario #2 : X-Forwarded-For without proxy.
    65  			//
    66  			request:  request2,
    67  			limiter:  limiter1,
    68  			expected: net.ParseIP("8.8.8.8").To4(),
    69  		},
    70  		{
    71  			//
    72  			// Scenario #3 : X-Real-IP without proxy.
    73  			//
    74  			request:  request3,
    75  			limiter:  limiter1,
    76  			expected: net.ParseIP("8.8.8.8").To4(),
    77  		},
    78  		{
    79  			//
    80  			// Scenario #4 : RemoteAddr with proxy.
    81  			//
    82  			request:  request1,
    83  			limiter:  limiter2,
    84  			expected: net.ParseIP("8.8.8.8").To4(),
    85  		},
    86  		{
    87  			//
    88  			// Scenario #5 : X-Forwarded-For with proxy.
    89  			//
    90  			request:  request2,
    91  			limiter:  limiter2,
    92  			expected: net.ParseIP("9.9.9.9").To4(),
    93  		},
    94  		{
    95  			//
    96  			// Scenario #6 : X-Real-IP with proxy.
    97  			//
    98  			request:  request3,
    99  			limiter:  limiter2,
   100  			expected: net.ParseIP("6.6.6.6").To4(),
   101  		},
   102  		{
   103  			//
   104  			// Scenario #7 : IPv4 with mask.
   105  			//
   106  			request:  request1,
   107  			limiter:  limiter3,
   108  			expected: net.ParseIP("8.8.8.0").To4(),
   109  		},
   110  		{
   111  			//
   112  			// Scenario #8 : IPv6 with mask.
   113  			//
   114  			request:  request4,
   115  			limiter:  limiter4,
   116  			expected: net.ParseIP("2001:db8:cafe::").To16(),
   117  		},
   118  	}
   119  
   120  	for i, scenario := range scenarios {
   121  		message := fmt.Sprintf("Scenario #%d", (i + 1))
   122  		ip := scenario.limiter.GetIPWithMask(scenario.request)
   123  		is.Equal(scenario.expected, ip, message)
   124  	}
   125  }
   126  
   127  func TestGetIPKey(t *testing.T) {
   128  	is := require.New(t)
   129  
   130  	limiter1 := New(limiter.WithTrustForwardHeader(false))
   131  	limiter2 := New(limiter.WithTrustForwardHeader(true))
   132  	limiter3 := New(limiter.WithIPv4Mask(net.CIDRMask(24, 32)))
   133  	limiter4 := New(limiter.WithIPv6Mask(net.CIDRMask(48, 128)))
   134  
   135  	request1 := &http.Request{
   136  		URL:        &url.URL{Path: "/"},
   137  		Header:     http.Header{},
   138  		RemoteAddr: "8.8.8.8:8888",
   139  	}
   140  
   141  	request2 := &http.Request{
   142  		URL:        &url.URL{Path: "/foo"},
   143  		Header:     http.Header{},
   144  		RemoteAddr: "8.8.8.8:8888",
   145  	}
   146  	request2.Header.Add("X-Forwarded-For", "9.9.9.9, 7.7.7.7, 6.6.6.6")
   147  
   148  	request3 := &http.Request{
   149  		URL:        &url.URL{Path: "/bar"},
   150  		Header:     http.Header{},
   151  		RemoteAddr: "8.8.8.8:8888",
   152  	}
   153  	request3.Header.Add("X-Real-IP", "6.6.6.6")
   154  
   155  	request4 := &http.Request{
   156  		URL:        &url.URL{Path: "/"},
   157  		Header:     http.Header{},
   158  		RemoteAddr: "[2001:db8:cafe:1234:beef::fafa]:8888",
   159  	}
   160  
   161  	scenarios := []struct {
   162  		request  *http.Request
   163  		limiter  *limiter.Limiter
   164  		expected string
   165  	}{
   166  		{
   167  			//
   168  			// Scenario #1 : RemoteAddr without proxy.
   169  			//
   170  			request:  request1,
   171  			limiter:  limiter1,
   172  			expected: "8.8.8.8",
   173  		},
   174  		{
   175  			//
   176  			// Scenario #2 : X-Forwarded-For without proxy.
   177  			//
   178  			request:  request2,
   179  			limiter:  limiter1,
   180  			expected: "8.8.8.8",
   181  		},
   182  		{
   183  			//
   184  			// Scenario #3 : X-Real-IP without proxy.
   185  			//
   186  			request:  request3,
   187  			limiter:  limiter1,
   188  			expected: "8.8.8.8",
   189  		},
   190  		{
   191  			//
   192  			// Scenario #4 : RemoteAddr without proxy.
   193  			//
   194  			request:  request1,
   195  			limiter:  limiter2,
   196  			expected: "8.8.8.8",
   197  		},
   198  		{
   199  			//
   200  			// Scenario #5 : X-Forwarded-For without proxy.
   201  			//
   202  			request:  request2,
   203  			limiter:  limiter2,
   204  			expected: "9.9.9.9",
   205  		},
   206  		{
   207  			//
   208  			// Scenario #6 : X-Real-IP without proxy.
   209  			//
   210  			request:  request3,
   211  			limiter:  limiter2,
   212  			expected: "6.6.6.6",
   213  		},
   214  		{
   215  			//
   216  			// Scenario #7 : IPv4 with mask.
   217  			//
   218  			request:  request1,
   219  			limiter:  limiter3,
   220  			expected: "8.8.8.0",
   221  		},
   222  		{
   223  			//
   224  			// Scenario #8 : IPv6 with mask.
   225  			//
   226  			request:  request4,
   227  			limiter:  limiter4,
   228  			expected: "2001:db8:cafe::",
   229  		},
   230  	}
   231  
   232  	for i, scenario := range scenarios {
   233  		message := fmt.Sprintf("Scenario #%d", (i + 1))
   234  		key := scenario.limiter.GetIPKey(scenario.request)
   235  		is.Equal(scenario.expected, key, message)
   236  	}
   237  }