1
0
Fork 0
mirror of synced 2024-09-28 15:31:43 +12:00

Update dynamic response method

This commit is contained in:
Khushboo Verma 2024-08-07 18:45:53 +05:30
parent 22853b7b59
commit dcf1684c8c
4 changed files with 79 additions and 58 deletions

View file

@ -18,7 +18,6 @@ use Appwrite\Utopia\Database\Validator\CustomId;
use Appwrite\Utopia\Database\Validator\Queries\Deployments;
use Appwrite\Utopia\Database\Validator\Queries\Executions;
use Appwrite\Utopia\Database\Validator\Queries\Functions;
use Appwrite\Utopia\Fetch\BodyMultipart;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Model\Rule;
use Executor\Executor;
@ -1641,20 +1640,6 @@ App::post('/v1/functions/:functionId/executions')
}
}
$datetimeParams = ['scheduledAt'];
foreach ($datetimeParams as $datetimeParam) {
if (!empty($$datetimeParam)) {
$$datetimeParam = new DateTime($$datetimeParam);
}
}
$validator = new DatetimeValidator(requireDateInFuture: true);
foreach ($datetimeParams as $datetimeParam) {
if (!empty($$datetimeParam) && !$validator->isValid($$datetimeParam)) {
throw new Exception($validator->getDescription(), 400);
}
}
// 'headers' validator
$validator = new Headers();
if (!$validator->isValid($headers)) {
@ -1967,9 +1952,9 @@ App::post('/v1/functions/:functionId/executions')
$execution->setAttribute('responseBody', $executionResponse['body'] ?? '');
$execution->setAttribute('responseHeaders', $headers);
$acceptTypes = \explode(', ', $request->getHeader('accept', 'application/json'));
$isJson = false;
$acceptTypes = \explode(', ', $request->getHeader('accept', 'application/json'));
foreach ($acceptTypes as $acceptType) {
if (\str_starts_with($acceptType, 'application/json') || \str_starts_with($acceptType, 'application/*')) {
$isJson = true;
@ -1977,28 +1962,10 @@ App::post('/v1/functions/:functionId/executions')
}
}
if ($isJson) {
$executionString = \json_encode($execution, JSON_UNESCAPED_UNICODE);
if (!$executionString) {
throw new Exception('Execution resulted in binary response, but JSON response does not allow binaries. Use "Accept: multipart/form-data" header to support binaries.', 400);
}
$response
->setStatusCode(Response::STATUS_CODE_OK)
->addHeader('content-type', 'application/json')
->send($executionString);
} else {
// Multipart form data response
$multipart = new BodyMultipart();
foreach ($execution as $key => $value) {
$multipart->setPart($key, $value);
}
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
->addHeader('content-type', $multipart->exportHeader())
->send($multipart->exportBody());
}
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
->setContentType($isJson ? Response::CONTENT_TYPE_JSON : Response::CONTENT_TYPE_MULTIPART)
->dynamic($execution, Response::MODEL_EXECUTION);
});
App::get('/v1/functions/:functionId/executions')

30
composer.lock generated
View file

