2025-02-22 17:26:51 +00:00
< ? php
namespace Tests\E2E\Services\Proxy ;
2025-02-24 15:22:23 +00:00
use Appwrite\ID ;
2025-02-22 17:26:51 +00:00
use Appwrite\Tests\Async ;
2025-02-24 15:22:23 +00:00
use CURLFile ;
2025-02-22 17:26:51 +00:00
use Tests\E2E\Client ;
2026-02-10 05:04:24 +00:00
use Utopia\Console ;
2025-02-22 17:26:51 +00:00
trait ProxyBase
{
use Async ;
2025-02-22 17:56:51 +00:00
2025-02-24 15:22:23 +00:00
protected function listRules ( array $params = []) : mixed
{
$rule = $this -> client -> call ( Client :: METHOD_GET , '/proxy/rules' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), $params );
return $rule ;
}
2025-02-22 17:26:51 +00:00
2025-02-22 17:56:51 +00:00
protected function createAPIRule ( string $domain ) : mixed
{
$rule = $this -> client -> call ( Client :: METHOD_POST , '/proxy/rules/api' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'domain' => $domain ,
]);
return $rule ;
}
2025-02-24 15:22:23 +00:00
protected function updateRuleVerification ( string $ruleId ) : mixed
{
$rule = $this -> client -> call ( Client :: METHOD_PATCH , '/proxy/rules/' . $ruleId . '/verification' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), []);
return $rule ;
}
protected function createSiteRule ( string $domain , string $siteId , string $branch = '' ) : mixed
2025-02-22 17:56:51 +00:00
{
$rule = $this -> client -> call ( Client :: METHOD_POST , '/proxy/rules/site' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'domain' => $domain ,
'siteId' => $siteId ,
2025-02-24 15:22:23 +00:00
'branch' => $branch ,
]);
return $rule ;
}
protected function getRule ( string $ruleId ) : mixed
{
$rule = $this -> client -> call ( Client :: METHOD_GET , '/proxy/rules/' . $ruleId , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), []);
return $rule ;
}
2025-06-09 09:31:02 +00:00
protected function createRedirectRule ( string $domain , string $url , int $statusCode , string $resourceType , string $resourceId ) : mixed
2025-02-24 15:22:23 +00:00
{
$rule = $this -> client -> call ( Client :: METHOD_POST , '/proxy/rules/redirect' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'domain' => $domain ,
2025-03-07 17:00:20 +00:00
'url' => $url ,
'statusCode' => $statusCode ,
2025-06-09 09:31:02 +00:00
'resourceType' => $resourceType ,
'resourceId' => $resourceId ,
2025-02-22 17:56:51 +00:00
]);
return $rule ;
}
2025-02-28 09:47:48 +00:00
protected function createFunctionRule ( string $domain , string $functionId , string $branch = '' ) : mixed
2025-02-22 17:26:51 +00:00
{
2025-02-22 17:56:51 +00:00
$rule = $this -> client -> call ( Client :: METHOD_POST , '/proxy/rules/function' , array_merge ([
2025-02-22 17:26:51 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2025-02-22 17:56:51 +00:00
], $this -> getHeaders ()), [
'domain' => $domain ,
'functionId' => $functionId ,
2025-02-28 09:47:48 +00:00
'branch' => $branch ,
2025-02-22 17:56:51 +00:00
]);
2025-02-22 17:26:51 +00:00
return $rule ;
}
protected function deleteRule ( string $ruleId ) : mixed
{
$rule = $this -> client -> call ( Client :: METHOD_DELETE , '/proxy/rules/' . $ruleId , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), []);
return $rule ;
}
2025-02-22 17:56:51 +00:00
protected function setupAPIRule ( string $domain ) : string
{
$rule = $this -> createAPIRule ( $domain );
$this -> assertEquals ( 201 , $rule [ 'headers' ][ 'status-code' ], 'Failed to setup rule: ' . \json_encode ( $rule ));
return $rule [ 'body' ][ '$id' ];
}
2025-06-09 09:31:02 +00:00
protected function setupRedirectRule ( string $domain , string $url , int $statusCode , string $resourceType , string $resourceId ) : string
2025-02-24 15:22:23 +00:00
{
2025-06-09 09:31:02 +00:00
$rule = $this -> createRedirectRule ( $domain , $url , $statusCode , $resourceType , $resourceId );
2025-02-24 15:22:23 +00:00
$this -> assertEquals ( 201 , $rule [ 'headers' ][ 'status-code' ], 'Failed to setup rule: ' . \json_encode ( $rule ));
return $rule [ 'body' ][ '$id' ];
}
2025-02-28 09:47:48 +00:00
protected function setupFunctionRule ( string $domain , string $functionId , string $branch = '' ) : string
2025-02-22 17:56:51 +00:00
{
2025-02-28 09:47:48 +00:00
$rule = $this -> createFunctionRule ( $domain , $functionId , $branch );
2025-02-22 17:56:51 +00:00
$this -> assertEquals ( 201 , $rule [ 'headers' ][ 'status-code' ], 'Failed to setup rule: ' . \json_encode ( $rule ));
return $rule [ 'body' ][ '$id' ];
}
2025-02-24 15:22:23 +00:00
protected function setupSiteRule ( string $domain , string $siteId , string $branch = '' ) : string
2025-02-22 17:26:51 +00:00
{
2025-02-24 15:22:23 +00:00
$rule = $this -> createSiteRule ( $domain , $siteId , $branch );
2025-02-22 17:26:51 +00:00
$this -> assertEquals ( 201 , $rule [ 'headers' ][ 'status-code' ], 'Failed to setup rule: ' . \json_encode ( $rule ));
return $rule [ 'body' ][ '$id' ];
}
protected function cleanupRule ( string $ruleId ) : void
{
$rule = $this -> deleteRule ( $ruleId );
$this -> assertEquals ( 204 , $rule [ 'headers' ][ 'status-code' ], 'Failed to cleanup rule: ' . \json_encode ( $rule ));
}
2025-02-24 15:22:23 +00:00
2025-02-25 14:13:59 +00:00
protected function cleanupSite ( string $siteId ) : void
{
$site = $this -> client -> call ( Client :: METHOD_DELETE , '/sites/' . $siteId , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), []);
$this -> assertEquals ( 204 , $site [ 'headers' ][ 'status-code' ], 'Failed to cleanup site: ' . \json_encode ( $site ));
}
protected function cleanupFunction ( string $functionId ) : void
{
$function = $this -> client -> call ( Client :: METHOD_DELETE , '/functions/' . $functionId , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), []);
$this -> assertEquals ( 204 , $function [ 'headers' ][ 'status-code' ], 'Failed to cleanup function: ' . \json_encode ( $function ));
}
2025-02-24 15:22:23 +00:00
protected function setupSite () : mixed
{
// Site
$site = $this -> client -> call ( Client :: METHOD_POST , '/sites' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'x-appwrite-key' => $this -> getProject ()[ 'apiKey' ],
]), [
'siteId' => ID :: unique (),
'name' => 'Proxy site' ,
'framework' => 'other' ,
'adapter' => 'static' ,
'buildRuntime' => 'static-1' ,
'outputDirectory' => './' ,
'buildCommand' => '' ,
'installCommand' => '' ,
'fallbackFile' => '' ,
]);
$this -> assertEquals ( $site [ 'headers' ][ 'status-code' ], 201 , 'Setup site failed with status code: ' . $site [ 'headers' ][ 'status-code' ] . ' and response: ' . json_encode ( $site [ 'body' ], JSON_PRETTY_PRINT ));
$siteId = $site [ 'body' ][ '$id' ];
// Deployment
$deployment = $this -> client -> call ( Client :: METHOD_POST , '/sites/' . $siteId . '/deployments' , array_merge ([
'content-type' => 'multipart/form-data' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'x-appwrite-key' => $this -> getProject ()[ 'apiKey' ],
]), [
'code' => $this -> packageSite ( 'static' ),
'activate' => 'true'
]);
$this -> assertEquals ( $deployment [ 'headers' ][ 'status-code' ], 202 , 'Setup deployment failed with status code: ' . $deployment [ 'headers' ][ 'status-code' ] . ' and response: ' . json_encode ( $deployment [ 'body' ], JSON_PRETTY_PRINT ));
$deploymentId = $deployment [ 'body' ][ '$id' ] ? ? '' ;
$this -> assertEventually ( function () use ( $siteId , $deploymentId ) {
$site = $this -> client -> call ( Client :: METHOD_GET , '/sites/' . $siteId , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'x-appwrite-key' => $this -> getProject ()[ 'apiKey' ],
]));
$this -> assertEquals ( $deploymentId , $site [ 'body' ][ 'deploymentId' ], 'Deployment is not activated, deployment: ' . json_encode ( $site [ 'body' ], JSON_PRETTY_PRINT ));
}, 100000 , 500 );
2025-02-25 14:13:59 +00:00
return [ 'siteId' => $siteId , 'deploymentId' => $deploymentId ];
2025-02-24 15:22:23 +00:00
}
protected function setupFunction () : mixed
{
// Function
$function = $this -> client -> call ( Client :: METHOD_POST , '/functions' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'x-appwrite-key' => $this -> getProject ()[ 'apiKey' ],
]), [
'functionId' => ID :: unique (),
2025-07-10 12:43:56 +00:00
'runtime' => 'node-22' ,
2025-02-24 15:22:23 +00:00
'name' => 'Proxy Function' ,
'entrypoint' => 'index.js' ,
'commands' => '' ,
'execute' => [ 'any' ]
]);
$this -> assertEquals ( $function [ 'headers' ][ 'status-code' ], 201 , 'Setup function failed with status code: ' . $function [ 'headers' ][ 'status-code' ] . ' and response: ' . json_encode ( $function [ 'body' ], JSON_PRETTY_PRINT ));
$functionId = $function [ 'body' ][ '$id' ];
// Deployment
$deployment = $this -> client -> call ( Client :: METHOD_POST , '/functions/' . $functionId . '/deployments' , array_merge ([
'content-type' => 'multipart/form-data' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'x-appwrite-key' => $this -> getProject ()[ 'apiKey' ],
]), [
2025-07-10 12:25:53 +00:00
'code' => $this -> packageFunction ( 'basic' ),
2025-02-24 15:22:23 +00:00
'activate' => 'true'
]);
$this -> assertEquals ( $deployment [ 'headers' ][ 'status-code' ], 202 , 'Setup deployment failed with status code: ' . $deployment [ 'headers' ][ 'status-code' ] . ' and response: ' . json_encode ( $deployment [ 'body' ], JSON_PRETTY_PRINT ));
$deploymentId = $deployment [ 'body' ][ '$id' ] ? ? '' ;
$this -> assertEventually ( function () use ( $functionId , $deploymentId ) {
$function = $this -> client -> call ( Client :: METHOD_GET , '/functions/' . $functionId , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'x-appwrite-key' => $this -> getProject ()[ 'apiKey' ],
]));
2025-03-11 15:26:49 +00:00
$this -> assertEquals ( $deploymentId , $function [ 'body' ][ 'deploymentId' ], 'Deployment is not activated, deployment: ' . json_encode ( $function [ 'body' ], JSON_PRETTY_PRINT ));
2025-02-24 15:22:23 +00:00
}, 100000 , 500 );
2025-02-25 14:13:59 +00:00
return [ 'functionId' => $functionId , 'deploymentId' => $deploymentId ];
2025-02-24 15:22:23 +00:00
}
private function packageSite ( string $site ) : CURLFile
{
$stdout = '' ;
$stderr = '' ;
$folderPath = realpath ( __DIR__ . '/../../../resources/sites' ) . " / $site " ;
$tarPath = " $folderPath /code.tar.gz " ;
Console :: execute ( " cd $folderPath && tar --exclude code.tar.gz -czf code.tar.gz . " , '' , $stdout , $stderr );
if ( filesize ( $tarPath ) > 1024 * 1024 * 5 ) {
throw new \Exception ( 'Code package is too large. Use the chunked upload method instead.' );
}
return new CURLFile ( $tarPath , 'application/x-gzip' , \basename ( $tarPath ));
}
private function packageFunction ( string $function ) : CURLFile
{
$stdout = '' ;
$stderr = '' ;
$folderPath = realpath ( __DIR__ . '/../../../resources/functions' ) . " / $function " ;
$tarPath = " $folderPath /code.tar.gz " ;
Console :: execute ( " cd $folderPath && tar --exclude code.tar.gz -czf code.tar.gz . " , '' , $stdout , $stderr );
if ( filesize ( $tarPath ) > 1024 * 1024 * 5 ) {
throw new \Exception ( 'Code package is too large. Use the chunked upload method instead.' );
}
return new CURLFile ( $tarPath , 'application/x-gzip' , \basename ( $tarPath ));
}
2025-02-22 17:26:51 +00:00
}