@@ -53,6 +53,13 @@ class Request
5353 */
5454 protected $ headers = null ;
5555
56+ /**
57+ * List of trusted proxy header names to check for client IP address
58+ *
59+ * @var array
60+ */
61+ protected array $ trustedIpHeaders = ['x-forwarded-for ' ];
62+
5663 /**
5764 * Get Param
5865 *
@@ -160,17 +167,34 @@ public function setServer(string $key, string $value): static
160167 /**
161168 * Get IP
162169 *
163- * Returns users IP address.
164- * Support HTTP_X_FORWARDED_FOR header usually return
165- * from different proxy servers or PHP default REMOTE_ADDR
170+ * Extracts the client's IP address from trusted headers or falls back to the remote address.
171+ * Prioritizes headers like X-Forwarded-For when behind proxies or load balancers,
172+ * defaulting to REMOTE_ADDR when trusted headers are unavailable.
166173 *
167- * @return string
174+ * @return string The validated client IP address or '0.0.0.0' if unavailable
168175 */
169176 public function getIP (): string
170177 {
171- $ ips = explode (', ' , $ this ->getHeader ('HTTP_X_FORWARDED_FOR ' , $ this ->getServer ('REMOTE_ADDR ' ) ?? '0.0.0.0 ' ));
178+ $ remoteAddr = $ this ->getServer ('remote_addr ' ) ?? '0.0.0.0 ' ;
179+
180+ foreach ($ this ->trustedIpHeaders as $ header ) {
181+ $ headerValue = $ this ->getHeader ($ header );
182+
183+ if (empty ($ headerValue )) {
184+ continue ;
185+ }
186+
187+ // Leftmost IP address is the address of the originating client
188+ $ ips = explode (', ' , $ headerValue );
189+ $ ip = trim ($ ips [0 ]);
190+
191+ // Validate IP format (supports both IPv4 and IPv6)
192+ if (filter_var ($ ip , FILTER_VALIDATE_IP )) {
193+ return $ ip ;
194+ }
195+ }
172196
173- return trim ( $ ips [ 0 ] ?? '' ) ;
197+ return $ remoteAddr ;
174198 }
175199
176200 /**
0 commit comments