Refactor the Status enum to remove HTTP_ prefix as it's redundant.

This commit is contained in:
abdulmohsen
2024-08-08 17:27:24 +03:00
parent be48c6ca1f
commit 78fefb8691
65 changed files with 408 additions and 434 deletions

View File

@@ -74,7 +74,7 @@ try {
);
if (!headers_sent()) {
http_response_code(Status::HTTP_SERVICE_UNAVAILABLE->value);
http_response_code(Status::SERVICE_UNAVAILABLE->value);
}
exit(Command::FAILURE);
@@ -98,7 +98,7 @@ try {
);
if (!headers_sent()) {
http_response_code(Status::HTTP_SERVICE_UNAVAILABLE->value);
http_response_code(Status::SERVICE_UNAVAILABLE->value);
}
exit(Command::FAILURE);

View File

@@ -26,17 +26,17 @@ final class AccessToken
public function __invoke(iRequest $request, array $args = []): iResponse
{
if (null === ($name = ag($args, 'name'))) {
return api_error('Invalid value for name path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for name path parameter.', Status::BAD_REQUEST);
}
if (null === $this->getBackend(name: $name)) {
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::HTTP_NOT_FOUND);
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::NOT_FOUND);
}
$data = DataUtil::fromArray($request->getParsedBody());
if (null === ($id = $data->get('id'))) {
return api_error('No id was given.', Status::HTTP_BAD_REQUEST);
return api_error('No id was given.', Status::BAD_REQUEST);
}
try {
@@ -47,7 +47,7 @@ final class AccessToken
);
if (!is_string($token)) {
return api_error('Failed to generate access token.', Status::HTTP_INTERNAL_SERVER_ERROR);
return api_error('Failed to generate access token.', Status::INTERNAL_SERVER_ERROR);
}
$arr = [
@@ -58,11 +58,11 @@ final class AccessToken
$arr['username'] = $data->get('username');
}
return api_response(Status::HTTP_OK, $arr);
return api_response(Status::OK, $arr);
} catch (InvalidArgumentException $e) {
return api_error($e->getMessage(), Status::HTTP_NOT_FOUND);
return api_error($e->getMessage(), Status::NOT_FOUND);
} catch (Throwable $e) {
return api_error($e->getMessage(), Status::HTTP_INTERNAL_SERVER_ERROR);
return api_error($e->getMessage(), Status::INTERNAL_SERVER_ERROR);
}
}
}

View File

@@ -24,11 +24,11 @@ final class Delete
public function __invoke(iRequest $request, array $args = []): iResponse
{
if (null === ($name = ag($args, 'name'))) {
return api_error('Invalid value for name path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for name path parameter.', Status::BAD_REQUEST);
}
if (null === ($data = $this->getBackend(name: $name))) {
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::HTTP_NOT_FOUND);
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::NOT_FOUND);
}
set_time_limit(0);
@@ -59,7 +59,7 @@ final class Delete
ConfigFile::open(Config::get('backends_file'), 'yaml')->delete($name)->persist();
return api_response(Status::HTTP_OK, [
return api_response(Status::OK, [
'deleted' => [
'references' => $removedReference,
'records' => $deletedRecords,

View File

@@ -26,28 +26,28 @@ final class Discover
public function __invoke(iRequest $request, array $args = []): iResponse
{
if (null === ($name = ag($args, 'name'))) {
return api_error('Invalid value for name path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for name path parameter.', Status::BAD_REQUEST);
}
if (null === $this->getBackend(name: $name)) {
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::HTTP_NOT_FOUND);
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::NOT_FOUND);
}
try {
$client = $this->getClient(name: $name);
if (PlexClient::CLIENT_NAME !== $client->getType()) {
return api_error('Discover is only available for Plex backends.', Status::HTTP_BAD_REQUEST);
return api_error('Discover is only available for Plex backends.', Status::BAD_REQUEST);
}
assert($client instanceof PlexClient);
$list = $client::discover($this->http, $client->getContext()->backendToken);
return api_response(Status::HTTP_OK, ag($list, 'list', []));
return api_response(Status::OK, ag($list, 'list', []));
} catch (InvalidArgumentException $e) {
return api_error($e->getMessage(), Status::HTTP_NOT_FOUND);
return api_error($e->getMessage(), Status::NOT_FOUND);
} catch (Throwable $e) {
return api_error($e->getMessage(), Status::HTTP_INTERNAL_SERVER_ERROR);
return api_error($e->getMessage(), Status::INTERNAL_SERVER_ERROR);
}
}
}

View File

@@ -31,11 +31,11 @@ final class Ignore
public function ignoredIds(iRequest $request, array $args = []): iResponse
{
if (null === ($name = ag($args, 'name'))) {
return api_error('Invalid value for name path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for name path parameter.', Status::BAD_REQUEST);
}
if (null === $this->getBackend(name: $name)) {
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::HTTP_NOT_FOUND);
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::NOT_FOUND);
}
$list = [];
@@ -66,62 +66,62 @@ final class Ignore
];
}
return api_response(Status::HTTP_OK, $list);
return api_response(Status::OK, $list);
}
#[Delete(Index::URL . '/{name:backend}/ignore[/]', name: 'backend.ignoredIds.delete')]
public function deleteRule(iRequest $request, array $args = []): iResponse
{
if (null === ($name = ag($args, 'name'))) {
return api_error('Invalid value for name path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for name path parameter.', Status::BAD_REQUEST);
}
if (null === $this->getBackend(name: $name)) {
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::HTTP_NOT_FOUND);
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::NOT_FOUND);
}
$data = $this->getBackends(name: $name);
if (empty($data)) {
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::HTTP_NOT_FOUND);
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::NOT_FOUND);
}
$params = DataUtil::fromRequest($request);
if (null === ($rule = $params->get('rule'))) {
return api_error('No rule was given.', Status::HTTP_BAD_REQUEST);
return api_error('No rule was given.', Status::BAD_REQUEST);
}
try {
checkIgnoreRule($rule);
} catch (Throwable $e) {
return api_error($e->getMessage(), Status::HTTP_BAD_REQUEST);
return api_error($e->getMessage(), Status::BAD_REQUEST);
}
if (!$this->file->has($rule)) {
return api_error('Rule not found.', Status::HTTP_NOT_FOUND);
return api_error('Rule not found.', Status::NOT_FOUND);
}
$this->file->delete($rule)->persist();
return api_response(Status::HTTP_OK);
return api_response(Status::OK);
}
#[Post(Index::URL . '/{name:backend}/ignore[/]', name: 'backend.ignoredIds.add')]
public function addRule(iRequest $request, array $args = []): iResponse
{
if (null === ($name = ag($args, 'name'))) {
return api_error('Invalid value for name path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for name path parameter.', Status::BAD_REQUEST);
}
if (null === $this->getBackend(name: $name)) {
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::HTTP_NOT_FOUND);
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::NOT_FOUND);
}
$data = $this->getBackends(name: $name);
if (empty($data)) {
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::HTTP_NOT_FOUND);
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::NOT_FOUND);
}
$params = DataUtil::fromRequest($request);
@@ -136,7 +136,7 @@ final class Ignore
foreach ($partial as $k => $v) {
if (empty($v)) {
return api_error(r('No {key} was given.', ['key' => $k]), Status::HTTP_BAD_REQUEST);
return api_error(r('No {key} was given.', ['key' => $k]), Status::BAD_REQUEST);
}
}
@@ -153,18 +153,18 @@ final class Ignore
checkIgnoreRule($rule);
$id = makeIgnoreId($rule);
} catch (Throwable $e) {
return api_error($e->getMessage(), Status::HTTP_BAD_REQUEST);
return api_error($e->getMessage(), Status::BAD_REQUEST);
}
if (true === $this->file->has((string)$id)) {
return api_error('Rule already exists.', Status::HTTP_CONFLICT);
return api_error('Rule already exists.', Status::CONFLICT);
}
if (true === $this->file->has((string)$id->withQuery(''))) {
return api_error('Global rule already exists.', Status::HTTP_CONFLICT);
return api_error('Global rule already exists.', Status::CONFLICT);
}
$this->file->set((string)$id, time())->persist();
return api_response(Status::HTTP_CREATED);
return api_response(Status::CREATED);
}
}

View File

@@ -20,13 +20,13 @@ final class Index
public function __invoke(iRequest $request, array $args = []): iResponse
{
if (null === ($name = ag($args, 'name'))) {
return api_error('Invalid value for name path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for name path parameter.', Status::BAD_REQUEST);
}
if (null === ($data = $this->getBackend(name: $name))) {
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::HTTP_NOT_FOUND);
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::NOT_FOUND);
}
return api_response(Status::HTTP_OK, $data);
return api_response(Status::OK, $data);
}
}

View File

@@ -22,17 +22,17 @@ final class Info
public function __invoke(iRequest $request, array $args = []): iResponse
{
if (null === ($name = ag($args, 'name'))) {
return api_error('Invalid value for name path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for name path parameter.', Status::BAD_REQUEST);
}
if (null === $this->getBackend(name: $name)) {
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::HTTP_NOT_FOUND);
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::NOT_FOUND);
}
try {
$client = $this->getClient(name: $name);
} catch (InvalidArgumentException $e) {
return api_error($e->getMessage(), Status::HTTP_NOT_FOUND);
return api_error($e->getMessage(), Status::NOT_FOUND);
}
$opts = [];
@@ -44,9 +44,9 @@ final class Info
try {
$data = $client->getInfo($opts);
return api_response(Status::HTTP_OK, $data);
return api_response(Status::OK, $data);
} catch (Throwable $e) {
return api_error($e->getMessage(), Status::HTTP_INTERNAL_SERVER_ERROR);
return api_error($e->getMessage(), Status::INTERNAL_SERVER_ERROR);
}
}
}

View File

@@ -25,20 +25,20 @@ final class Library
public function listLibraries(iRequest $request, array $args = []): iResponse
{
if (null === ($name = ag($args, 'name'))) {
return api_error('Invalid value for name path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for name path parameter.', Status::BAD_REQUEST);
}
if (null === $this->getBackend(name: $name)) {
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::HTTP_NOT_FOUND);
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::NOT_FOUND);
}
try {
$client = $this->getClient(name: $name);
return api_response(Status::HTTP_OK, $client->listLibraries());
return api_response(Status::OK, $client->listLibraries());
} catch (RuntimeException $e) {
return api_error($e->getMessage(), Status::HTTP_NOT_FOUND);
return api_error($e->getMessage(), Status::NOT_FOUND);
} catch (Throwable $e) {
return api_error($e->getMessage(), Status::HTTP_INTERNAL_SERVER_ERROR);
return api_error($e->getMessage(), Status::INTERNAL_SERVER_ERROR);
}
}
@@ -46,15 +46,15 @@ final class Library
public function ignoreLibrary(iRequest $request, array $args = []): iResponse
{
if (null === ($name = ag($args, 'name'))) {
return api_error('Invalid value for name path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for name path parameter.', Status::BAD_REQUEST);
}
if (null === $this->getBackend(name: $name)) {
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::HTTP_NOT_FOUND);
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::NOT_FOUND);
}
if (null === ($id = ag($args, 'id'))) {
return api_error('Invalid value for id path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for id path parameter.', Status::BAD_REQUEST);
}
$remove = 'DELETE' === $request->getMethod();
@@ -62,7 +62,7 @@ final class Library
$config = ConfigFile::open(Config::get('backends_file'), 'yaml');
if (null === $config->get($name)) {
return api_error(r("Backend '{backend}' not found.", ['backend' => $name]), Status::HTTP_NOT_FOUND);
return api_error(r("Backend '{backend}' not found.", ['backend' => $name]), Status::NOT_FOUND);
}
$ignoreIds = array_map(
@@ -75,7 +75,7 @@ final class Library
return api_error(r("Library id '{id}' is {message} ignored.", [
'id' => $id,
'message' => $remove ? "not" : 'already',
]), Status::HTTP_CONFLICT);
]), Status::CONFLICT);
}
$found = false;
@@ -92,7 +92,7 @@ final class Library
}
if (false === $found) {
return api_error(r("The library id '{id}' is incorrect.", ['id' => $name]), Status::HTTP_NOT_FOUND, [
return api_error(r("The library id '{id}' is incorrect.", ['id' => $name]), Status::NOT_FOUND, [
'possible_ids' => array_column($libraries, 'id'),
]);
}
@@ -103,6 +103,6 @@ final class Library
$config->set("{$name}.options." . Options::IGNORE, implode(',', array_values($ignoreIds)))->persist();
return api_response(Status::HTTP_OK, $libraries);
return api_response(Status::OK, $libraries);
}
}

