1
0
Fork 0
mirror of synced 2024-06-14 08:44:49 +12:00

Basic implementation for Open Runtimes V2

This commit is contained in:
Matej Bačo 2023-02-09 15:27:11 +01:00
parent 543246c50b
commit eea635fe4b
10 changed files with 115 additions and 1 deletions

1
.env
View file

@ -14,6 +14,7 @@ _APP_OPTIONS_ABUSE=disabled
_APP_OPTIONS_FORCE_HTTPS=disabled
_APP_OPENSSL_KEY_V1=your-secret-key
_APP_DOMAIN=demo.appwrite.io
_APP_DOMAIN_FUNCTIONS=functions.localhost
_APP_DOMAIN_TARGET=demo.appwrite.io
_APP_REDIS_HOST=redis
_APP_REDIS_PORT=6379

View file

@ -191,6 +191,7 @@ ENV _APP_SERVER=swoole \
_APP_LOCALE=en \
_APP_DOMAIN=localhost \
_APP_DOMAIN_TARGET=localhost \
_APP_DOMAIN_FUNCTIONS=disabled \
_APP_HOME=https://appwrite.io \
_APP_EDITION=community \
_APP_CONSOLE_WHITELIST_ROOT=enabled \

View file

@ -514,6 +514,16 @@ return [
'description' => 'The project key has expired. Please generate a new key using the Appwrite console.',
'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 => [
'name' => Exception::WEBHOOK_NOT_FOUND,
'description' => 'Webhook with the requested ID could not be found.',

View file

@ -61,6 +61,15 @@ return [
'question' => 'Enter your Appwrite hostname',
'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',
'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\'.',

View file

@ -8,6 +8,10 @@ use Utopia\Locale\Locale;
use Utopia\Logger\Logger;
use Utopia\Logger\Log;
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\Response;
use Appwrite\Utopia\View;
@ -42,6 +46,8 @@ Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE);
App::init()
->inject('utopia')
->inject('swooleRequest')
->inject('swooleResponse')
->inject('request')
->inject('response')
->inject('console')
@ -51,7 +57,80 @@ App::init()
->inject('locale')
->inject('clients')
->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
*/

View file

@ -229,6 +229,9 @@ $http->on('start', function (Server $http) use ($payloadSize, $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);
$response = new Response($swooleResponse);

View file

@ -98,6 +98,7 @@ services:
- _APP_OPENSSL_KEY_V1
- _APP_DOMAIN
- _APP_DOMAIN_TARGET
- _APP_DOMAIN_FUNCTIONS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@ -345,6 +346,7 @@ services:
- _APP_OPENSSL_KEY_V1
- _APP_DOMAIN
- _APP_DOMAIN_TARGET
- _APP_DOMAIN_FUNCTIONS
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
- _APP_DB_HOST
- _APP_DB_PORT
@ -449,6 +451,7 @@ services:
- _APP_OPENSSL_KEY_V1
- _APP_DOMAIN
- _APP_DOMAIN_TARGET
- _APP_DOMAIN_FUNCTIONS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA

View file

@ -114,6 +114,7 @@ services:
- _APP_OPENSSL_KEY_V1
- _APP_DOMAIN
- _APP_DOMAIN_TARGET
- _APP_DOMAIN_FUNCTIONS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@ -424,6 +425,7 @@ services:
- _APP_OPENSSL_KEY_V1
- _APP_DOMAIN
- _APP_DOMAIN_TARGET
- _APP_DOMAIN_FUNCTIONS
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
- _APP_DB_HOST
- _APP_DB_PORT
@ -562,6 +564,7 @@ services:
- _APP_POOL_CLIENTS
- _APP_DOMAIN
- _APP_DOMAIN_TARGET
- _APP_DOMAIN_FUNCTIONS
- _APP_OPENSSL_KEY_V1
- _APP_DB_HOST
- _APP_DB_PORT

View file

@ -163,6 +163,10 @@ class Exception extends \Exception
/** Webhooks */
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 */
public const KEY_NOT_FOUND = 'key_not_found';

View file

@ -70,6 +70,7 @@ services:
- _APP_OPTIONS_FORCE_HTTPS
- _APP_OPENSSL_KEY_V1
- _APP_DOMAIN
- _APP_DOMAIN_FUNCTIONS
- _APP_DOMAIN_TARGET
- _APP_REDIS_HOST
- _APP_REDIS_PORT