Skip to content
This repository was archived by the owner on Apr 29, 2026. It is now read-only.

Commit e42b6b8

Browse files
authored
Merge pull request #36 from utopia-php/clo-3704-duplicate-changes-to-swoole-due-to-overwrite
chore: duplicate changes from http to swoole
2 parents 150c307 + 1f06c2d commit e42b6b8

5 files changed

Lines changed: 114 additions & 26 deletions

File tree

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"require": {
1616
"php": ">=8.0",
1717
"ext-swoole": "*",
18-
"utopia-php/framework": "0.33.*"
18+
"utopia-php/framework": "0.33.35"
1919
},
2020
"require-dev": {
2121
"phpunit/phpunit": "^9.3",

composer.lock

Lines changed: 62 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docker-compose.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
version: '3'
2-
31
services:
42
php:
53
image: swoole-dev

src/Swoole/Request.php

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ class Request extends UtopiaRequest
1414
*/
1515
protected SwooleRequest $swoole;
1616

17+
/**
18+
* List of trusted proxy header names to check for client IP address
19+
*
20+
* @var array<string>
21+
*/
22+
protected array $trustedIpHeaders = [];
23+
1724
/**
1825
* Request constructor.
1926
*/
@@ -64,18 +71,55 @@ public function setServer(string $key, string $value): static
6471
return $this;
6572
}
6673

74+
/**
75+
* Set trusted ip headers
76+
*
77+
* WARNING: Only set these headers if your application is behind a trusted proxy.
78+
* Trusting these headers when accepting direct client connections is a security risk.
79+
*
80+
* @param array<string> $headers List of header names to trust (e.g., ['x-forwarded-for', 'x-real-ip'])
81+
* @return static
82+
*/
83+
public function setTrustedIpHeaders(array $headers): static
84+
{
85+
$normalized = array_map('strtolower', $headers);
86+
$trimmed = array_map('trim', $normalized);
87+
$this->trustedIpHeaders = array_filter($trimmed);
88+
89+
return $this;
90+
}
91+
6792
/**
6893
* Get IP
6994
*
70-
* Returns users IP address.
71-
* Support HTTP_X_FORWARDED_FOR header usually return
72-
* from different proxy servers or PHP default REMOTE_ADDR
95+
* Extracts the client's IP address from trusted headers or falls back to the remote address.
96+
* Prioritizes headers like X-Forwarded-For when behind proxies or load balancers,
97+
* defaulting to REMOTE_ADDR when trusted headers are unavailable.
98+
*
99+
* @return string The validated client IP address or '0.0.0.0' if unavailable
73100
*/
74101
public function getIP(): string
75102
{
76-
$ips = explode(',', $this->getHeader('x-forwarded-for', $this->getServer('remote_addr') ?? '0.0.0.0'));
103+
$remoteAddr = $this->getServer('REMOTE_ADDR') ?? '0.0.0.0';
104+
105+
foreach ($this->trustedIpHeaders as $header) {
106+
$headerValue = $this->getHeader($header);
107+
108+
if (empty($headerValue)) {
109+
continue;
110+
}
111+
112+
// Leftmost IP address is the address of the originating client
113+
$ips = explode(',', $headerValue);
114+
$ip = trim($ips[0]);
115+
116+
// Validate IP format (supports both IPv4 and IPv6)
117+
if (filter_var($ip, FILTER_VALIDATE_IP)) {
118+
return $ip;
119+
}
120+
}
77121

78-
return trim($ips[0] ?? '');
122+
return $remoteAddr;
79123
}
80124

81125
/**

tests/e2e/server.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@
7171
->inject('request')
7272
->inject('response')
7373
->action(function (Request $request, Response $response) {
74-
$response->addHeader('Set-Cookie', 'key1=value1');
75-
$response->addHeader('Set-Cookie', 'key2=value2');
74+
$response->addHeader('Set-Cookie', 'key1=value1', override: false);
75+
$response->addHeader('Set-Cookie', 'key2=value2', override: false);
7676
$response->send('OK');
7777
});
7878

0 commit comments

Comments
 (0)