View File

@@ -54,11 +54,11 @@ final class Mismatched
public function __invoke(iRequest $request, array $args = []): iResponse
{
if (null === ($name = ag($args, 'name'))) {
return api_error('Invalid value for name path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for name path parameter.', Status::BAD_REQUEST);
}
if (null === $this->getBackend(name: $name)) {
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::HTTP_NOT_FOUND);
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::NOT_FOUND);
}
$params = DataUtil::fromArray($request->getQueryParams());
@@ -84,13 +84,13 @@ final class Mismatched
'method' => $method,
'methods' => implode(", ", self::METHODS),
]), Status::HTTP_BAD_REQUEST);
]), Status::BAD_REQUEST);
}
try {
$client = $this->getClient(name: $name, config: $backendOpts);
} catch (RuntimeException $e) {
return api_error($e->getMessage(), Status::HTTP_NOT_FOUND);
return api_error($e->getMessage(), Status::NOT_FOUND);
}
$ids = [];
@@ -121,7 +121,7 @@ final class Mismatched
}
}
return api_response(Status::HTTP_OK, $list);
return api_response(Status::OK, $list);
}
protected function compare(iClient $client, array $item, string $method): array

View File

@@ -22,19 +22,19 @@ final class Option
public function __invoke(iRequest $request, array $args = []): iResponse
{
if (null === ($name = ag($args, 'name'))) {
return api_error('Invalid value for name path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for name path parameter.', Status::BAD_REQUEST);
}
$list = ConfigFile::open(Config::get('backends_file'), 'yaml', autoCreate: true);
if (false === $list->has($name)) {
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::HTTP_NOT_FOUND);
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::NOT_FOUND);
}
$data = DataUtil::fromRequest($request);
if (null === ($option = ag($args, 'option', $data->get('key')))) {
return api_error('No option key was given.', Status::HTTP_BAD_REQUEST);
return api_error('No option key was given.', Status::BAD_REQUEST);
}
$isInternalRequest = true === (bool)$request->getAttribute('INTERNAL_REQUEST', false);
@@ -42,13 +42,13 @@ final class Option
if (false === str_starts_with($option, 'options.') && !$isInternalRequest) {
return api_error(
"Invalid option key was given. Option keys must start with 'options.'",
Status::HTTP_BAD_REQUEST
Status::BAD_REQUEST
);
}
$spec = getServerColumnSpec($option);
if (empty($spec)) {
return api_error(r("Invalid option '{key}'.", ['key' => $option]), Status::HTTP_BAD_REQUEST);
return api_error(r("Invalid option '{key}'.", ['key' => $option]), Status::BAD_REQUEST);
}
if ('GET' === $request->getMethod()) {
@@ -56,7 +56,7 @@ final class Option
return api_error(r("Option '{option}' not found in backend '{name}' config.", [
'option' => $option,
'name' => $name
]), Status::HTTP_NOT_FOUND);
]), Status::NOT_FOUND);
}
return $this->viewOption($spec, $list->get("{$name}.{$option}"));
@@ -66,7 +66,7 @@ final class Option
return api_error(r("Option '{option}' not found in backend '{name}' config.", [
'option' => $option,
'name' => $name
]), Status::HTTP_NOT_FOUND);
]), Status::NOT_FOUND);
}
if ('DELETE' === $request->getMethod()) {
@@ -90,7 +90,7 @@ final class Option
return api_error(r("Value validation for '{key}' failed. {error}", [
'key' => $option,
'error' => $e->getMessage()
]), Status::HTTP_BAD_REQUEST);
]), Status::BAD_REQUEST);
}
}
@@ -99,7 +99,7 @@ final class Option
$list->persist();
return api_response(Status::HTTP_OK, [
return api_response(Status::OK, [
'key' => $option,
'value' => $value,
'real_val' => $data->get('value'),
@@ -114,7 +114,7 @@ final class Option
settype($value, ag($spec, 'type', 'string'));
}
return api_response(Status::HTTP_OK, [
return api_response(Status::OK, [
'key' => $spec['key'],
'value' => $value,
'type' => ag($spec, 'type', 'string'),

View File

@@ -22,11 +22,11 @@ final class Search
public function __invoke(iRequest $request, array $args = []): iResponse
{
if (null === ($name = ag($args, 'name'))) {
return api_error('Invalid value for name path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for name path parameter.', Status::BAD_REQUEST);
}
if (null === $this->getBackend(name: $name)) {
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::HTTP_NOT_FOUND);
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::NOT_FOUND);
}
$params = DataUtil::fromRequest($request, true);
@@ -35,13 +35,13 @@ final class Search
$query = $params->get('q', null);
if (null === $id && null === $query) {
return api_error('No search id or query string was provided.', Status::HTTP_BAD_REQUEST);
return api_error('No search id or query string was provided.', Status::BAD_REQUEST);
}
try {
$backend = $this->getClient(name: $name);
} catch (RuntimeException $e) {
return api_error($e->getMessage(), Status::HTTP_NOT_FOUND);
return api_error($e->getMessage(), Status::NOT_FOUND);
}
$raw = $params->get('raw', false) || $params->get(Options::RAW_RESPONSE, false);
@@ -73,16 +73,16 @@ final class Search
}
}
} catch (Throwable $e) {
return api_error($e->getMessage(), Status::HTTP_INTERNAL_SERVER_ERROR);
return api_error($e->getMessage(), Status::INTERNAL_SERVER_ERROR);
}
if (count($data) < 1) {
return api_error(r("No results were found for '{query}'.", [
'query' => $id ?? $query
]), Status::HTTP_NOT_FOUND);
]), Status::NOT_FOUND);
}
return api_response(Status::HTTP_OK, $response);
return api_response(Status::OK, $response);
}
}

View File

@@ -22,17 +22,17 @@ final class Sessions
public function __invoke(iRequest $request, array $args = []): iResponse
{
if (null === ($name = ag($args, 'name'))) {
return api_error('Invalid value for name path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for name path parameter.', Status::BAD_REQUEST);
}
if (null === $this->getBackend(name: $name)) {
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::HTTP_NOT_FOUND);
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::NOT_FOUND);
}
try {
$client = $this->getClient(name: $name);
} catch (InvalidArgumentException $e) {
return api_error($e->getMessage(), Status::HTTP_NOT_FOUND);
return api_error($e->getMessage(), Status::NOT_FOUND);
}
$opts = [];
@@ -44,9 +44,9 @@ final class Sessions
try {
$sessions = $client->getSessions($opts);
return api_response(Status::HTTP_OK, ag($sessions, 'sessions', []));
return api_response(Status::OK, ag($sessions, 'sessions', []));
} catch (Throwable $e) {
return api_error($e->getMessage(), Status::HTTP_INTERNAL_SERVER_ERROR);
return api_error($e->getMessage(), Status::INTERNAL_SERVER_ERROR);
}
}
}

View File

@@ -24,11 +24,11 @@ final class Unmatched
public function __invoke(iRequest $request, array $args = []): iResponse
{
if (null === ($name = ag($args, 'name'))) {
return api_error('Invalid value for name path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for name path parameter.', Status::BAD_REQUEST);
}
if (null === $this->getBackend(name: $name)) {
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::HTTP_NOT_FOUND);
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::NOT_FOUND);
}
$params = DataUtil::fromArray($request->getQueryParams());
@@ -46,7 +46,7 @@ final class Unmatched
try {
$client = $this->getClient(name: $name, config: $backendOpts);
} catch (RuntimeException $e) {
return api_error($e->getMessage(), Status::HTTP_NOT_FOUND);
return api_error($e->getMessage(), Status::NOT_FOUND);
}
$ids = [];
@@ -97,6 +97,6 @@ final class Unmatched
}
}
return api_response(Status::HTTP_OK, $list);
return api_response(Status::OK, $list);
}
}

View File

@@ -48,11 +48,11 @@ final class Update
public function update(iRequest $request, array $args = []): iResponse
{
if (null === ($name = ag($args, 'name'))) {
return api_error('Invalid value for name path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for name path parameter.', Status::BAD_REQUEST);
}
if (false === $this->backendFile->has($name)) {
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::HTTP_NOT_FOUND);
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::NOT_FOUND);
}
try {
@@ -72,7 +72,7 @@ final class Update
);
if (false === $client->validateContext($context)) {
return api_error('Context information validation failed.', Status::HTTP_BAD_REQUEST);
return api_error('Context information validation failed.', Status::BAD_REQUEST);
}
$this->backendFile->set($name, $config->getAll());
@@ -89,14 +89,14 @@ final class Update
$backend = $this->getBackends(name: $name);
if (empty($backend)) {
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::HTTP_NOT_FOUND);
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::NOT_FOUND);
}
$backend = array_pop($backend);
return api_response(Status::HTTP_OK, $backend);
return api_response(Status::OK, $backend);
} catch (InvalidContextException|ValidationException $e) {
return api_error($e->getMessage(), Status::HTTP_BAD_REQUEST);
return api_error($e->getMessage(), Status::BAD_REQUEST);
}
}
@@ -104,18 +104,18 @@ final class Update
public function patchUpdate(iRequest $request, array $args = []): iResponse
{
if (null === ($name = ag($args, 'name'))) {
return api_error('Invalid value for name path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for name path parameter.', Status::BAD_REQUEST);
}
if (false === $this->backendFile->has($name)) {
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::HTTP_NOT_FOUND);
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::NOT_FOUND);
}
try {
$data = json_decode((string)$request->getBody(), true, flags: JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
return api_error(r('Invalid JSON data. {error}', ['error' => $e->getMessage()]),
Status::HTTP_BAD_REQUEST);
Status::BAD_REQUEST);
}
$updates = [];
@@ -124,13 +124,13 @@ final class Update
$value = ag($update, 'value');
if (null === ($key = ag($update, 'key'))) {
return api_error('No key to update was present.', Status::HTTP_BAD_REQUEST);
return api_error('No key to update was present.', Status::BAD_REQUEST);
}
$spec = getServerColumnSpec($key);
if (empty($spec)) {
return api_error(r("Invalid key '{key}' was given.", ['key' => $key]), Status::HTTP_BAD_REQUEST);
return api_error(r("Invalid key '{key}' was given.", ['key' => $key]), Status::BAD_REQUEST);
}
settype($value, ag($spec, 'type', 'string'));
@@ -142,12 +142,12 @@ final class Update
return api_error(r("Value validation for '{key}' failed. {error}", [
'key' => $key,
'error' => $e->getMessage()
]), Status::HTTP_BAD_REQUEST);
]), Status::BAD_REQUEST);
}
}
if (in_array($key, self::IMMUTABLE_KEYS, true)) {
return api_error(r('Key {key} is immutable.', ['key' => $key]), Status::HTTP_BAD_REQUEST);
return api_error(r('Key {key} is immutable.', ['key' => $key]), Status::BAD_REQUEST);
}
$updates["{$name}.{$key}"] = $value;
@@ -162,12 +162,12 @@ final class Update
$backend = $this->getBackends(name: $name);
if (empty($backend)) {
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::HTTP_NOT_FOUND);
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::NOT_FOUND);
}
$backend = array_pop($backend);
return api_response(Status::HTTP_OK, $backend);
return api_response(Status::OK, $backend);
}
private function fromRequest(array $config, iRequest $request, iClient $client): array

View File

@@ -22,11 +22,11 @@ final class Users
public function __invoke(iRequest $request, array $args = []): iResponse
{
if (null === ($name = ag($args, 'name'))) {
return api_error('Invalid value for id path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for id path parameter.', Status::BAD_REQUEST);
}
if (null === $this->getBackend(name: $name)) {
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::HTTP_NOT_FOUND);
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::NOT_FOUND);
}
$opts = [];
@@ -41,11 +41,11 @@ final class Users
}
try {
return api_response(Status::HTTP_OK, $this->getClient(name: $name)->getUsersList($opts));
return api_response(Status::OK, $this->getClient(name: $name)->getUsersList($opts));
} catch (InvalidArgumentException $e) {
return api_error($e->getMessage(), Status::HTTP_NOT_FOUND);
return api_error($e->getMessage(), Status::NOT_FOUND);
} catch (Throwable $e) {
return api_error($e->getMessage(), Status::HTTP_INTERNAL_SERVER_ERROR);
return api_error($e->getMessage(), Status::INTERNAL_SERVER_ERROR);
}
}
}

View File

@@ -20,19 +20,19 @@ final class Version
public function __invoke(iRequest $request, array $args = []): iResponse
{
if (null === ($name = ag($args, 'name'))) {
return api_error('Invalid value for id path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for id path parameter.', Status::BAD_REQUEST);
}
if (null === $this->getBackend(name: $name)) {
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::HTTP_NOT_FOUND);
return api_error(r("Backend '{name}' not found.", ['name' => $name]), Status::NOT_FOUND);
}
try {
return api_response(Status::HTTP_OK, ['version' => $this->getClient(name: $name)->getVersion()]);
return api_response(Status::OK, ['version' => $this->getClient(name: $name)->getVersion()]);
} catch (InvalidArgumentException $e) {
return api_error($e->getMessage(), Status::HTTP_NOT_FOUND);
return api_error($e->getMessage(), Status::NOT_FOUND);
} catch (Throwable $e) {
return api_error($e->getMessage(), Status::HTTP_INTERNAL_SERVER_ERROR);
return api_error($e->getMessage(), Status::INTERNAL_SERVER_ERROR);
}
}
}

View File

