mirror of
https://github.com/appwrite/appwrite
synced 2026-05-24 09:28:40 +00:00
Merge branch '1.7.x' into feat-add-branch-url-for-first-git-deployment
This commit is contained in:
commit
ef12f49277
8 changed files with 109 additions and 13 deletions
|
|
@ -25446,12 +25446,33 @@
|
||||||
"Temporary Redirect 307",
|
"Temporary Redirect 307",
|
||||||
"Permanent Redirect 308"
|
"Permanent Redirect 308"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"resourceId": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "ID of parent resource.",
|
||||||
|
"x-example": "<RESOURCE_ID>"
|
||||||
|
},
|
||||||
|
"resourceType": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Type of parent resource.",
|
||||||
|
"x-example": "site",
|
||||||
|
"enum": [
|
||||||
|
"site",
|
||||||
|
"function"
|
||||||
|
],
|
||||||
|
"x-enum-name": "ProxyResourceType",
|
||||||
|
"x-enum-keys": [
|
||||||
|
"Site",
|
||||||
|
"Function"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"domain",
|
"domain",
|
||||||
"url",
|
"url",
|
||||||
"statusCode"
|
"statusCode",
|
||||||
|
"resourceId",
|
||||||
|
"resourceType"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25696,12 +25696,35 @@
|
||||||
"Temporary Redirect 307",
|
"Temporary Redirect 307",
|
||||||
"Permanent Redirect 308"
|
"Permanent Redirect 308"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"resourceId": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "ID of parent resource.",
|
||||||
|
"default": null,
|
||||||
|
"x-example": "<RESOURCE_ID>"
|
||||||
|
},
|
||||||
|
"resourceType": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Type of parent resource.",
|
||||||
|
"default": null,
|
||||||
|
"x-example": "site",
|
||||||
|
"enum": [
|
||||||
|
"site",
|
||||||
|
"function"
|
||||||
|
],
|
||||||
|
"x-enum-name": "ProxyResourceType",
|
||||||
|
"x-enum-keys": [
|
||||||
|
"Site",
|
||||||
|
"Function"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"domain",
|
"domain",
|
||||||
"url",
|
"url",
|
||||||
"statusCode"
|
"statusCode",
|
||||||
|
"resourceId",
|
||||||
|
"resourceType"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -105,9 +105,11 @@ class Get extends Action
|
||||||
|
|
||||||
$response
|
$response
|
||||||
->setContentType('application/gzip')
|
->setContentType('application/gzip')
|
||||||
->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days
|
->addHeader('Cache-Control', 'no-cache, no-store, must-revalidate')
|
||||||
|
->addHeader('Expires', '0')
|
||||||
|
->addHeader('Pragma', 'no-cache')
|
||||||
->addHeader('X-Peak', \memory_get_peak_usage())
|
->addHeader('X-Peak', \memory_get_peak_usage())
|
||||||
->addHeader('Content-Disposition', 'attachment; filename="' . $deploymentId . '.tar.gz"');
|
->addHeader('Content-Disposition', 'attachment; filename="' . $deploymentId . '-' . $type . '.tar.gz"');
|
||||||
|
|
||||||
$size = $device->getFileSize($path);
|
$size = $device->getFileSize($path);
|
||||||
$rangeHeader = $request->getHeader('range');
|
$rangeHeader = $request->getHeader('range');
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ use Utopia\Database\Database;
|
||||||
use Utopia\Database\Document;
|
use Utopia\Database\Document;
|
||||||
use Utopia\Database\Exception\Duplicate;
|
use Utopia\Database\Exception\Duplicate;
|
||||||
use Utopia\Database\Helpers\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
|
use Utopia\Database\Validator\UID;
|
||||||
use Utopia\Domains\Domain;
|
use Utopia\Domains\Domain;
|
||||||
use Utopia\Platform\Action;
|
use Utopia\Platform\Action;
|
||||||
use Utopia\Platform\Scope\HTTP;
|
use Utopia\Platform\Scope\HTTP;
|
||||||
|
|
@ -65,15 +66,18 @@ class Create extends Action
|
||||||
->param('domain', null, new ValidatorDomain(), 'Domain name.')
|
->param('domain', null, new ValidatorDomain(), 'Domain name.')
|
||||||
->param('url', null, new URL(), 'Target URL of redirection')
|
->param('url', null, new URL(), 'Target URL of redirection')
|
||||||
->param('statusCode', null, new WhiteList([301, 302, 307, 308]), 'Status code of redirection')
|
->param('statusCode', null, new WhiteList([301, 302, 307, 308]), 'Status code of redirection')
|
||||||
|
->param('resourceId', '', new UID(), 'ID of parent resource.')
|
||||||
|
->param('resourceType', '', new WhiteList(['site', 'function']), 'Type of parent resource.')
|
||||||
->inject('response')
|
->inject('response')
|
||||||
->inject('project')
|
->inject('project')
|
||||||
->inject('queueForCertificates')
|
->inject('queueForCertificates')
|
||||||
->inject('queueForEvents')
|
->inject('queueForEvents')
|
||||||
->inject('dbForPlatform')
|
->inject('dbForPlatform')
|
||||||
|
->inject('dbForProject')
|
||||||
->callback([$this, 'action']);
|
->callback([$this, 'action']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function action(string $domain, string $url, int $statusCode, Response $response, Document $project, Certificate $queueForCertificates, Event $queueForEvents, Database $dbForPlatform)
|
public function action(string $domain, string $url, int $statusCode, string $resourceId, string $resourceType, Response $response, Document $project, Certificate $queueForCertificates, Event $queueForEvents, Database $dbForPlatform, Database $dbForProject)
|
||||||
{
|
{
|
||||||
$deniedDomains = [
|
$deniedDomains = [
|
||||||
'localhost',
|
'localhost',
|
||||||
|
|
@ -116,6 +120,15 @@ class Create extends Action
|
||||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Domain may not start with http:// or https://.');
|
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Domain may not start with http:// or https://.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$collection = match ($resourceType) {
|
||||||
|
'site' => 'sites',
|
||||||
|
'function' => 'functions'
|
||||||
|
};
|
||||||
|
$resource = $dbForProject->getDocument($collection, $resourceId);
|
||||||
|
if ($resource->isEmpty()) {
|
||||||
|
throw new Exception(Exception::RULE_RESOURCE_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: @christyjacob remove once we migrate the rules in 1.7.x
|
// TODO: @christyjacob remove once we migrate the rules in 1.7.x
|
||||||
$ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain->get()) : ID::unique();
|
$ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain->get()) : ID::unique();
|
||||||
|
|
||||||
|
|
@ -164,6 +177,9 @@ class Create extends Action
|
||||||
'trigger' => 'manual',
|
'trigger' => 'manual',
|
||||||
'redirectUrl' => $url,
|
'redirectUrl' => $url,
|
||||||
'redirectStatusCode' => $statusCode,
|
'redirectStatusCode' => $statusCode,
|
||||||
|
'deploymentResourceType' => $resourceType,
|
||||||
|
'deploymentResourceId' => $resource->getId(),
|
||||||
|
'deploymentResourceInternalId' => $resource->getInternalId(),
|
||||||
'certificateId' => '',
|
'certificateId' => '',
|
||||||
'search' => implode(' ', [$ruleId, $domain->get()]),
|
'search' => implode(' ', [$ruleId, $domain->get()]),
|
||||||
'owner' => $owner,
|
'owner' => $owner,
|
||||||
|
|
|
||||||
|
|
@ -99,12 +99,14 @@ class Get extends Action
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$device->exists($path)) {
|
if (!$device->exists($path)) {
|
||||||
throw new Exception(Exception::BUILD_NOT_FOUND);
|
throw new Exception(Exception::DEPLOYMENT_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response
|
$response
|
||||||
->setContentType('application/gzip')
|
->setContentType('application/gzip')
|
||||||
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache
|
->addHeader('Cache-Control', 'no-cache, no-store, must-revalidate')
|
||||||
|
->addHeader('Expires', '0')
|
||||||
|
->addHeader('Pragma', 'no-cache')
|
||||||
->addHeader('X-Peak', \memory_get_peak_usage())
|
->addHeader('X-Peak', \memory_get_peak_usage())
|
||||||
->addHeader('Content-Disposition', 'attachment; filename="' . $deploymentId . '-' . $type . '.tar.gz"');
|
->addHeader('Content-Disposition', 'attachment; filename="' . $deploymentId . '-' . $type . '.tar.gz"');
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,16 @@ abstract class Format
|
||||||
protected function getEnumName(string $service, string $method, string $param): ?string
|
protected function getEnumName(string $service, string $method, string $param): ?string
|
||||||
{
|
{
|
||||||
switch ($service) {
|
switch ($service) {
|
||||||
|
case 'proxy':
|
||||||
|
switch ($method) {
|
||||||
|
case 'createRedirectRule':
|
||||||
|
switch ($param) {
|
||||||
|
case 'resourceType':
|
||||||
|
return 'ProxyResourceType';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'console':
|
case 'console':
|
||||||
switch ($method) {
|
switch ($method) {
|
||||||
case 'getResource':
|
case 'getResource':
|
||||||
|
|
@ -441,7 +451,13 @@ abstract class Format
|
||||||
case 'proxy':
|
case 'proxy':
|
||||||
switch ($method) {
|
switch ($method) {
|
||||||
case 'createRedirectRule':
|
case 'createRedirectRule':
|
||||||
return ['Moved Permanently 301', 'Found 302', 'Temporary Redirect 307', 'Permanent Redirect 308'];
|
switch ($param) {
|
||||||
|
case 'statusCode':
|
||||||
|
return ['Moved Permanently 301', 'Found 302', 'Temporary Redirect 307', 'Permanent Redirect 308'];
|
||||||
|
case 'resourceType':
|
||||||
|
return ['Site', 'Function'];
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'functions':
|
case 'functions':
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ trait ProxyBase
|
||||||
return $rule;
|
return $rule;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function createRedirectRule(string $domain, string $url, int $statusCode): mixed
|
protected function createRedirectRule(string $domain, string $url, int $statusCode, string $resourceType, string $resourceId): mixed
|
||||||
{
|
{
|
||||||
$rule = $this->client->call(Client::METHOD_POST, '/proxy/rules/redirect', array_merge([
|
$rule = $this->client->call(Client::METHOD_POST, '/proxy/rules/redirect', array_merge([
|
||||||
'content-type' => 'application/json',
|
'content-type' => 'application/json',
|
||||||
|
|
@ -77,6 +77,8 @@ trait ProxyBase
|
||||||
'domain' => $domain,
|
'domain' => $domain,
|
||||||
'url' => $url,
|
'url' => $url,
|
||||||
'statusCode' => $statusCode,
|
'statusCode' => $statusCode,
|
||||||
|
'resourceType' => $resourceType,
|
||||||
|
'resourceId' => $resourceId,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return $rule;
|
return $rule;
|
||||||
|
|
@ -115,9 +117,9 @@ trait ProxyBase
|
||||||
return $rule['body']['$id'];
|
return $rule['body']['$id'];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function setupRedirectRule(string $domain, string $url, int $statusCode): string
|
protected function setupRedirectRule(string $domain, string $url, int $statusCode, string $resourceType, string $resourceId): string
|
||||||
{
|
{
|
||||||
$rule = $this->createRedirectRule($domain, $url, $statusCode);
|
$rule = $this->createRedirectRule($domain, $url, $statusCode, $resourceType, $resourceId);
|
||||||
|
|
||||||
$this->assertEquals(201, $rule['headers']['status-code'], 'Failed to setup rule: ' . \json_encode($rule));
|
$this->assertEquals(201, $rule['headers']['status-code'], 'Failed to setup rule: ' . \json_encode($rule));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,9 @@ class ProxyCustomServerTest extends Scope
|
||||||
$response = $proxyClient->call(Client::METHOD_GET, '/todos/1');
|
$response = $proxyClient->call(Client::METHOD_GET, '/todos/1');
|
||||||
$this->assertEquals(404, $response['headers']['status-code']);
|
$this->assertEquals(404, $response['headers']['status-code']);
|
||||||
|
|
||||||
$ruleId = $this->setupRedirectRule($domain, 'https://jsonplaceholder.typicode.com/todos/1', 301);
|
$siteId = $this->setupSite()['siteId'];
|
||||||
|
|
||||||
|
$ruleId = $this->setupRedirectRule($domain, 'https://jsonplaceholder.typicode.com/todos/1', 301, 'site', $siteId);
|
||||||
$this->assertNotEmpty($ruleId);
|
$this->assertNotEmpty($ruleId);
|
||||||
|
|
||||||
$response = $proxyClient->call(Client::METHOD_GET, '/todos/1');
|
$response = $proxyClient->call(Client::METHOD_GET, '/todos/1');
|
||||||
|
|
@ -147,7 +149,7 @@ class ProxyCustomServerTest extends Scope
|
||||||
$this->assertEquals('https://jsonplaceholder.typicode.com/todos/1', $response['headers']['location']);
|
$this->assertEquals('https://jsonplaceholder.typicode.com/todos/1', $response['headers']['location']);
|
||||||
|
|
||||||
$domain = \uniqid() . '-redirect-307.custom.localhost';
|
$domain = \uniqid() . '-redirect-307.custom.localhost';
|
||||||
$ruleId = $this->setupRedirectRule($domain, 'https://jsonplaceholder.typicode.com/todos/1', 307);
|
$ruleId = $this->setupRedirectRule($domain, 'https://jsonplaceholder.typicode.com/todos/1', 307, 'site', $siteId);
|
||||||
$this->assertNotEmpty($ruleId);
|
$this->assertNotEmpty($ruleId);
|
||||||
|
|
||||||
$proxyClient = new Client();
|
$proxyClient = new Client();
|
||||||
|
|
@ -158,6 +160,18 @@ class ProxyCustomServerTest extends Scope
|
||||||
$this->assertEquals(307, $response['headers']['status-code']);
|
$this->assertEquals(307, $response['headers']['status-code']);
|
||||||
$this->assertEquals('https://jsonplaceholder.typicode.com/todos/1', $response['headers']['location']);
|
$this->assertEquals('https://jsonplaceholder.typicode.com/todos/1', $response['headers']['location']);
|
||||||
|
|
||||||
|
$rules = $this->listRules([
|
||||||
|
'queries' => [
|
||||||
|
Query::equal('type', ['redirect'])->toString(),
|
||||||
|
Query::equal('trigger', ['manual'])->toString(),
|
||||||
|
Query::equal('deploymentResourceType', ['site'])->toString(),
|
||||||
|
Query::equal('deploymentResourceId', [$siteId])->toString(),
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
$this->assertEquals(200, $rules['headers']['status-code']);
|
||||||
|
$this->assertEquals(2, $rules['body']['total']);
|
||||||
|
|
||||||
|
$this->cleanupSite($siteId);
|
||||||
$this->cleanupRule($ruleId);
|
$this->cleanupRule($ruleId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue