client_ip_test.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. // SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
  2. // SPDX-License-Identifier: Apache-2.0
  3. package request // import "miniflux.app/v2/internal/http/request"
  4. import (
  5. "net/http"
  6. "testing"
  7. )
  8. func TestFindClientIPWithoutHeaders(t *testing.T) {
  9. r := &http.Request{RemoteAddr: "192.168.0.1:4242"}
  10. if ip := FindClientIP(r, false); ip != "192.168.0.1" {
  11. t.Fatalf(`Unexpected result, got: %q`, ip)
  12. }
  13. r = &http.Request{RemoteAddr: "192.168.0.1"}
  14. if ip := FindClientIP(r, false); ip != "192.168.0.1" {
  15. t.Fatalf(`Unexpected result, got: %q`, ip)
  16. }
  17. r = &http.Request{RemoteAddr: "fe80::14c2:f039:edc7:edc7"}
  18. if ip := FindClientIP(r, false); ip != "fe80::14c2:f039:edc7:edc7" {
  19. t.Fatalf(`Unexpected result, got: %q`, ip)
  20. }
  21. r = &http.Request{RemoteAddr: "fe80::14c2:f039:edc7:edc7%eth0"}
  22. if ip := FindClientIP(r, false); ip != "fe80::14c2:f039:edc7:edc7" {
  23. t.Fatalf(`Unexpected result, got: %q`, ip)
  24. }
  25. r = &http.Request{RemoteAddr: "[fe80::14c2:f039:edc7:edc7%eth0]:4242"}
  26. if ip := FindClientIP(r, false); ip != "fe80::14c2:f039:edc7:edc7" {
  27. t.Fatalf(`Unexpected result, got: %q`, ip)
  28. }
  29. r = &http.Request{RemoteAddr: "@"}
  30. if ip := FindClientIP(r, false); ip != "127.0.0.1" {
  31. t.Fatalf(`Unexpected result, got: %q`, ip)
  32. }
  33. r = &http.Request{RemoteAddr: ""}
  34. if ip := FindClientIP(r, false); ip != "127.0.0.1" {
  35. t.Fatalf(`Unexpected result, got: %q`, ip)
  36. }
  37. }
  38. func TestFindClientIPWithXFFHeader(t *testing.T) {
  39. // Test with multiple IPv4 addresses.
  40. headers := http.Header{}
  41. headers.Set("X-Forwarded-For", "203.0.113.195, 70.41.3.18, 150.172.238.178")
  42. r := &http.Request{RemoteAddr: "192.168.0.1:4242", Header: headers}
  43. if ip := FindClientIP(r, true); ip != "203.0.113.195" {
  44. t.Fatalf(`Unexpected result, got: %q`, ip)
  45. }
  46. // Test with single IPv6 address.
  47. headers = http.Header{}
  48. headers.Set("X-Forwarded-For", "2001:db8:85a3:8d3:1319:8a2e:370:7348")
  49. r = &http.Request{RemoteAddr: "192.168.0.1:4242", Header: headers}
  50. if ip := FindClientIP(r, true); ip != "2001:db8:85a3:8d3:1319:8a2e:370:7348" {
  51. t.Fatalf(`Unexpected result, got: %q`, ip)
  52. }
  53. // Test with single IPv6 address with zone
  54. headers = http.Header{}
  55. headers.Set("X-Forwarded-For", "fe80::14c2:f039:edc7:edc7%eth0")
  56. r = &http.Request{RemoteAddr: "192.168.0.1:4242", Header: headers}
  57. if ip := FindClientIP(r, true); ip != "fe80::14c2:f039:edc7:edc7" {
  58. t.Fatalf(`Unexpected result, got: %q`, ip)
  59. }
  60. // Test with single IPv4 address.
  61. headers = http.Header{}
  62. headers.Set("X-Forwarded-For", "70.41.3.18")
  63. r = &http.Request{RemoteAddr: "192.168.0.1:4242", Header: headers}
  64. if ip := FindClientIP(r, true); ip != "70.41.3.18" {
  65. t.Fatalf(`Unexpected result, got: %q`, ip)
  66. }
  67. // Test with invalid IP address.
  68. headers = http.Header{}
  69. headers.Set("X-Forwarded-For", "fake IP")
  70. r = &http.Request{RemoteAddr: "192.168.0.1:4242", Header: headers}
  71. if ip := FindClientIP(r, true); ip != "192.168.0.1" {
  72. t.Fatalf(`Unexpected result, got: %q`, ip)
  73. }
  74. }
  75. func TestClientIPWithXRealIPHeader(t *testing.T) {
  76. headers := http.Header{}
  77. headers.Set("X-Real-Ip", "192.168.122.1")
  78. r := &http.Request{RemoteAddr: "192.168.0.1:4242", Header: headers}
  79. if ip := FindClientIP(r, true); ip != "192.168.122.1" {
  80. t.Fatalf(`Unexpected result, got: %q`, ip)
  81. }
  82. }
  83. func TestClientIPWithBothHeaders(t *testing.T) {
  84. headers := http.Header{}
  85. headers.Set("X-Forwarded-For", "203.0.113.195, 70.41.3.18, 150.172.238.178")
  86. headers.Set("X-Real-Ip", "192.168.122.1")
  87. r := &http.Request{RemoteAddr: "192.168.0.1:4242", Header: headers}
  88. if ip := FindClientIP(r, true); ip != "203.0.113.195" {
  89. t.Fatalf(`Unexpected result, got: %q`, ip)
  90. }
  91. }
  92. func TestClientIPWithUnixSocketRemoteAddrAndBothHeaders(t *testing.T) {
  93. headers := http.Header{}
  94. headers.Set("X-Forwarded-For", "203.0.113.195, 70.41.3.18, 150.172.238.178")
  95. headers.Set("X-Real-Ip", "192.168.122.1")
  96. r := &http.Request{RemoteAddr: "@", Header: headers}
  97. if ip := FindClientIP(r, true); ip != "203.0.113.195" {
  98. t.Fatalf(`Unexpected result, got: %q`, ip)
  99. }
  100. }
  101. func TestIsTrustedIP(t *testing.T) {
  102. trustedNetworks := []string{"127.0.0.1/8", "10.0.0.0/8", "::1/128", "invalid"}
  103. scenarios := []struct {
  104. ip string
  105. expected bool
  106. }{
  107. {"127.0.0.1", true},
  108. {"10.0.0.1", true},
  109. {"::1", true},
  110. {"192.168.1.1", false},
  111. {"invalid", false},
  112. {"@", false},
  113. {"/tmp/miniflux.sock", false},
  114. {"", false},
  115. }
  116. for _, scenario := range scenarios {
  117. result := IsTrustedIP(scenario.ip, trustedNetworks)
  118. if result != scenario.expected {
  119. t.Errorf("Expected %v for IP %s, got %v", scenario.expected, scenario.ip, result)
  120. }
  121. }
  122. if IsTrustedIP("127.0.0.1", nil) {
  123. t.Error("Expected false when no trusted networks are defined")
  124. }
  125. if IsTrustedIP("127.0.0.1", []string{}) {
  126. t.Error("Expected false when trusted networks list is empty")
  127. }
  128. }
  129. func TestFindRemoteIP(t *testing.T) {
  130. scenarios := []struct {
  131. ip string
  132. expected string
  133. }{
  134. {"192.168.0.1:4242", "192.168.0.1"},
  135. {"[2001:db8::1]:4242", "2001:db8::1"},
  136. {"fe80::14c2:f039:edc7:edc7%eth0", "fe80::14c2:f039:edc7:edc7"},
  137. {"", "127.0.0.1"},
  138. {"@", "127.0.0.1"},
  139. {"invalid", "127.0.0.1"},
  140. }
  141. for _, scenario := range scenarios {
  142. r := &http.Request{RemoteAddr: scenario.ip}
  143. result := FindRemoteIP(r)
  144. if result != scenario.expected {
  145. t.Errorf("Expected %q for RemoteAddr %q, got %q", scenario.expected, scenario.ip, result)
  146. }
  147. }
  148. }