Update dynamic response method
This commit is contained in:
parent
22853b7b59
commit
dcf1684c8c
4 changed files with 79 additions and 58 deletions
|
@ -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
30
composer.lock
generated
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue