Merge pull request #10941 from appwrite/CLO-3704-utopia-request-extend

feat: improved reference client ip through _APP_TRUSTED_HEADERS
This commit is contained in:
Levi van Noort 2025-12-15 16:15:18 +01:00 committed by GitHub
commit f4bca74a59
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 67 additions and 15 deletions

1
.env
View file

@ -125,3 +125,4 @@ _APP_WEBHOOK_MAX_FAILED_ATTEMPTS=10
_APP_PROJECT_REGIONS=default
_APP_FUNCTIONS_CREATION_ABUSE_LIMIT=5000
_APP_STATS_USAGE_DUAL_WRITING_DBS=database_db_main
_APP_TRUSTED_HEADERS=x-forwarded-for

View file

@ -357,6 +357,15 @@ return [
'required' => false,
'question' => '',
'filter' => ''
],
[
'name' => '_APP_TRUSTED_HEADERS',
'description' => 'This option allows you to set the list of trusted headers, the value is a commaseparated list of HTTP header names, evaluated left-to-right for the first valid IP. Header names are treated case-insensitively.',
'introduction' => '1.8.0',
'default' => 'x-forwarded-for',
'required' => false,
'question' => '',
'filter' => ''
]
],
],

30
composer.lock generated
View file

@ -4264,16 +4264,16 @@
},
{
"name": "utopia-php/framework",
"version": "0.33.34",
"version": "0.33.35",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/http.git",
"reference": "76def92594c32504ec80eaacdb60ff8fad73c856"
"reference": "82b139fb04f30045db51b0d322224f222da32313"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/http/zipball/76def92594c32504ec80eaacdb60ff8fad73c856",
"reference": "76def92594c32504ec80eaacdb60ff8fad73c856",
"url": "https://api.github.com/repos/utopia-php/http/zipball/82b139fb04f30045db51b0d322224f222da32313",
"reference": "82b139fb04f30045db51b0d322224f222da32313",
"shasum": ""
},
"require": {
@ -4306,9 +4306,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/http/issues",
"source": "https://github.com/utopia-php/http/tree/0.33.34"
"source": "https://github.com/utopia-php/http/tree/0.33.35"
},
"time": "2025-12-08T07:55:31+00:00"
"time": "2025-12-12T08:33:52+00:00"
},
{
"name": "utopia-php/image",
@ -5011,22 +5011,22 @@
},
{
"name": "utopia-php/swoole",
"version": "0.8.4",
"version": "0.8.5",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/swoole.git",
"reference": "150c30700e738c52348cce9ed0e0f0ff96872081"
"reference": "e42b6b8e44c457a7b35d8a857d7af1d67d667c58"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/swoole/zipball/150c30700e738c52348cce9ed0e0f0ff96872081",
"reference": "150c30700e738c52348cce9ed0e0f0ff96872081",
"url": "https://api.github.com/repos/utopia-php/swoole/zipball/e42b6b8e44c457a7b35d8a857d7af1d67d667c58",
"reference": "e42b6b8e44c457a7b35d8a857d7af1d67d667c58",
"shasum": ""
},
"require": {
"ext-swoole": "*",
"php": ">=8.0",
"utopia-php/framework": "0.33.*"
"utopia-php/framework": "0.33.35"
},
"require-dev": {
"laravel/pint": "1.2.*",
@ -5056,9 +5056,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/swoole/issues",
"source": "https://github.com/utopia-php/swoole/tree/0.8.4"
"source": "https://github.com/utopia-php/swoole/tree/0.8.5"
},
"time": "2025-09-07T09:39:46+00:00"
"time": "2025-12-15T14:03:23+00:00"
},
{
"name": "utopia-php/system",
@ -8943,7 +8943,7 @@
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"stability-flags": {},
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
@ -8967,5 +8967,5 @@
"platform-overrides": {
"php": "8.3"
},
"plugin-api-version": "2.6.0"
"plugin-api-version": "2.9.0"
}

View file

@ -220,6 +220,7 @@ services:
- _APP_DATABASE_SHARED_NAMESPACE
- _APP_FUNCTIONS_CREATION_ABUSE_LIMIT
- _APP_CUSTOM_DOMAIN_DENY_LIST
- _APP_TRUSTED_HEADERS
extra_hosts:
- "host.docker.internal:host-gateway"

View file

@ -9,6 +9,7 @@ use Swoole\Http\Request as SwooleRequest;
use Utopia\Database\Validator\Authorization;
use Utopia\Route;
use Utopia\Swoole\Request as UtopiaRequest;
use Utopia\System\System;
class Request extends UtopiaRequest
{
@ -20,6 +21,9 @@ class Request extends UtopiaRequest
public function __construct(SwooleRequest $request)
{
$trustedHeaders = System::getEnv('_APP_TRUSTED_HEADERS', 'x-forwarded-for');
$this->setTrustedIpHeaders(explode(',', $trustedHeaders));
parent::__construct($request);
}

View file

@ -326,4 +326,41 @@ trait AccountBase
$this->assertEquals($response['headers']['status-code'], 204);
}
public function testFallbackForTrustedIp(): void
{
$email = uniqid() . 'user@localhost.test';
$password = 'password';
$name = 'User Name';
// call appwrite directly to avoid proxy stripping the headers
$this->client->setEndpoint('http://localhost/v1');
$response = $this->client->call(Client::METHOD_POST, '/account', array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-forwarded-for' => '191.0.113.195',
]), [
'userId' => ID::unique(),
'email' => $email,
'password' => $password,
'name' => $name,
]);
$this->assertEquals($response['headers']['status-code'], 201);
$response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-forwarded-for' => '191.0.113.195',
]), [
'email' => $email,
'password' => $password,
]);
$this->assertEquals($response['headers']['status-code'], 201);
$this->assertEquals('191.0.113.195', $response['body']['clientIp'] ?? $response['body']['ip'] ?? '');
}
}