@@ -60,7 +60,7 @@ final class Webhooks
public function __invoke(iRequest $request, array $args = []): iResponse
{
if (null === ($name = ag($args, 'name'))) {
return api_error('Invalid value for id path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for id path parameter.', Status::BAD_REQUEST);
}
return $this->process($name, $request);
@@ -87,7 +87,7 @@ final class Webhooks
$client = $this->getClient(name: $name);
} catch (RuntimeException $e) {
return api_error($e->getMessage(), Status::HTTP_NOT_FOUND);
return api_error($e->getMessage(), Status::NOT_FOUND);
}
if (true === Config::get('webhook.dumpRequest')) {
@@ -101,7 +101,7 @@ final class Webhooks
if (null === ($requestUser = ag($attr, 'user.id'))) {
$message = "Request payload didn't contain a user id. Backend requires a user check.";
$this->write($request, Level::Info, $message);
return api_error($message, Status::HTTP_BAD_REQUEST);
return api_error($message, Status::BAD_REQUEST);
}
if (false === hash_equals((string)$userId, (string)$requestUser)) {
@@ -110,7 +110,7 @@ final class Webhooks
'config_user' => $userId,
]);
$this->write($request, Level::Info, $message);
return api_error($message, Status::HTTP_BAD_REQUEST);
return api_error($message, Status::BAD_REQUEST);
}
}
@@ -118,7 +118,7 @@ final class Webhooks
if (null === ($requestBackendId = ag($attr, 'backend.id'))) {
$message = "Request payload didn't contain the backend unique id.";
$this->write($request, Level::Info, $message);
return api_error($message, Status::HTTP_BAD_REQUEST);
return api_error($message, Status::BAD_REQUEST);
}
if (false === hash_equals((string)$uuid, (string)$requestBackendId)) {
@@ -127,7 +127,7 @@ final class Webhooks
'config_uid' => $uuid,
]);
$this->write($request, Level::Info, $message);
return api_error($message, Status::HTTP_BAD_REQUEST);
return api_error($message, Status::BAD_REQUEST);
}
}
@@ -140,7 +140,7 @@ final class Webhooks
$metadataOnly = true === (bool)ag($backend, 'options.' . Options::IMPORT_METADATA_ONLY);
if (true !== $metadataOnly && true !== (bool)ag($backend, 'import.enabled')) {
$response = api_response(Status::HTTP_NOT_ACCEPTABLE);
$response = api_response(Status::NOT_ACCEPTABLE);
$this->write($request, Level::Error, r('Import are disabled for [{backend}].', [
'backend' => $client->getName(),
]), forceContext: true);
@@ -168,7 +168,7 @@ final class Webhooks
]
);
return api_response(Status::HTTP_NOT_MODIFIED);
return api_response(Status::NOT_MODIFIED);
}
if ((0 === (int)$entity->episode || null === $entity->season) && $entity->isEpisode()) {
@@ -187,7 +187,7 @@ final class Webhooks
]
);
return api_response(Status::HTTP_NOT_MODIFIED);
return api_response(Status::NOT_MODIFIED);
}
$items = $this->cache->get('requests', []);
@@ -228,7 +228,7 @@ final class Webhooks
]
);
return api_response(Status::HTTP_OK);
return api_response(Status::OK);
}
/**

View File

@@ -23,7 +23,7 @@ final class AccessToken
public function __invoke(iRequest $request, array $args = []): iResponse
{
if (null === ($type = ag($args, 'type'))) {
return api_error('Invalid value for type path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for type path parameter.', Status::BAD_REQUEST);
}
$params = DataUtil::fromRequest($request);
@@ -31,25 +31,25 @@ final class AccessToken
$password = $params->get('password');
if (empty($username) || empty($password)) {
return api_error('Invalid username or password.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid username or password.', Status::BAD_REQUEST);
}
if (false === in_array($type, ['jellyfin', 'emby'])) {
return api_error('Access token endpoint only supported on jellyfin, emby.', Status::HTTP_BAD_REQUEST);
return api_error('Access token endpoint only supported on jellyfin, emby.', Status::BAD_REQUEST);
}
try {
$client = $this->getBasicClient($type, $params->with('token', 'accesstoken_request'));
} catch (InvalidArgumentException $e) {
return api_error($e->getMessage(), Status::HTTP_BAD_REQUEST);
return api_error($e->getMessage(), Status::BAD_REQUEST);
}
try {
$info = $client->generateAccessToken($username, $password);
} catch (Throwable $e) {
return api_error($e->getMessage(), Status::HTTP_INTERNAL_SERVER_ERROR);
return api_error($e->getMessage(), Status::INTERNAL_SERVER_ERROR);
}
return api_response(Status::HTTP_OK, $info);
return api_response(Status::OK, $info);
}
}

View File

@@ -34,23 +34,23 @@ final class Add
$requestData = $request->getParsedBody();
if (!is_array($requestData)) {
return api_error('Invalid request data.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid request data.', Status::BAD_REQUEST);
}
$data = DataUtil::fromArray($request->getParsedBody());
if (null === ($type = $data->get('type'))) {
return api_error('No type was given.', Status::HTTP_BAD_REQUEST);
return api_error('No type was given.', Status::BAD_REQUEST);
}
$type = strtolower($type);
if (null === ($name = $data->get('name'))) {
return api_error('No name was given.', Status::HTTP_BAD_REQUEST);
return api_error('No name was given.', Status::BAD_REQUEST);
}
if (false === isValidName($name)) {
return api_error('Invalid name was given.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid name was given.', Status::BAD_REQUEST);
}
$backend = $this->getBackends(name: $name);
@@ -58,24 +58,24 @@ final class Add
if (!empty($backend)) {
return api_error(r("Backend '{backend}' already exists.", [
'backend' => $name
]), Status::HTTP_CONFLICT);
]), Status::CONFLICT);
}
if (null === ($url = $data->get('url'))) {
return api_error('No url was given.', Status::HTTP_BAD_REQUEST);
return api_error('No url was given.', Status::BAD_REQUEST);
}
if (false === isValidUrl($url)) {
return api_error('Invalid url was given.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid url was given.', Status::BAD_REQUEST);
}
if (null === ($token = $data->get('token'))) {
return api_error('No access token was given.', Status::HTTP_BAD_REQUEST);
return api_error('No access token was given.', Status::BAD_REQUEST);
}
if (null === ($class = Config::get("supported.{$type}", null))) {
return api_error(r("Unexpected client type '{type}' was given.", ['type' => $type]),
Status::HTTP_BAD_REQUEST);
Status::BAD_REQUEST);
}
$instance = Container::getNew($class);
@@ -96,7 +96,7 @@ final class Add
);
if (false === $instance->validateContext($context)) {
return api_error('Context information validation failed.', Status::HTTP_BAD_REQUEST);
return api_error('Context information validation failed.', Status::BAD_REQUEST);
}
if (!$config->get('uuid')) {
@@ -111,13 +111,13 @@ final class Add
->set($name, $config->getAll())
->persist();
} catch (InvalidContextException $e) {
return api_error($e->getMessage(), Status::HTTP_BAD_REQUEST);
return api_error($e->getMessage(), Status::BAD_REQUEST);
}
$data = $this->getBackends(name: $name);
$data = array_pop($data);
return api_response(Status::HTTP_CREATED, $data);
return api_response(Status::CREATED, $data);
}
private function fromRequest(string $type, iRequest $request, iClient $client): array

View File

@@ -27,25 +27,25 @@ final class Discover
public function __invoke(iRequest $request, array $args = []): iResponse
{
if (null === ($type = ag($args, 'type'))) {
return api_error('Invalid value for type path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for type path parameter.', Status::BAD_REQUEST);
}
if ('plex' !== $type) {
return api_error('Discover only supported on plex.', Status::HTTP_BAD_REQUEST);
return api_error('Discover only supported on plex.', Status::BAD_REQUEST);
}
try {
$client = $this->getBasicClient($type, DataUtil::fromRequest($request, true));
assert($client instanceof PlexClient);
} catch (InvalidArgumentException $e) {
return api_error($e->getMessage(), Status::HTTP_BAD_REQUEST);
return api_error($e->getMessage(), Status::BAD_REQUEST);
}
try {
$list = $client::discover($this->http, $client->getContext()->backendToken);
return api_response(Status::HTTP_OK, ag($list, 'list', []));
return api_response(Status::OK, ag($list, 'list', []));
} catch (Throwable $e) {
return api_error($e->getMessage(), Status::HTTP_INTERNAL_SERVER_ERROR);
return api_error($e->getMessage(), Status::INTERNAL_SERVER_ERROR);
}
}
}

View File

@@ -44,6 +44,6 @@ final class Index
$list[] = $item;
}
return api_response(Status::HTTP_OK, $list);
return api_response(Status::OK, $list);
}
}

View File

@@ -35,6 +35,6 @@ final class Spec
$list[] = $item;
}
return api_response(Status::HTTP_OK, $list);
return api_response(Status::OK, $list);
}
}

View File

@@ -20,7 +20,7 @@ final class UUid
public function __invoke(iRequest $request, array $args = []): iResponse
{
if (null === ($type = ag($args, 'type'))) {
return api_error('Invalid value for type path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for type path parameter.', Status::BAD_REQUEST);
}
try {
@@ -28,14 +28,14 @@ final class UUid
$info = $client->getInfo();
return api_response(Status::HTTP_OK, [
return api_response(Status::OK, [
'type' => strtolower((string)ag($info, 'type')),
'identifier' => ag($info, 'identifier'),
]);
} catch (InvalidArgumentException $e) {
return api_error($e->getMessage(), Status::HTTP_BAD_REQUEST);
return api_error($e->getMessage(), Status::BAD_REQUEST);
} catch (\Throwable $e) {
return api_error($e->getMessage(), Status::HTTP_INTERNAL_SERVER_ERROR);
return api_error($e->getMessage(), Status::INTERNAL_SERVER_ERROR);
}
}
}

View File

@@ -21,7 +21,7 @@ final class Users
public function __invoke(iRequest $request, array $args = []): iResponse
{
if (null === ($type = ag($args, 'type'))) {
return api_error('Invalid value for type path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for type path parameter.', Status::BAD_REQUEST);
}
$params = DataUtil::fromRequest($request, true);
@@ -29,7 +29,7 @@ final class Users
try {
$client = $this->getBasicClient($type, $params);
} catch (InvalidArgumentException $e) {
return api_error($e->getMessage(), Status::HTTP_BAD_REQUEST);
return api_error($e->getMessage(), Status::BAD_REQUEST);
}
$users = $opts = [];
@@ -43,9 +43,9 @@ final class Users
$users[] = $user;
}
} catch (Throwable $e) {
return api_error($e->getMessage(), Status::HTTP_INTERNAL_SERVER_ERROR);
return api_error($e->getMessage(), Status::INTERNAL_SERVER_ERROR);
}
return api_response(Status::HTTP_OK, $users);
return api_response(Status::OK, $users);
}
}

View File

@@ -73,7 +73,7 @@ final class Index
if (1 !== preg_match($regex, $data->get('rguid'), $matches)) {
return api_error(
'Invalid value for rguid query string expected value format is guid://parentID/seasonNumber[/episodeNumber].',
Status::HTTP_BAD_REQUEST
Status::BAD_REQUEST
);
}
@@ -144,7 +144,7 @@ final class Index
if (null === $parent) {
return api_error(
'Invalid value for parent query string expected value format is db://id.',
Status::HTTP_BAD_REQUEST
Status::BAD_REQUEST
);
}
@@ -161,7 +161,7 @@ final class Index
if (null === $guid) {
return api_error(
'Invalid value for guid query string expected value format is db://id.',
Status::HTTP_BAD_REQUEST
Status::BAD_REQUEST
);
}
@@ -176,14 +176,14 @@ final class Index
if (null === $sField || null === $sValue) {
return api_error(
'When searching using JSON fields the query string \'key\' and \'value\' must be set.',
Status::HTTP_BAD_REQUEST
Status::BAD_REQUEST
);
}
if (preg_match('/[^a-zA-Z0-9_\.]/', $sField)) {
return api_error(
'Invalid value for key query string expected value format is [a-zA-Z0-9_].',
Status::HTTP_BAD_REQUEST
Status::BAD_REQUEST
);
}
@@ -239,14 +239,14 @@ final class Index
if (null === $sField || null === $sValue) {
return api_error(
'When searching using JSON fields the query string \'key\' and \'value\' must be set.',
Status::HTTP_BAD_REQUEST
Status::BAD_REQUEST
);
}
if (preg_match('/[^a-zA-Z0-9_\.]/', $sField)) {
return api_error(
'Invalid value for key query string expected value format is [a-zA-Z0-9_].',
Status::HTTP_BAD_REQUEST
Status::BAD_REQUEST
);
}
@@ -283,7 +283,7 @@ final class Index
$message .= ' Probably invalid filters values were used.';
}
return api_error($message, Status::HTTP_NOT_FOUND, ['filters' => $filters]);
return api_error($message, Status::NOT_FOUND, ['filters' => $filters]);
}
$sorts = [];
@@ -446,66 +446,66 @@ final class Index
$response['history'][] = $this->formatEntity($row);
}
return api_response(Status::HTTP_OK, $response);
return api_response(Status::OK, $response);
}
#[Get(self::URL . '/{id:\d+}[/]', name: 'history.view')]
public function historyView(iRequest $request, array $args = []): iResponse
{
if (null === ($id = ag($args, 'id'))) {
return api_error('Invalid value for id path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for id path parameter.', Status::BAD_REQUEST);
}
$entity = Container::get(iState::class)::fromArray([iState::COLUMN_ID => $id]);
if (null === ($item = $this->db->get($entity))) {
return api_error('Not found', Status::HTTP_NOT_FOUND);
return api_error('Not found', Status::NOT_FOUND);
}
return api_response(Status::HTTP_OK, $this->formatEntity($item));
return api_response(Status::OK, $this->formatEntity($item));
}
#[Delete(self::URL . '/{id:\d+}[/]', name: 'history.item.delete')]
public function historyDelete(iRequest $request, array $args = []): iResponse
{
if (null === ($id = ag($args, 'id'))) {
return api_error('Invalid value for id path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for id path parameter.', Status::BAD_REQUEST);
}
$entity = Container::get(iState::class)::fromArray([iState::COLUMN_ID => $id]);
if (null === ($item = $this->db->get($entity))) {
return api_error('Not found', Status::HTTP_NOT_FOUND);
return api_error('Not found', Status::NOT_FOUND);
}
$this->db->remove($item);
return api_response(Status::HTTP_OK);
return api_response(Status::OK);
}
#[Route(['GET', 'POST', 'DELETE'], self::URL . '/{id:\d+}/watch[/]', name: 'history.watch')]
public function historyPlayStatus(iRequest $request, array $args = []): iResponse
{
if (null === ($id = ag($args, 'id'))) {
return api_error('Invalid value for id path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for id path parameter.', Status::BAD_REQUEST);
}
$entity = Container::get(iState::class)::fromArray([iState::COLUMN_ID => $id]);
if (null === ($item = $this->db->get($entity))) {
return api_error('Not found', Status::HTTP_NOT_FOUND);
return api_error('Not found', Status::NOT_FOUND);
}
if ('GET' === $request->getMethod()) {
return api_response(Status::HTTP_OK, ['watched' => $item->isWatched()]);
return api_response(Status::OK, ['watched' => $item->isWatched()]);
}
if ('POST' === $request->getMethod() && true === $item->isWatched()) {
return api_error('Already watched', Status::HTTP_CONFLICT);
return api_error('Already watched', Status::CONFLICT);
}
if ('DELETE' === $request->getMethod() && false === $item->isWatched()) {
return api_error('Already unwatched', Status::HTTP_CONFLICT);
return api_error('Already unwatched', Status::CONFLICT);
}
$item->watched = 'POST' === $request->getMethod() ? 1 : 0;

View File

@@ -76,7 +76,7 @@ final class Index
$response[] = $item;
}
return api_response(Status::HTTP_OK, $response);
return api_response(Status::OK, $response);
}
#[Post(self::URL . '[/]', name: 'ignore.add')]
@@ -88,7 +88,7 @@ final class Index
foreach (['id', 'db', 'backend', 'type'] as $key) {
if (null === $params->get($key)) {
return api_error(r('Missing required parameter: {key}', ['key' => $key]),
Status::HTTP_BAD_REQUEST);
Status::BAD_REQUEST);
}
}
@@ -104,19 +104,19 @@ final class Index
try {
checkIgnoreRule($id);
} catch (RuntimeException $e) {
return api_error($e->getMessage(), Status::HTTP_BAD_REQUEST);
return api_error($e->getMessage(), Status::BAD_REQUEST);
}
$filtered = (string)makeIgnoreId($id);
$date = time();
if ($this->config->has($id) || $this->config->has($filtered)) {
return api_error(r('Rule already exists: {id}', ['id' => $id]), Status::HTTP_CONFLICT);
return api_error(r('Rule already exists: {id}', ['id' => $id]), Status::CONFLICT);
}
$this->config->set($filtered, $date)->persist();
return api_response(Status::HTTP_OK, $this->ruleAsArray($filtered, $date));
return api_response(Status::OK, $this->ruleAsArray($filtered, $date));
}
#[Delete(self::URL . '[/]', name: 'ignore.delete')]
@@ -125,26 +125,26 @@ final class Index
$params = DataUtil::fromRequest($request);
if (null === ($rule = $params->get('rule'))) {
return api_error('Missing required parameter: rule', Status::HTTP_BAD_REQUEST);
return api_error('Missing required parameter: rule', Status::BAD_REQUEST);
}
try {
checkIgnoreRule($rule);
} catch (RuntimeException $e) {
return api_error($e->getMessage(), Status::HTTP_BAD_REQUEST);
return api_error($e->getMessage(), Status::BAD_REQUEST);
}
$filtered = (string)makeIgnoreId($rule);
if (!$this->config->has($filtered)) {
return api_error(r('Rule does not exist: {rule}', ['rule' => $rule]), Status::HTTP_NOT_FOUND);
return api_error(r('Rule does not exist: {rule}', ['rule' => $rule]), Status::NOT_FOUND);
}
$date = $this->config->get($filtered);
$this->config->delete($filtered)->persist();
return api_response(Status::HTTP_OK, $this->ruleAsArray($filtered, $date));
return api_response(Status::OK, $this->ruleAsArray($filtered, $date));
}
/**

View File

@@ -53,7 +53,7 @@ final class Index
$list[] = $builder;
}
return api_response(Status::HTTP_OK, $list);
return api_response(Status::OK, $list);
}
#[Get(Index::URL . '/recent[/]', name: 'logs.recent')]
@@ -105,14 +105,14 @@ final class Index
$list[] = $builder;
}
return api_response(Status::HTTP_OK, $list);
return api_response(Status::OK, $list);
}
#[Route(['GET', 'DELETE'], Index::URL_FILE . '/{filename}[/]', name: 'logs.view')]
public function logView(iRequest $request, array $args = []): iResponse
{
if (null === ($filename = ag($args, 'filename'))) {
return api_error('Invalid value for filename path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for filename path parameter.', Status::BAD_REQUEST);
}
$path = realpath(fixPath(Config::get('tmpDir') . '/logs'));
@@ -120,16 +120,16 @@ final class Index
$filePath = realpath($path . '/' . $filename);
if (false === $filePath) {
return api_error('File not found.', Status::HTTP_NOT_FOUND);
return api_error('File not found.', Status::NOT_FOUND);
}
if (false === str_starts_with($filePath, $path)) {
return api_error('Invalid file path.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid file path.', Status::BAD_REQUEST);
}
if ('DELETE' === $request->getMethod()) {
unlink($filePath);
return api_response(Status::HTTP_OK);
return api_response(Status::OK);
}
$params = DataUtil::fromArray($request->getQueryParams());
@@ -144,7 +144,7 @@ final class Index
}
if ($file->getSize() < 1) {
return api_response(Status::HTTP_OK);
return api_response(Status::OK);
}
$limit = (int)$params->get('limit', self::DEFAULT_LIMIT);
@@ -170,7 +170,7 @@ final class Index
$stream->rewind();
return new Response(status: Status::HTTP_OK->value, headers: [
return new Response(status: Status::OK->value, headers: [
'Content-Type' => 'text/plain',
'X-No-AccessLog' => '1'
], body: $stream);
@@ -181,7 +181,7 @@ final class Index
$mime = (new finfo(FILEINFO_MIME_TYPE))->file($filePath);
return new Response(
status: Status::HTTP_OK->value,
status: Status::OK->value,
headers: [
'Content-Type' => false === $mime ? 'application/octet-stream' : $mime,
'Content-Length' => filesize($filePath),
@@ -262,7 +262,7 @@ final class Index
};
return (new Response(
status: Status::HTTP_OK->value,
status: Status::OK->value,
headers: [
'Content-Type' => 'text/event-stream; charset=UTF-8',
'Cache-Control' => 'no-cache',

View File

@@ -19,12 +19,12 @@ final class AutoConfig
public function __invoke(iRequest $request): iResponse
{
if (false === (bool)Config::get('api.auto', false)) {
return api_error('auto configuration is disabled.', Status::HTTP_FORBIDDEN);
return api_error('auto configuration is disabled.', Status::FORBIDDEN);
}
$data = DataUtil::fromRequest($request);
return api_response(Status::HTTP_OK, [
return api_response(Status::OK, [
'url' => $data->get('origin', ag($_SERVER, 'HTTP_ORIGIN', 'localhost')),
'path' => Config::get('api.prefix'),
'token' => Config::get('api.key'),

View File

@@ -45,14 +45,14 @@ final class Backup
$item['date'] = makeDate(ag($item, 'date'));
}
return api_response(Status::HTTP_OK, $list);
return api_response(Status::OK, $list);
}
#[Route(['GET', 'DELETE'], self::URL . '/{filename}[/]', name: 'system.backup.view')]
public function logView(iRequest $request, array $args = []): iResponse
{
if (null === ($filename = ag($args, 'filename'))) {
return api_error('Invalid value for filename path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for filename path parameter.', Status::BAD_REQUEST);
}
$path = realpath(fixPath(Config::get('path') . '/backup'));
@@ -60,22 +60,22 @@ final class Backup
$filePath = realpath($path . '/' . $filename);
if (false === $filePath) {
return api_error('File not found.', Status::HTTP_NOT_FOUND);
return api_error('File not found.', Status::NOT_FOUND);
}
if (false === str_starts_with($filePath, $path)) {
return api_error('Invalid file path.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid file path.', Status::BAD_REQUEST);
}
if ('DELETE' === $request->getMethod()) {
unlink($filePath);
return api_response(Status::HTTP_OK);
return api_response(Status::OK);
}
$mime = (new finfo(FILEINFO_MIME_TYPE))->file($filePath);
return new Response(
status: Status::HTTP_OK->value,
status: Status::OK->value,
headers: [
'Content-Type' => false === $mime ? 'application/octet-stream' : $mime,
'Content-Length' => filesize($filePath),

View File

@@ -57,7 +57,7 @@ final class Env
$list = array_filter($list, fn($info) => $this->envFile->has($info['key']));
}
return api_response(Status::HTTP_OK, [
return api_response(Status::OK, [
'data' => array_values($list),
'file' => Config::get('path') . '/config/.env',
]);
@@ -68,20 +68,20 @@ final class Env
{
$key = strtoupper((string)ag($args, 'key', ''));
if (empty($key)) {
return api_error('Invalid value for key path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for key path parameter.', Status::BAD_REQUEST);
}
$spec = $this->getSpec($key);
if (empty($spec)) {
return api_error(r("Invalid key '{key}' was given.", ['key' => $key]), Status::HTTP_BAD_REQUEST);
return api_error(r("Invalid key '{key}' was given.", ['key' => $key]), Status::BAD_REQUEST);
}
if (false === $this->envFile->has($key)) {
return api_error(r("Key '{key}' is not set.", ['key' => $key]), Status::HTTP_NOT_FOUND);
return api_error(r("Key '{key}' is not set.", ['key' => $key]), Status::NOT_FOUND);
}
return api_response(Status::HTTP_OK, [
return api_response(Status::OK, [
'key' => $key,
'value' => $this->settype($spec, ag($spec, 'value', fn() => $this->envFile->get($key))),
'description' => ag($spec, 'description'),
@@ -94,19 +94,19 @@ final class Env
{
$key = strtoupper((string)ag($args, 'key', ''));
if (empty($key)) {
return api_error('Invalid value for key path parameter.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid value for key path parameter.', Status::BAD_REQUEST);
}
$spec = $this->getSpec($key);
if (empty($spec)) {
return api_error(r("Invalid key '{key}' was given.", ['key' => $key]), Status::HTTP_BAD_REQUEST);
return api_error(r("Invalid key '{key}' was given.", ['key' => $key]), Status::BAD_REQUEST);
}
if ('DELETE' === $request->getMethod()) {
$this->envFile->remove($key)->persist();
return api_response(Status::HTTP_OK, [
return api_response(Status::OK, [
'key' => $key,
'value' => $this->setType($spec, ag($spec, 'value', fn() => $this->envFile->get($key))),
'description' => ag($spec, 'description'),
@@ -117,11 +117,11 @@ final class Env
$params = DataUtil::fromRequest($request);
if (null === ($value = $params->get('value', null))) {
return api_error(r("No value was provided for '{key}'.", ['key' => $key]), Status::HTTP_BAD_REQUEST);
return api_error(r("No value was provided for '{key}'.", ['key' => $key]), Status::BAD_REQUEST);
}
if ($value === ag($spec, 'value')) {
return api_response(Status::HTTP_NOT_MODIFIED);
return api_response(Status::NOT_MODIFIED);
}
try {
@@ -134,12 +134,12 @@ final class Env
return api_error(r("Value validation for '{key}' failed. {error}", [
'key' => $key,
'error' => $e->getMessage()
]), Status::HTTP_BAD_REQUEST);
]), Status::BAD_REQUEST);
}
$this->envFile->set($key, $value)->persist();
return api_response(Status::HTTP_OK, [
return api_response(Status::OK, [
'key' => $key,
'value' => $value,
'description' => ag($spec, 'description'),

View File

@@ -69,7 +69,7 @@ final class Events
$response['requests'][] = ['key' => $key, 'item' => $this->formatEntity($item)];
}
return api_response(Status::HTTP_OK, $response);
return api_response(Status::OK, $response);
}
/**
@@ -81,7 +81,7 @@ final class Events
$params = DataUtil::fromRequest($request, true);
if (null === ($id = $params->get('id', ag($args, 'id')))) {
return api_error('Invalid id.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid id.', Status::BAD_REQUEST);
}
$type = $params->get('type', 'queue');
@@ -90,20 +90,20 @@ final class Events
return api_error(r("Invalid type '{type}'. Only '{types}' are supported.", [
'type' => $type,
'types' => implode(", ", self::TYPES),
]), Status::HTTP_BAD_REQUEST);
]), Status::BAD_REQUEST);
}
$items = $this->cache->get($type, []);
if (empty($items)) {
return api_error(r('{type} is empty.', ['type' => $type]), Status::HTTP_NOT_FOUND);
return api_error(r('{type} is empty.', ['type' => $type]), Status::NOT_FOUND);
}
if (false === array_key_exists($id, $items)) {
return api_error(r("Record id '{id}' doesn't exists. for '{type}' list.", [
'id' => $id,
'type' => $type,
]), Status::HTTP_NOT_FOUND);
]), Status::NOT_FOUND);
}
if ('queue' === $type) {
@@ -114,6 +114,6 @@ final class Events
$this->cache->set($type, $items, new DateInterval('P3D'));
}
return api_response(Status::HTTP_OK, ['id' => $id, 'type' => $type, 'status' => 'deleted']);
return api_response(Status::OK, ['id' => $id, 'type' => $type, 'status' => 'deleted']);
}
}

View File

@@ -31,6 +31,6 @@ final class Guids
$list[] = $item;
}
return api_response(Status::HTTP_OK, $list);
return api_response(Status::OK, $list);
}
}

View File

@@ -16,7 +16,7 @@ final class HealthCheck
#[Get(self::URL . '[/]', name: 'system.healthcheck')]
public function __invoke(iRequest $request): iResponse
{
return api_response(Status::HTTP_OK, [
return api_response(Status::OK, [
'status' => 'ok',
'message' => 'System is healthy',
]);

View File

@@ -89,7 +89,7 @@ final class Integrity
'checked_file' => $this->checkedFile,
], new DateInterval('PT1H'));
return api_response(Status::HTTP_OK, $response);
return api_response(Status::OK, $response);
}
private function checkIntegrity(iState $entity): bool
@@ -163,7 +163,7 @@ final class Integrity
$this->cache->delete('system.integrity');
}
return api_response(Status::HTTP_OK);
return api_response(Status::OK);
}
private function checkPath(string $file): bool

View File

@@ -54,7 +54,7 @@ final class Parity
if ($counter > $backendsCount) {
return api_error(r("Minimum value cannot be greater than the number of backends '({backends})'.", [
'backends' => $backendsCount,
]), Status::HTTP_BAD_REQUEST);
]), Status::BAD_REQUEST);
}
$counter = 0 === $counter ? $backendsCount : $counter;
@@ -68,7 +68,7 @@ final class Parity
return api_error(r("Invalid page number. '{page}' is higher than what the last page is '{last_page}'.", [
'page' => $page,
'last_page' => $lastPage,
]), Status::HTTP_NOT_FOUND);
]), Status::NOT_FOUND);
}
$sql = "SELECT
@@ -107,7 +107,7 @@ final class Parity
]
];
return api_response(Status::HTTP_OK, $response);
return api_response(Status::OK, $response);
}
/**
@@ -119,7 +119,7 @@ final class Parity
$params = DataUtil::fromRequest($request, true);
if (0 === ($counter = (int)$params->get('min', 0))) {
return api_error('Invalid minimum value.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid minimum value.', Status::BAD_REQUEST);
}
$count = count($this->getBackends());
@@ -127,7 +127,7 @@ final class Parity
if ($counter > $count) {
return api_error(r("Minimum value cannot be greater than the number of backends '({backends})'.", [
'backends' => $count,
]), Status::HTTP_BAD_REQUEST);
]), Status::BAD_REQUEST);
}
$sql = "DELETE FROM
@@ -137,7 +137,7 @@ final class Parity
";
$stmt = $this->db->getPDO()->query($sql);
return api_response(Status::HTTP_OK, [
return api_response(Status::OK, [
'deleted_records' => $stmt->rowCount(),
]);
}

View File

@@ -16,6 +16,6 @@ final class Report
#[Get(self::URL . '[/]', name: 'system.report')]
public function __invoke(iRequest $request): iResponse
{
return api_response(Status::HTTP_OK, runCommand('system:report', asArray: true));
return api_response(Status::OK, runCommand('system:report', asArray: true));
}
}

View File

@@ -41,6 +41,6 @@ final class Reset
$list->persist();
return api_response(Status::HTTP_OK, ['message' => 'System reset.']);
return api_response(Status::OK, ['message' => 'System reset.']);
}
}

View File

@@ -17,6 +17,6 @@ final class Supported
#[Get(self::URL . '[/]', name: 'system.supported')]
public function __invoke(iRequest $request): iResponse
{
return api_response(Status::HTTP_OK, array_keys(Config::get('supported')));
return api_response(Status::OK, array_keys(Config::get('supported')));
}
}

View File

@@ -37,7 +37,7 @@ final class Suppressor
$list[] = ['id' => $id, ...$data,];
}
return api_response(Status::HTTP_OK, [
return api_response(Status::OK, [
'items' => $list,
'types' => self::TYPES
]);
@@ -52,11 +52,11 @@ final class Suppressor
$params = DataUtil::fromRequest($request);
if (null === ($rule = $params->get('rule')) || empty($rule)) {
return api_error('Rule is required.', Status::HTTP_BAD_REQUEST);
return api_error('Rule is required.', Status::BAD_REQUEST);
}
if (null === ($type = $params->get('type')) || empty($type)) {
return api_error('Rule type is required.', Status::HTTP_BAD_REQUEST);
return api_error('Rule type is required.', Status::BAD_REQUEST);
}
$type = strtolower($type);
@@ -65,15 +65,15 @@ final class Suppressor
return api_error(r("Invalid rule type '{type}'. Expected '{types}'", [
'type' => $type,
'types' => implode(', ', self::TYPES),
]), Status::HTTP_BAD_REQUEST);
]), Status::BAD_REQUEST);
}
if (null === ($example = $params->get('example')) || empty($example)) {
return api_error('Rule example is required.', Status::HTTP_BAD_REQUEST);
return api_error('Rule example is required.', Status::BAD_REQUEST);
}
if ('regex' === $type && false === @preg_match($rule, '')) {
return api_error('Invalid regex pattern.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid regex pattern.', Status::BAD_REQUEST);
}
$suppressor = new LogSuppressor([
@@ -88,7 +88,7 @@ final class Suppressor
'example' => $example,
'type' => $type,
'rule' => $rule,
]), Status::HTTP_BAD_REQUEST);
]), Status::BAD_REQUEST);
}
$id = ag($args, 'id', null);
@@ -102,7 +102,7 @@ final class Suppressor
$suppressor = new LogSuppressor($rules);
if ($suppressor->isSuppressed($example)) {
return api_error('Example is already suppressed by another rule.', Status::HTTP_BAD_REQUEST);
return api_error('Example is already suppressed by another rule.', Status::BAD_REQUEST);
}
$data = [
@@ -115,7 +115,7 @@ final class Suppressor
$this->file->set($id, $data)->persist();
return api_response(Status::HTTP_OK, ['id' => $id, ...$data]);
return api_response(Status::OK, ['id' => $id, ...$data]);
}
/**
@@ -131,30 +131,30 @@ final class Suppressor
public function deleteSuppressor(iRequest $request, array $args = []): iResponse
{
if (null === ($id = ag($args, 'id')) || empty($id)) {
return api_error('Invalid suppressor id.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid suppressor id.', Status::BAD_REQUEST);
}
if (null === ($rule = $this->file->get($id))) {
return api_error('Suppressor rule not found.', Status::HTTP_NOT_FOUND);
return api_error('Suppressor rule not found.', Status::NOT_FOUND);
}
$this->file->delete($id)->persist();
return api_response(Status::HTTP_OK, ['id' => $id, ...$rule]);
return api_response(Status::OK, ['id' => $id, ...$rule]);
}
#[Get(self::URL . '/{id:\w{11}}[/]', name: 'system.suppressor.view')]
public function viewSuppressor(iRequest $request, array $args = []): iResponse
{
if (null === ($id = ag($args, 'id')) || empty($id)) {
return api_error('Invalid suppressor id.', Status::HTTP_BAD_REQUEST);
return api_error('Invalid suppressor id.', Status::BAD_REQUEST);
}
if (null === ($rule = $this->file->get($id))) {
return api_error('Suppressor rule not found.', Status::HTTP_NOT_FOUND);
return api_error('Suppressor rule not found.', Status::NOT_FOUND);
}
return api_response(Status::HTTP_OK, ['id' => $id, ...$rule]);
return api_response(Status::OK, ['id' => $id, ...$rule]);
}
/**

View File

@@ -16,6 +16,6 @@ final class Version
#[Get(self::URL . '[/]', name: 'system.version')]
public function __invoke(iRequest $request): iResponse
{
return api_response(Status::HTTP_OK, ['version' => getAppVersion()]);
return api_response(Status::OK, ['version' => getAppVersion()]);
}
}

View File

@@ -42,7 +42,7 @@ final class Index
$response['tasks'][] = $task;
}
return api_response(Status::HTTP_OK, $response);
return api_response(Status::OK, $response);
}
/**
@@ -52,13 +52,13 @@ final class Index
public function taskQueue(iRequest $request, array $args = []): iResponse
{
if (null === ($id = ag($args, 'id'))) {
return api_error('No id was given.', Status::HTTP_BAD_REQUEST);
return api_error('No id was given.', Status::BAD_REQUEST);
}
$task = TasksCommand::getTasks($id);
if (empty($task)) {
return api_error('Task not found.', Status::HTTP_NOT_FOUND);
return api_error('Task not found.', Status::NOT_FOUND);
}
$queuedTasks = $this->cache->get('queued_tasks', []);
@@ -66,16 +66,16 @@ final class Index
if ('POST' === $request->getMethod()) {
$queuedTasks[] = $id;
$this->cache->set('queued_tasks', $queuedTasks, new DateInterval('P3D'));
return api_response(Status::HTTP_ACCEPTED, ['queue' => $queuedTasks]);
return api_response(Status::ACCEPTED, ['queue' => $queuedTasks]);
}
if ('DELETE' === $request->getMethod()) {
$queuedTasks = array_filter($queuedTasks, fn($v) => $v !== $id);
$this->cache->set('queued_tasks', $queuedTasks, new DateInterval('P3D'));
return api_response(Status::HTTP_OK, ['queue' => $queuedTasks]);
return api_response(Status::OK, ['queue' => $queuedTasks]);
}
return api_response(Status::HTTP_OK, [
return api_response(Status::OK, [
'task' => $id,
'is_queued' => in_array($id, $queuedTasks),
]);
@@ -88,13 +88,13 @@ final class Index
public function taskView(iRequest $request, array $args = []): iResponse
{
if (null === ($id = ag($args, 'id'))) {
return api_error('No id was given.', Status::HTTP_BAD_REQUEST);
return api_error('No id was given.', Status::BAD_REQUEST);
}
$task = TasksCommand::getTasks($id);
if (empty($task)) {
return api_error('Task not found.', Status::HTTP_NOT_FOUND);
return api_error('Task not found.', Status::NOT_FOUND);
}
$queuedTasks = $this->cache->get('queued_tasks', []);
@@ -102,7 +102,7 @@ final class Index
$data = Index::formatTask($task);
$data['queued'] = in_array(ag($task, 'name'), $queuedTasks);
return api_response(Status::HTTP_OK, $data);
return api_response(Status::OK, $data);
}
private function formatTask(array $task): array

View File

@@ -83,11 +83,11 @@ class JellyfinValidateContext
],
]);
if (Status::HTTP_UNAUTHORIZED->value === $request->getStatusCode()) {
if (Status::UNAUTHORIZED->value === $request->getStatusCode()) {
throw new InvalidContextException('Backend responded with 401. Most likely means token is invalid.');
}
if (Status::HTTP_NOT_FOUND->value === $request->getStatusCode()) {
if (Status::NOT_FOUND->value === $request->getStatusCode()) {
throw new InvalidContextException('Backend responded with 404. Most likely means url is incorrect.');
}

View File

@@ -78,7 +78,7 @@ final class GetUser
'url' => (string)$url,
]);
if (Status::HTTP_OK->value !== $response->getStatusCode()) {
if (Status::OK->value !== $response->getStatusCode()) {
$message = "Request for '{backend}' user info returned with unexpected '{status_code}' status code. Using {type} token.";
if (null !== ag($context->options, Options::ADMIN_TOKEN)) {
@@ -89,7 +89,7 @@ final class GetUser
'X-Plex-Client-Identifier' => $context->backendId,
],
]);
if (Status::HTTP_OK->value === $adminResponse->getStatusCode()) {
if (Status::OK->value === $adminResponse->getStatusCode()) {
return $this->process($context, $url, $adminResponse, $opts);
}

View File

@@ -97,7 +97,7 @@ final class GetUsersList
'url' => (string)$url,
]);
if (Status::HTTP_OK->value !== $response->getStatusCode()) {
if (Status::OK !== Status::from($response->getStatusCode())) {
$message = "Request for '{backend}' users list returned with unexpected '{status_code}' status code. Using {type} token.";
if (null !== ag($context->options, Options::ADMIN_TOKEN)) {
@@ -109,7 +109,7 @@ final class GetUsersList
],
]);
if (Status::HTTP_OK->value === $adminResponse->getStatusCode()) {
if (Status::OK === Status::from($adminResponse->getStatusCode())) {
return $this->process($context, $url, $adminResponse, $opts);
}
$tokenType = 'user and admin';

View File

@@ -89,11 +89,11 @@ final readonly class PlexValidateContext
],
]);
if (Status::HTTP_UNAUTHORIZED->value === $request->getStatusCode()) {
if (Status::UNAUTHORIZED->value === $request->getStatusCode()) {
throw new InvalidContextException('Backend responded with 401. Most likely means token is invalid.');
}
if (Status::HTTP_NOT_FOUND->value === $request->getStatusCode()) {
if (Status::NOT_FOUND->value === $request->getStatusCode()) {
throw new InvalidContextException('Backend responded with 404. Most likely means url is incorrect.');
}

View File

@@ -127,7 +127,7 @@ final class ManageCommand extends Command
if ($input->getOption('remove')) {
$response = APIRequest('DELETE', '/ignore/', ['rule' => $rule]);
if (Status::HTTP_OK !== $response->status) {
if (Status::OK !== $response->status) {
$output->writeln(r("<error>API error. {status}: {message}</error>", [
'key' => $rule,
'status' => $response->status->value,
@@ -142,7 +142,7 @@ final class ManageCommand extends Command
$response = APIRequest('POST', '/ignore/', ['rule' => $rule]);
if (Status::HTTP_OK !== $response->status) {
if (Status::OK !== $response->status) {
$output->writeln(r("<error>API error. {status}: {message}</error>", [
'key' => $rule,
'status' => $response->status->value,

View File

@@ -159,7 +159,7 @@ final class MismatchCommand extends Command
$response = APIRequest('GET', $url, opts: ['query' => $query]);
if (Status::HTTP_OK !== $response->status) {
if (Status::OK !== $response->status) {
$output->writeln(r('<error>API error. {status}: {message}</error>', [
'id' => $id,
'status' => $response->status->value,

View File

@@ -112,7 +112,7 @@ final class UnmatchedCommand extends Command
$response = APIRequest('GET', $url, opts: ['query' => $query]);
if (Status::HTTP_OK !== $response->status) {
if (Status::OK !== $response->status) {
$output->writeln(r('<error>API error. {status}: {message}</error>', [
'id' => $id,
'status' => $response->status->value,

View File

@@ -84,7 +84,7 @@ final class IdCommand extends Command
$response = APIRequest('GET', r('/backend/{backend}/search', ['backend' => $name]), opts: ['query' => $query]);
if (Status::HTTP_NOT_FOUND === $response->status) {
if (Status::NOT_FOUND === $response->status) {
$output->writeln(r("<error>No results for '{key}'. {status}: {message}</error>", [
'key' => $id,
'status' => $response->status->value,
@@ -93,7 +93,7 @@ final class IdCommand extends Command
return self::FAILURE;
}
if (Status::HTTP_OK !== $response->status) {
if (Status::OK !== $response->status) {
$output->writeln(r("<error>API error. {status}: {message}</error>", [
'key' => $id,
'status' => $response->status->value,

View File

@@ -88,7 +88,7 @@ final class QueryCommand extends Command
$response = APIRequest('GET', r('/backend/{backend}/search', ['backend' => $name]), opts: ['query' => $query]);
if (Status::HTTP_NOT_FOUND === $response->status) {
if (Status::NOT_FOUND === $response->status) {
$output->writeln(r("<error>No results for '{key}'. {status}: {message}</error>", [
'key' => $query,
'status' => $response->status->value,
@@ -97,7 +97,7 @@ final class QueryCommand extends Command
return self::FAILURE;
}
if (Status::HTTP_OK !== $response->status) {
if (Status::OK !== $response->status) {
$output->writeln(r("<error>API error. {status}: {message}</error>", [
'key' => $query,
'status' => $response->status->value,

View File

@@ -152,7 +152,7 @@ final class DeleteCommand extends Command
$response = APIRequest('DELETE', '/backend/' . $name);
if (Status::HTTP_OK !== $response->status) {
if (Status::OK !== $response->status) {
$output->writeln(r("<error>API error. {status}: {message}</error>", [
'key' => $name,
'status' => $response->status->value,

View File

@@ -122,7 +122,7 @@ final class EditCommand extends Command
$response = apiRequest($method, "/backend/{$name}/option/{$key}", $json);
if (Status::HTTP_OK !== $response->status) {
if (Status::OK !== $response->status) {
$output->writeln(r("<error>API error. {status}: {message}</error>", [
'status' => $response->status->value,
'message' => ag($response->body, 'error.message', 'Unknown error.')

View File

@@ -296,7 +296,7 @@ final class ListCommand extends Command
'query' => $params,
]);
if (Status::HTTP_OK !== $response->status) {
if (Status::OK !== $response->status) {
$output->writeln(r("<error>API error. {status}: {message}</error>", [
'status' => $response->status->value,
'message' => ag($response->body, 'error.message', 'Unknown error.')

View File

@@ -112,7 +112,7 @@ final class ParityCommand extends Command
$response = APIRequest('GET', '/system/parity/', opts: ['query' => $params]);
if (Status::HTTP_OK !== $response->status) {
if (Status::OK !== $response->status) {
$output->writeln(r("<error>API error. {status}: {message}</error>", [
'status' => $response->status->value,
'message' => ag($response->body, 'error.message', 'Unknown error.')
@@ -177,7 +177,7 @@ final class ParityCommand extends Command
$response = APIRequest('DELETE', '/system/parity/', opts: ['query' => ['min' => $min]]);
if (Status::HTTP_OK !== $response->status) {
if (Status::OK !== $response->status) {
$output->writeln(r("<error>API error. {status}: {message}</error>", [
'status' => $response->status->value,
'message' => ag($response->body, 'error.message', 'Unknown error.')

View File

@@ -159,7 +159,7 @@ final class EnvCommand extends Command
$response = APIRequest('POST', '/system/env/' . $key, ['value' => $input->getOption('set')]);
}
if (Status::HTTP_OK !== $response->status) {
if (Status::OK !== $response->status) {
$output->writeln(r("<error>API error. {status}: {message}</error>", [
'key' => $key,
'status' => $response->status->value,

View File

@@ -128,7 +128,7 @@ final class ResetCommand extends Command
);
$response = APIRequest('DELETE', '/system/reset');
if (Status::HTTP_OK !== $response->status) {
if (Status::OK !== $response->status) {
$output->writeln(r("<error>API error. {status}: {message}</error>", [
'status' => $response->status->value,
'message' => ag($response->body, 'error.message', 'Unknown error.')

View File

@@ -120,7 +120,7 @@ final class SuppressCommand extends Command
}
$response = APIRequest('GET', '/system/suppressor/' . $id);
if (Status::HTTP_OK !== $response->status) {
if (Status::OK !== $response->status) {
$output->writeln(r("<error>API error. {status}: {message}</error>", [
'status' => $response->status->value,
'message' => ag($response->body, 'error.message', 'Unknown error.')
@@ -184,7 +184,7 @@ final class SuppressCommand extends Command
$response = APIRequest($id ? 'PUT' : 'POST', '/system/suppressor' . ($id ? '/' . $id : ''), $data);
if (Status::HTTP_OK !== $response->status) {
if (Status::OK !== $response->status) {
$output->writeln(r("<error>API error. {status}: {message}</error>", [
'status' => $response->status->value,
'message' => ag($response->body, 'error.message', 'Unknown error.')
@@ -206,7 +206,7 @@ final class SuppressCommand extends Command
}
$response = APIRequest('DELETE', '/system/suppressor/' . $id);
if (Status::HTTP_OK !== $response->status) {
if (Status::OK !== $response->status) {
$output->writeln(r("<error>API error. {status}: {message}</error>", [
'status' => $response->status->value,
'message' => ag($response->body, 'error.message', 'Unknown error.')
@@ -222,7 +222,7 @@ final class SuppressCommand extends Command
{
$response = APIRequest('GET', '/system/suppressor');
if (Status::HTTP_OK !== $response->status) {
if (Status::OK !== $response->status) {
$output->writeln(r("<error>API error. {status}: {message}</error>", [
'status' => $response->status->value,
'message' => ag($response->body, 'error.message', 'Unknown error.')

View File

@@ -7,67 +7,67 @@ namespace App\Libs\Enums\Http;
*/
enum Status: int
{
case HTTP_CONTINUE = 100;
case HTTP_SWITCHING_PROTOCOLS = 101;
case HTTP_PROCESSING = 102; // RFC2518
case HTTP_EARLY_HINTS = 103; // RFC8297
case HTTP_OK = 200;
case HTTP_CREATED = 201;
case HTTP_ACCEPTED = 202;
case HTTP_NON_AUTHORITATIVE_INFORMATION = 203;
case HTTP_NO_CONTENT = 204;
case HTTP_RESET_CONTENT = 205;
case HTTP_PARTIAL_CONTENT = 206;
case HTTP_MULTI_STATUS = 207; // RFC4918
case HTTP_ALREADY_REPORTED = 208; // RFC5842
case HTTP_IM_USED = 226; // RFC3229
case HTTP_MULTIPLE_CHOICES = 300;
case HTTP_MOVED_PERMANENTLY = 301;
case HTTP_FOUND = 302;
case HTTP_SEE_OTHER = 303;
case HTTP_NOT_MODIFIED = 304;
case HTTP_USE_PROXY = 305;
case HTTP_RESERVED = 306;
case HTTP_TEMPORARY_REDIRECT = 307;
case HTTP_PERMANENTLY_REDIRECT = 308; // RFC7238
case HTTP_BAD_REQUEST = 400;
case HTTP_UNAUTHORIZED = 401;
case HTTP_PAYMENT_REQUIRED = 402;
case HTTP_FORBIDDEN = 403;
case HTTP_NOT_FOUND = 404;
case HTTP_METHOD_NOT_ALLOWED = 405;
case HTTP_NOT_ACCEPTABLE = 406;
case HTTP_PROXY_AUTHENTICATION_REQUIRED = 407;
case HTTP_REQUEST_TIMEOUT = 408;
case HTTP_CONFLICT = 409;
case HTTP_GONE = 410;
case HTTP_LENGTH_REQUIRED = 411;
case HTTP_PRECONDITION_FAILED = 412;
case HTTP_REQUEST_ENTITY_TOO_LARGE = 413;
case HTTP_REQUEST_URI_TOO_LONG = 414;
case HTTP_UNSUPPORTED_MEDIA_TYPE = 415;
case HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
case HTTP_EXPECTATION_FAILED = 417;
case HTTP_I_AM_A_TEAPOT = 418; // RFC2324
case HTTP_MISDIRECTED_REQUEST = 421; // RFC7540
case HTTP_UNPROCESSABLE_ENTITY = 422; // RFC4918
case HTTP_LOCKED = 423; // RFC4918
case HTTP_FAILED_DEPENDENCY = 424; // RFC4918
case HTTP_TOO_EARLY = 425; // RFC-ietf-httpbis-replay-04
case HTTP_UPGRADE_REQUIRED = 426; // RFC2817
case HTTP_PRECONDITION_REQUIRED = 428; // RFC6585
case HTTP_TOO_MANY_REQUESTS = 429; // RFC6585
case HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431; // RFC6585
case HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451; // RFC7725
case HTTP_INTERNAL_SERVER_ERROR = 500;
case HTTP_NOT_IMPLEMENTED = 501;
case HTTP_BAD_GATEWAY = 502;
case HTTP_SERVICE_UNAVAILABLE = 503;
case HTTP_GATEWAY_TIMEOUT = 504;
case HTTP_VERSION_NOT_SUPPORTED = 505;
case HTTP_VARIANT_ALSO_NEGOTIATES_EXPERIMENTAL = 506; // RFC2295
case HTTP_INSUFFICIENT_STORAGE = 507; // RFC4918
case HTTP_LOOP_DETECTED = 508; // RFC5842
case HTTP_NOT_EXTENDED = 510; // RFC2774
case HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511; // RFC6585
case CONTINUE = 100;
case SWITCHING_PROTOCOLS = 101;
case PROCESSING = 102; // RFC2518
case EARLY_HINTS = 103; // RFC8297
case OK = 200;
case CREATED = 201;
case ACCEPTED = 202;
case NON_AUTHORITATIVE_INFORMATION = 203;
case NO_CONTENT = 204;
case RESET_CONTENT = 205;
case PARTIAL_CONTENT = 206;
case MULTI_STATUS = 207; // RFC4918
case ALREADY_REPORTED = 208; // RFC5842
case IM_USED = 226; // RFC3229
case MULTIPLE_CHOICES = 300;
case MOVED_PERMANENTLY = 301;
case FOUND = 302;
case SEE_OTHER = 303;
case NOT_MODIFIED = 304;
case USE_PROXY = 305;
case RESERVED = 306;
case TEMPORARY_REDIRECT = 307;
case PERMANENTLY_REDIRECT = 308; // RFC7238
case BAD_REQUEST = 400;
case UNAUTHORIZED = 401;
case PAYMENT_REQUIRED = 402;
case FORBIDDEN = 403;
case NOT_FOUND = 404;
case METHOD_NOT_ALLOWED = 405;
case NOT_ACCEPTABLE = 406;
case PROXY_AUTHENTICATION_REQUIRED = 407;
case REQUEST_TIMEOUT = 408;
case CONFLICT = 409;
case GONE = 410;
case LENGTH_REQUIRED = 411;
case PRECONDITION_FAILED = 412;
case REQUEST_ENTITY_TOO_LARGE = 413;
case REQUEST_URI_TOO_LONG = 414;
case UNSUPPORTED_MEDIA_TYPE = 415;
case REQUESTED_RANGE_NOT_SATISFIABLE = 416;
case EXPECTATION_FAILED = 417;
case I_AM_A_TEAPOT = 418; // RFC2324
case MISDIRECTED_REQUEST = 421; // RFC7540
case UNPROCESSABLE_ENTITY = 422; // RFC4918
case LOCKED = 423; // RFC4918
case FAILED_DEPENDENCY = 424; // RFC4918
case TOO_EARLY = 425; // RFC-ietf-httpbis-replay-04
case UPGRADE_REQUIRED = 426; // RFC2817
case PRECONDITION_REQUIRED = 428; // RFC6585
case TOO_MANY_REQUESTS = 429; // RFC6585
case REQUEST_HEADER_FIELDS_TOO_LARGE = 431; // RFC6585
case UNAVAILABLE_FOR_LEGAL_REASONS = 451; // RFC7725
case INTERNAL_SERVER_ERROR = 500;
case NOT_IMPLEMENTED = 501;
case BAD_GATEWAY = 502;
case SERVICE_UNAVAILABLE = 503;
case GATEWAY_TIMEOUT = 504;
case VERSION_NOT_SUPPORTED = 505;
case VARIANT_ALSO_NEGOTIATES_EXPERIMENTAL = 506; // RFC2295
case INSUFFICIENT_STORAGE = 507; // RFC4918
case LOOP_DETECTED = 508; // RFC5842
case NOT_EXTENDED = 510; // RFC2774
case NETWORK_AUTHENTICATION_REQUIRED = 511; // RFC6585
}

