Basic implementation for Open Runtimes V2
This commit is contained in:
parent
543246c50b
commit
eea635fe4b
10 changed files with 115 additions and 1 deletions
1
.env
1
.env
|
@ -14,6 +14,7 @@ _APP_OPTIONS_ABUSE=disabled
|
||||||
_APP_OPTIONS_FORCE_HTTPS=disabled
|
_APP_OPTIONS_FORCE_HTTPS=disabled
|
||||||
_APP_OPENSSL_KEY_V1=your-secret-key
|
_APP_OPENSSL_KEY_V1=your-secret-key
|
||||||
_APP_DOMAIN=demo.appwrite.io
|
_APP_DOMAIN=demo.appwrite.io
|
||||||
|
_APP_DOMAIN_FUNCTIONS=functions.localhost
|
||||||
_APP_DOMAIN_TARGET=demo.appwrite.io
|
_APP_DOMAIN_TARGET=demo.appwrite.io
|
||||||
_APP_REDIS_HOST=redis
|
_APP_REDIS_HOST=redis
|
||||||
_APP_REDIS_PORT=6379
|
_APP_REDIS_PORT=6379
|
||||||
|
|
|
@ -191,6 +191,7 @@ ENV _APP_SERVER=swoole \
|
||||||
_APP_LOCALE=en \
|
_APP_LOCALE=en \
|
||||||
_APP_DOMAIN=localhost \
|
_APP_DOMAIN=localhost \
|
||||||
_APP_DOMAIN_TARGET=localhost \
|
_APP_DOMAIN_TARGET=localhost \
|
||||||
|
_APP_DOMAIN_FUNCTIONS=disabled \
|
||||||
_APP_HOME=https://appwrite.io \
|
_APP_HOME=https://appwrite.io \
|
||||||
_APP_EDITION=community \
|
_APP_EDITION=community \
|
||||||
_APP_CONSOLE_WHITELIST_ROOT=enabled \
|
_APP_CONSOLE_WHITELIST_ROOT=enabled \
|
||||||
|
|
|
@ -514,6 +514,16 @@ return [
|
||||||
'description' => 'The project key has expired. Please generate a new key using the Appwrite console.',
|
'description' => 'The project key has expired. Please generate a new key using the Appwrite console.',
|
||||||
'code' => 401,
|
'code' => 401,
|
||||||
],
|
],
|
||||||
|
Exception::ROUTER_INVALID_URL => [
|
||||||
|
'name' => Exception::ROUTER_INVALID_URL,
|
||||||
|
'description' => 'Invalid preview URL for Appwrite Router.',
|
||||||
|
'code' => 400,
|
||||||
|
],
|
||||||
|
Exception::ROUTER_CONSOLE_PROJECT => [
|
||||||
|
'name' => Exception::ROUTER_CONSOLE_PROJECT,
|
||||||
|
'description' => 'Use of "console" project with Appwrite Router is not allowed.',
|
||||||
|
'code' => 400,
|
||||||
|
],
|
||||||
Exception::WEBHOOK_NOT_FOUND => [
|
Exception::WEBHOOK_NOT_FOUND => [
|
||||||
'name' => Exception::WEBHOOK_NOT_FOUND,
|
'name' => Exception::WEBHOOK_NOT_FOUND,
|
||||||
'description' => 'Webhook with the requested ID could not be found.',
|
'description' => 'Webhook with the requested ID could not be found.',
|
||||||
|
|
|
@ -61,6 +61,15 @@ return [
|
||||||
'question' => 'Enter your Appwrite hostname',
|
'question' => 'Enter your Appwrite hostname',
|
||||||
'filter' => ''
|
'filter' => ''
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'name' => '_APP_DOMAIN_FUNCTIONS',
|
||||||
|
'description' => 'A domain to use for function preview URLs. Setting to "disabled" turns off function preview URLs.',
|
||||||
|
'introduction' => '',
|
||||||
|
'default' => 'disabled',
|
||||||
|
'required' => false,
|
||||||
|
'question' => '',
|
||||||
|
'filter' => ''
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'name' => '_APP_DOMAIN_TARGET',
|
'name' => '_APP_DOMAIN_TARGET',
|
||||||
'description' => 'A DNS A record hostname to serve as a CNAME target for your Appwrite custom domains. You can use the same value as used for the Appwrite \'_APP_DOMAIN\' variable. The default value is \'localhost\'.',
|
'description' => 'A DNS A record hostname to serve as a CNAME target for your Appwrite custom domains. You can use the same value as used for the Appwrite \'_APP_DOMAIN\' variable. The default value is \'localhost\'.',
|
||||||
|
|
|
@ -8,6 +8,10 @@ use Utopia\Locale\Locale;
|
||||||
use Utopia\Logger\Logger;
|
use Utopia\Logger\Logger;
|
||||||
use Utopia\Logger\Log;
|
use Utopia\Logger\Log;
|
||||||
use Utopia\Logger\Log\User;
|
use Utopia\Logger\Log\User;
|
||||||
|
use Swoole\Http\Request as SwooleRequest;
|
||||||
|
use Swoole\Http\Response as SwooleResponse;
|
||||||
|
use Utopia\Cache\Cache;
|
||||||
|
use Utopia\Pools\Group;
|
||||||
use Appwrite\Utopia\Request;
|
use Appwrite\Utopia\Request;
|
||||||
use Appwrite\Utopia\Response;
|
use Appwrite\Utopia\Response;
|
||||||
use Appwrite\Utopia\View;
|
use Appwrite\Utopia\View;
|
||||||
|
@ -42,6 +46,8 @@ Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE);
|
||||||
|
|
||||||
App::init()
|
App::init()
|
||||||
->inject('utopia')
|
->inject('utopia')
|
||||||
|
->inject('swooleRequest')
|
||||||
|
->inject('swooleResponse')
|
||||||
->inject('request')
|
->inject('request')
|
||||||
->inject('response')
|
->inject('response')
|
||||||
->inject('console')
|
->inject('console')
|
||||||
|
@ -51,7 +57,80 @@ App::init()
|
||||||
->inject('locale')
|
->inject('locale')
|
||||||
->inject('clients')
|
->inject('clients')
|
||||||
->inject('servers')
|
->inject('servers')
|
||||||
->action(function (App $utopia, Request $request, Response $response, Document $console, Document $project, Database $dbForConsole, Document $user, Locale $locale, array $clients, array $servers) {
|
->inject('pools')
|
||||||
|
->inject('cache')
|
||||||
|
->action(function (App $utopia, SwooleRequest $swooleRequest, SwooleResponse $swooleResponse, Request $request, Response $response, Document $console, Document $project, Database $dbForConsole, Document $user, Locale $locale, array $clients, array $servers, Group $pools, Cache $cache) {
|
||||||
|
/*
|
||||||
|
* Appwrite Router
|
||||||
|
*/
|
||||||
|
$host = $swooleRequest->header['host'] ?? '';
|
||||||
|
|
||||||
|
// Function Preview
|
||||||
|
if(\str_ends_with($host, App::getEnv('_APP_DOMAIN_FUNCTIONS'))) {
|
||||||
|
$host = rtrim($host, App::getEnv('_APP_DOMAIN_FUNCTIONS'));
|
||||||
|
$host = rtrim($host, '.');
|
||||||
|
$subdomains = explode('.', $host);
|
||||||
|
|
||||||
|
if(\count($subdomains) === 2) {
|
||||||
|
// Active deployment preview
|
||||||
|
$functionId = $subdomains[0];
|
||||||
|
$projectId = $subdomains[1];
|
||||||
|
|
||||||
|
if($projectId === 'console') {
|
||||||
|
throw new AppwriteException(AppwriteException::ROUTER_CONSOLE_PROJECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Rate limit?
|
||||||
|
|
||||||
|
$body = \json_encode([
|
||||||
|
'async' => false,
|
||||||
|
'data' => 'Heyy'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$headers = [
|
||||||
|
'Content-Type: application/json',
|
||||||
|
'Content-Length: ' . \strlen($body),
|
||||||
|
'X-Appwrite-Project: ' . $projectId
|
||||||
|
];
|
||||||
|
|
||||||
|
$ch = \curl_init();
|
||||||
|
\curl_setopt($ch, CURLOPT_URL, "http://localhost/v1/functions/{$functionId}/executions");
|
||||||
|
\curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
|
||||||
|
\curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
|
||||||
|
\curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||||
|
\curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
// \curl_setopt($ch, CURLOPT_HEADER, true);
|
||||||
|
\curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
|
||||||
|
|
||||||
|
$executionResponse = \utf8_decode(\curl_exec($ch));
|
||||||
|
$statusCode = \curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||||
|
$error = \curl_error($ch);
|
||||||
|
$errNo = \curl_errno($ch);
|
||||||
|
|
||||||
|
\curl_close($ch);
|
||||||
|
|
||||||
|
$responseBody = \json_decode($executionResponse, true)['response'];
|
||||||
|
|
||||||
|
return $response->setStatusCode(200)->send($responseBody);
|
||||||
|
} else if(\count($subdomains) === 3) {
|
||||||
|
// Deployment preview
|
||||||
|
$deploymentId = $subdomains[0];
|
||||||
|
$functionId = $subdomains[1];
|
||||||
|
$projectId = $subdomains[2];
|
||||||
|
|
||||||
|
if($projectId === 'console') {
|
||||||
|
throw new AppwriteException(AppwriteException::ROUTER_CONSOLE_PROJECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Implement
|
||||||
|
throw new AppwriteException(AppwriteException::GENERAL_SERVER_ERROR, 'Deployment preview not implemented yet.');
|
||||||
|
} else {
|
||||||
|
throw new AppwriteException(AppwriteException::ROUTER_INVALID_URL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Custom domains
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Request format
|
* Request format
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -229,6 +229,9 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) {
|
||||||
});
|
});
|
||||||
|
|
||||||
$http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swooleResponse) use ($register) {
|
$http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swooleResponse) use ($register) {
|
||||||
|
App::setResource('swooleRequest', fn() => $swooleRequest);
|
||||||
|
App::setResource('swooleResponse', fn() => $swooleResponse);
|
||||||
|
|
||||||
$request = new Request($swooleRequest);
|
$request = new Request($swooleRequest);
|
||||||
$response = new Response($swooleResponse);
|
$response = new Response($swooleResponse);
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,7 @@ services:
|
||||||
- _APP_OPENSSL_KEY_V1
|
- _APP_OPENSSL_KEY_V1
|
||||||
- _APP_DOMAIN
|
- _APP_DOMAIN
|
||||||
- _APP_DOMAIN_TARGET
|
- _APP_DOMAIN_TARGET
|
||||||
|
- _APP_DOMAIN_FUNCTIONS
|
||||||
- _APP_DB_HOST
|
- _APP_DB_HOST
|
||||||
- _APP_DB_PORT
|
- _APP_DB_PORT
|
||||||
- _APP_DB_SCHEMA
|
- _APP_DB_SCHEMA
|
||||||
|
@ -345,6 +346,7 @@ services:
|
||||||
- _APP_OPENSSL_KEY_V1
|
- _APP_OPENSSL_KEY_V1
|
||||||
- _APP_DOMAIN
|
- _APP_DOMAIN
|
||||||
- _APP_DOMAIN_TARGET
|
- _APP_DOMAIN_TARGET
|
||||||
|
- _APP_DOMAIN_FUNCTIONS
|
||||||
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
|
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
|
||||||
- _APP_DB_HOST
|
- _APP_DB_HOST
|
||||||
- _APP_DB_PORT
|
- _APP_DB_PORT
|
||||||
|
@ -449,6 +451,7 @@ services:
|
||||||
- _APP_OPENSSL_KEY_V1
|
- _APP_OPENSSL_KEY_V1
|
||||||
- _APP_DOMAIN
|
- _APP_DOMAIN
|
||||||
- _APP_DOMAIN_TARGET
|
- _APP_DOMAIN_TARGET
|
||||||
|
- _APP_DOMAIN_FUNCTIONS
|
||||||
- _APP_DB_HOST
|
- _APP_DB_HOST
|
||||||
- _APP_DB_PORT
|
- _APP_DB_PORT
|
||||||
- _APP_DB_SCHEMA
|
- _APP_DB_SCHEMA
|
||||||
|
|
|
@ -114,6 +114,7 @@ services:
|
||||||
- _APP_OPENSSL_KEY_V1
|
- _APP_OPENSSL_KEY_V1
|
||||||
- _APP_DOMAIN
|
- _APP_DOMAIN
|
||||||
- _APP_DOMAIN_TARGET
|
- _APP_DOMAIN_TARGET
|
||||||
|
- _APP_DOMAIN_FUNCTIONS
|
||||||
- _APP_DB_HOST
|
- _APP_DB_HOST
|
||||||
- _APP_DB_PORT
|
- _APP_DB_PORT
|
||||||
- _APP_DB_SCHEMA
|
- _APP_DB_SCHEMA
|
||||||
|
@ -424,6 +425,7 @@ services:
|
||||||
- _APP_OPENSSL_KEY_V1
|
- _APP_OPENSSL_KEY_V1
|
||||||
- _APP_DOMAIN
|
- _APP_DOMAIN
|
||||||
- _APP_DOMAIN_TARGET
|
- _APP_DOMAIN_TARGET
|
||||||
|
- _APP_DOMAIN_FUNCTIONS
|
||||||
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
|
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
|
||||||
- _APP_DB_HOST
|
- _APP_DB_HOST
|
||||||
- _APP_DB_PORT
|
- _APP_DB_PORT
|
||||||
|
@ -562,6 +564,7 @@ services:
|
||||||
- _APP_POOL_CLIENTS
|
- _APP_POOL_CLIENTS
|
||||||
- _APP_DOMAIN
|
- _APP_DOMAIN
|
||||||
- _APP_DOMAIN_TARGET
|
- _APP_DOMAIN_TARGET
|
||||||
|
- _APP_DOMAIN_FUNCTIONS
|
||||||
- _APP_OPENSSL_KEY_V1
|
- _APP_OPENSSL_KEY_V1
|
||||||
- _APP_DB_HOST
|
- _APP_DB_HOST
|
||||||
- _APP_DB_PORT
|
- _APP_DB_PORT
|
||||||
|
|
|
@ -163,6 +163,10 @@ class Exception extends \Exception
|
||||||
/** Webhooks */
|
/** Webhooks */
|
||||||
public const WEBHOOK_NOT_FOUND = 'webhook_not_found';
|
public const WEBHOOK_NOT_FOUND = 'webhook_not_found';
|
||||||
|
|
||||||
|
/** Router */
|
||||||
|
public const ROUTER_INVALID_URL = 'router_invalid_url';
|
||||||
|
public const ROUTER_CONSOLE_PROJECT = 'router_console_project';
|
||||||
|
|
||||||
/** Keys */
|
/** Keys */
|
||||||
public const KEY_NOT_FOUND = 'key_not_found';
|
public const KEY_NOT_FOUND = 'key_not_found';
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,7 @@ services:
|
||||||
- _APP_OPTIONS_FORCE_HTTPS
|
- _APP_OPTIONS_FORCE_HTTPS
|
||||||
- _APP_OPENSSL_KEY_V1
|
- _APP_OPENSSL_KEY_V1
|
||||||
- _APP_DOMAIN
|
- _APP_DOMAIN
|
||||||
|
- _APP_DOMAIN_FUNCTIONS
|
||||||
- _APP_DOMAIN_TARGET
|
- _APP_DOMAIN_TARGET
|
||||||
- _APP_REDIS_HOST
|
- _APP_REDIS_HOST
|
||||||
- _APP_REDIS_PORT
|
- _APP_REDIS_PORT
|
||||||
|
|
Loading…
Reference in a new issue