@ -2990,16 +2990,16 @@
"packages-dev": [
{
"name": "appwrite/sdk-generator",
"version": "0.39.4",
"version": "0.39.5",
"source": {
"type": "git",
"url": "https://github.com/appwrite/sdk-generator.git",
"reference": "501b92d73ae55e0f880ed00f57bc64a54d0ce137"
"reference": "40d0f66f2f85be74049ad710b46203aa151f53fd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/501b92d73ae55e0f880ed00f57bc64a54d0ce137",
"reference": "501b92d73ae55e0f880ed00f57bc64a54d0ce137",
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/40d0f66f2f85be74049ad710b46203aa151f53fd",
"reference": "40d0f66f2f85be74049ad710b46203aa151f53fd",
"shasum": ""
},
"require": {
@ -3035,9 +3035,9 @@
"description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms",
"support": {
"issues": "https://github.com/appwrite/sdk-generator/issues",
"source": "https://github.com/appwrite/sdk-generator/tree/0.39.4"
"source": "https://github.com/appwrite/sdk-generator/tree/0.39.5"
},
"time": "2024-07-26T22:34:10+00:00"
"time": "2024-08-06T00:51:40+00:00"
},
{
"name": "doctrine/deprecations",
@ -3158,16 +3158,16 @@
},
{
"name": "laravel/pint",
"version": "v1.17.1",
"version": "v1.17.2",
"source": {
"type": "git",
"url": "https://github.com/laravel/pint.git",
"reference": "b5b6f716db298671c1dfea5b1082ec2c0ae7064f"
"reference": "e8a88130a25e3f9d4d5785e6a1afca98268ab110"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/pint/zipball/b5b6f716db298671c1dfea5b1082ec2c0ae7064f",
"reference": "b5b6f716db298671c1dfea5b1082ec2c0ae7064f",
"url": "https://api.github.com/repos/laravel/pint/zipball/e8a88130a25e3f9d4d5785e6a1afca98268ab110",
"reference": "e8a88130a25e3f9d4d5785e6a1afca98268ab110",
"shasum": ""
},
"require": {
@ -3178,13 +3178,13 @@
"php": "^8.1.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.59.3",
"illuminate/view": "^10.48.12",
"larastan/larastan": "^2.9.7",
"friendsofphp/php-cs-fixer": "^3.61.1",
"illuminate/view": "^10.48.18",
"larastan/larastan": "^2.9.8",
"laravel-zero/framework": "^10.4.0",
"mockery/mockery": "^1.6.12",
"nunomaduro/termwind": "^1.15.1",
"pestphp/pest": "^2.34.8"
"pestphp/pest": "^2.35.0"
},
"bin": [
"builds/pint"
@ -3220,7 +3220,7 @@
"issues": "https://github.com/laravel/pint/issues",
"source": "https://github.com/laravel/pint"
},
"time": "2024-08-01T09:06:33+00:00"
"time": "2024-08-06T15:11:54+00:00"
},
{
"name": "matthiasmullie/minify",

View file

@ -2,6 +2,7 @@
namespace Appwrite\Utopia;
use Appwrite\Utopia\Fetch\BodyMultipart;
use Appwrite\Utopia\Response\Filter;
use Appwrite\Utopia\Response\Model;
use Appwrite\Utopia\Response\Model\Account;
@ -107,6 +108,7 @@ use Appwrite\Utopia\Response\Model\Variable;
use Appwrite\Utopia\Response\Model\VcsContent;
use Appwrite\Utopia\Response\Model\Webhook;
use Exception;
use JsonException;
use Swoole\Http\Response as SwooleHTTPResponse;
// Keep last
use Utopia\Database\Document;
@ -486,6 +488,7 @@ class Response extends SwooleResponse
*/
public const CONTENT_TYPE_YAML = 'application/x-yaml';
public const CONTENT_TYPE_NULL = 'null';
public const CONTENT_TYPE_MULTIPART = 'multipart/form-data';
/**
* List of defined output objects
@ -556,7 +559,11 @@ class Response extends SwooleResponse
switch ($this->getContentType()) {
case self::CONTENT_TYPE_JSON:
$this->json(!empty($output) ? $output : new \stdClass());
try {
$this->json(!empty($output) ? $output : new \stdClass());
} catch (JsonException $e) {
throw new Exception('Failed to parse binary response: ' . $e->getMessage(), 400);
}
break;
case self::CONTENT_TYPE_YAML:
@ -566,6 +573,10 @@ class Response extends SwooleResponse
case self::CONTENT_TYPE_NULL:
break;
case self::CONTENT_TYPE_MULTIPART:
$this->multipart(!empty($output) ? $output : new \stdClass());
break;
default:
if ($model === self::MODEL_NONE) {
$this->noContent();
@ -697,6 +708,49 @@ class Response extends SwooleResponse
->send(\yaml_emit($data, YAML_UTF8_ENCODING));
}
/**
* Multipart
*
* This helper is for sending multipart/form-data HTTP response.
* It sets relevant content type header ('multipart/form-data') and convert a PHP array ($data) to valid Multipart using BodyMultipart
*
* @param array $data
*
* @return void
*/
public function multipart(array $data): void
{
$multipart = new BodyMultipart();
foreach ($data as $key => $value) {
$multipart->setPart($key, $value);
}
$this
->send($multipart->exportBody());
}
/**
* JSON
*
* This helper is for sending JSON HTTP response.
* It sets relevant content type header ('application/json') and convert a PHP array ($data) to valid JSON using native json_encode
*
* @see http://en.wikipedia.org/wiki/JSON
*
* @param mixed $data
* @return void
*/
public function json($data): void
{
if (!is_array($data) && !$data instanceof \stdClass) {
throw new \Exception('Invalid JSON input var');
}
$this
->setContentType(Response::CONTENT_TYPE_JSON, self::CHARSET_UTF8)
->send(\json_encode($data, JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR));
}
/**
* @return array
*/

View file

@ -1403,8 +1403,8 @@ class FunctionsCustomServerTest extends Scope
'body' => null,
]);
$this->assertEquals(500, $execution['headers']['status-code']);
$this->assertStringContainsString('Execution resulted in binary response, but JSON response does not allow binaries.', $execution['body']['type']);
$this->assertEquals(400, $execution['headers']['status-code']);
$this->assertStringContainsString('Failed to parse binary response', $execution['body']['message']);
// Cleanup : Delete function
$response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [
@ -1499,9 +1499,9 @@ class FunctionsCustomServerTest extends Scope
$executionBody = json_decode($execution['body'], true);
$this->assertEquals(200, $execution['headers']['status-code']);
$this->assertEquals(201, $execution['headers']['status-code']);
$this->assertEquals(\md5($bytes), $executionBody['responseBody']);
$this->assertEquals($execution['headers']['content-type'], 'application/json');
$this->assertStringStartsWith('application/json', $execution['headers']['content-type']);
/**
* Test for FAILURE