View File

@@ -23,7 +23,7 @@ class RouterStrategy extends ApplicationStrategy implements OptionsHandlerInterf
'Allow' => implode(', ', $methods),
];
$response = new Response(status: Status::HTTP_NO_CONTENT->value, headers: $headers);
$response = new Response(status: Status::NO_CONTENT->value, headers: $headers);
if ('cors' === ag($_SERVER, 'HTTP_SEC_FETCH_MODE')) {
return fn(): iResponse => addCors($response, $headers, $methods);

View File

@@ -226,10 +226,10 @@ final class Initializer
$response = api_error(
message: "{$realStatusCode}: {$e->getMessage()}",
httpCode: Status::tryFrom($realStatusCode) ?? Status::HTTP_SERVICE_UNAVAILABLE,
httpCode: Status::tryFrom($realStatusCode) ?? Status::SERVICE_UNAVAILABLE,
);
if (Status::HTTP_SERVICE_UNAVAILABLE->value === $statusCode) {
if (Status::SERVICE_UNAVAILABLE->value === $statusCode) {
Container::get(LoggerInterface::class)->error($e->getMessage(), [
'kind' => $e::class,
'file' => $e->getFile(),
@@ -246,7 +246,7 @@ final class Initializer
} catch (Throwable $e) {
$response = api_error(
message: 'Unable to serve request.',
httpCode: Status::HTTP_SERVICE_UNAVAILABLE,
httpCode: Status::SERVICE_UNAVAILABLE,
body: true !== (bool)Config::get('debug.enabled', false) ? [] : [
'exception' => [
'message' => $e->getMessage(),
@@ -289,7 +289,7 @@ final class Initializer
// -- health endpoint.
if (true === str_starts_with($requestPath, '/healthcheck')) {
return api_response(Status::HTTP_OK);
return api_response(Status::OK);
}
// -- Forward requests to API server.
@@ -301,7 +301,7 @@ final class Initializer
if (empty($apikey)) {
if (false === (bool)Config::get('webui.enabled', false)) {
$response = api_response(Status::HTTP_UNAUTHORIZED);
$response = api_response(Status::UNAUTHORIZED);
$this->write(
$request,
Level::Info,
@@ -332,7 +332,7 @@ final class Initializer
}
if (empty($backend)) {
$response = api_response(Status::HTTP_UNAUTHORIZED);
$response = api_response(Status::UNAUTHORIZED);
$this->write($request, Level::Info, $this->formatLog($request, $response, 'Invalid token was given.'));
return $response;
}

View File

@@ -8,12 +8,12 @@ use App\API\Backends\AccessToken;
use App\API\System\AutoConfig;
use App\API\System\HealthCheck;
use App\Libs\Config;
use App\Libs\Enums\Http\Method;
use App\Libs\Enums\Http\Status;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface as iResponse;
use Psr\Http\Message\ServerRequestInterface as iRequest;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Random\RandomException;
use Psr\Http\Server\RequestHandlerInterface as iHandler;
final class APIKeyRequiredMiddleware implements MiddlewareInterface
{
@@ -35,19 +35,20 @@ final class APIKeyRequiredMiddleware implements MiddlewareInterface
'/webhook'
];
/**
* @throws RandomException if random_bytes() fails
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
public function process(iRequest $request, iHandler $handler): iResponse
{
if ('OPTIONS' === $request->getMethod() || true === (bool)$request->getAttribute('INTERNAL_REQUEST', false)) {
if (true === (bool)$request->getAttribute('INTERNAL_REQUEST')) {
return $handler->handle($request);
}
if (Method::OPTIONS === Method::from($request->getMethod())) {
return $handler->handle($request);
}
$requestPath = rtrim($request->getUri()->getPath(), '/');
$openRoutes = self::PUBLIC_ROUTES;
if (false === (bool)Config::get('api.secure')) {
if (false === (bool)Config::get('api.secure', false)) {
$openRoutes = array_merge($openRoutes, self::OPEN_ROUTES);
}
@@ -58,77 +59,50 @@ final class APIKeyRequiredMiddleware implements MiddlewareInterface
}
}
$headerApiKey = $request->getHeaderLine('x-' . self::KEY_NAME);
$tokens = $this->parseTokens($request);
if (!empty($headerApiKey)) {
$apikey = $headerApiKey;
} elseif (null !== ($headerApiKey = $this->parseAuthorization($request->getHeaderLine('Authorization')))) {
$apikey = $headerApiKey;
} else {
$apikey = (string)ag($request->getQueryParams(), self::KEY_NAME, '');
if (count($tokens) < 1) {
return api_error('API key is required to access the API.', Status::BAD_REQUEST);
}
if (empty($apikey)) {
return api_error(
'API key is required to access the API.',
Status::HTTP_BAD_REQUEST,
reason: 'API key is required to access the API.',
);
foreach ($tokens as $token) {
if (true === $this->validate($token)) {
return $handler->handle($request);
}
}
if (true === $this->validateKey(rawurldecode($apikey))) {
return $handler->handle($request);
}
return api_error('API key is incorrect.', Status::HTTP_FORBIDDEN, reason: 'API key is incorrect.');
return api_error('incorrect API key.', Status::FORBIDDEN);
}
/**
* @throws RandomException if random_bytes() fails
*/
private function validateKey(?string $token): bool
private function validate(?string $token): bool
{
if (empty($token)) {
if (empty($token) || !($storedKey = Config::get('api.key')) || empty($storedKey)) {
return false;
}
// -- we generate random key if not set, to prevent timing attacks or unauthorized access.
$storedKey = getValue(Config::get('api.key'));
if (empty($storedKey)) {
$storedKey = bin2hex(random_bytes(16));
}
return hash_equals(getValue($storedKey), $token);
return hash_equals($storedKey, $token);
}
private function parseAuthorization(string $header): null|string
private function parseTokens(iRequest $request): array
{
if (empty($header)) {
return null;
$tokens = [];
if (true === $request->hasHeader('x-' . self::KEY_NAME)) {
$tokens['header'] = $request->getHeaderLine('x-' . self::KEY_NAME);
}
$headerLower = strtolower(trim($header));
if (true === str_starts_with($headerLower, 'bearer')) {
return trim(substr($header, 6));
if (true === ag_exists($request->getQueryParams(), self::KEY_NAME)) {
$tokens['param'] = ag($request->getQueryParams(), self::KEY_NAME);
}
if (false === str_starts_with($headerLower, 'basic')) {
return null;
$auth = $request->getHeaderLine('Authorization');
if (!empty($auth)) {
[$type, $key] = explode(' ', $auth, 2);
if (true === in_array(strtolower($type), ['bearer', 'token'])) {
$tokens['auth'] = trim($key);
}
}
/** @phpstan-ignore-next-line */
if (false === ($decoded = base64_decode(substr($header, 6)))) {
return null;
}
if (false === str_contains($decoded, ':')) {
return null;
}
[, $password] = explode(':', $decoded, 2);
return empty($password) ? null : $password;
return array_map(fn($val) => rawurldecode($val), array_values(array_unique(array_filter($tokens))));
}
}

View File

@@ -125,7 +125,7 @@ class Response implements iResponse
* @param string|resource|iStream|null $body Stream identifier and/or actual stream resource
*/
public function __construct(
Status|int $status = Status::HTTP_OK,
Status|int $status = Status::OK,
array $headers = [],
mixed $body = null,
string $version = '1.1',

View File

@@ -65,7 +65,7 @@ final class ServeStatic
if (false === in_array($request->getMethod(), ['GET', 'HEAD', 'OPTIONS'])) {
throw new BadRequestException(
message: r("Method '{method}' is not allowed.", ['method' => $request->getMethod()]),
code: Status::HTTP_METHOD_NOT_ALLOWED->value
code: Status::METHOD_NOT_ALLOWED->value
);
}
@@ -99,7 +99,7 @@ final class ServeStatic
'looked' => $this->looked,
]
),
code: Status::HTTP_NOT_FOUND->value
code: Status::NOT_FOUND->value
);
}
$filePath = $checkIndex;
@@ -108,7 +108,7 @@ final class ServeStatic
if (false === ($realBasePath = realpath($this->staticPath))) {
throw new BadRequestException(
message: r("The static path '{path}' doesn't exists.", ['path' => $this->staticPath]),
code: Status::HTTP_SERVICE_UNAVAILABLE->value
code: Status::SERVICE_UNAVAILABLE->value
);
}
@@ -117,7 +117,7 @@ final class ServeStatic
if (false === $filePath || false === str_starts_with($filePath, $realBasePath)) {
throw new BadRequestException(
message: r("Request '{file}' is invalid.", ['file' => $requestPath]),
code: Status::HTTP_BAD_REQUEST->value
code: Status::BAD_REQUEST->value
);
}
@@ -132,7 +132,7 @@ final class ServeStatic
try {
$ifModifiedSince = makeDate($ifModifiedSince)->getTimestamp();
if ($ifModifiedSince >= $file->getMTime()) {
return new Response(Status::HTTP_NOT_MODIFIED->value, [
return new Response(Status::NOT_MODIFIED->value, [
'Last-Modified' => gmdate('D, d M Y H:i:s T', $file->getMTime())
]);
}
@@ -154,7 +154,7 @@ final class ServeStatic
$stream = Stream::make($file->getRealPath());
}
return new Response(Status::HTTP_OK->value, $headers, $stream);
return new Response(Status::OK->value, $headers, $stream);
}
/**

View File

@@ -391,7 +391,7 @@ if (!function_exists('api_response')) {
/**
* Create a API response.
*
* @param Status $status Optional. The HTTP status code. Default is {@see Status::HTTP_OK}.
* @param Status $status Optional. The HTTP status code. Default is {@see Status::OK}.
* @param array|null $body The JSON data to include in the response body.
* @param array $headers Optional. Additional headers to include in the response.
* @param string|null $reason Optional. The reason phrase to include in the response. Default is null.
@@ -399,7 +399,7 @@ if (!function_exists('api_response')) {
* @return iResponse A PSR-7 compatible response object.
*/
function api_response(
Status $status = Status::HTTP_OK,
Status $status = Status::OK,
array|null $body = null,
array $headers = [],
string|null $reason = null
@@ -430,7 +430,7 @@ if (!function_exists('api_error')) {
* Create a API error response.
*
* @param string $message The error message.
* @param Status $httpCode Optional. The HTTP status code. Default is {@see Status::HTTP_BAD_REQUEST}.
* @param Status $httpCode Optional. The HTTP status code. Default is {@see Status::BAD_REQUEST}.
* @param array $body Optional. Additional fields to include in the response body.
* @param array $opts Optional. Additional options.
*
@@ -438,7 +438,7 @@ if (!function_exists('api_error')) {
*/
function api_error(
string $message,
Status $httpCode = Status::HTTP_BAD_REQUEST,
Status $httpCode = Status::BAD_REQUEST,
array $body = [],
array $headers = [],
string|null $reason = null,
@@ -1433,7 +1433,7 @@ if (!function_exists('APIRequest')) {
)->withAttribute('INTERNAL_REQUEST', true)
);
$statusCode = Status::tryFrom($response->getStatusCode()) ?? Status::HTTP_SERVICE_UNAVAILABLE;
$statusCode = Status::tryFrom($response->getStatusCode()) ?? Status::SERVICE_UNAVAILABLE;
if ($response->getBody()->getSize() < 1) {
return new APIResponse($statusCode, $response->getHeaders());

View File

@@ -332,8 +332,8 @@ class HelpersTest extends TestCase
]
]);
$data = ['foo' => 'bar'];
$response = api_response(Status::HTTP_OK, $data);
$this->assertSame(Status::HTTP_OK->value, $response->getStatusCode());
$response = api_response(Status::OK, $data);
$this->assertSame(Status::OK->value, $response->getStatusCode());
$this->assertSame('application/json', $response->getHeaderLine('Content-Type'));
$this->assertSame(getAppVersion(), $response->getHeaderLine('X-Application-Version'));
$this->assertSame($data, json_decode($response->getBody()->getContents(), true));
@@ -353,9 +353,9 @@ class HelpersTest extends TestCase
]
]);
$data = ['error' => ['code' => Status::HTTP_BAD_REQUEST->value, 'message' => 'error message']];
$response = api_error('error message', Status::HTTP_BAD_REQUEST);
$this->assertSame(Status::HTTP_BAD_REQUEST->value, $response->getStatusCode());
$data = ['error' => ['code' => Status::BAD_REQUEST->value, 'message' => 'error message']];
$response = api_error('error message', Status::BAD_REQUEST);
$this->assertSame(Status::BAD_REQUEST->value, $response->getStatusCode());
$this->assertSame('application/json', $response->getHeaderLine('Content-Type'));
$this->assertSame(getAppVersion(), $response->getHeaderLine('X-Application-Version'));
$this->assertSame($data, json_decode($response->getBody()->getContents(), true));