Ublaboo\api-router a ošetření výjimek

forkman
Člen | 72
+
0
-

Ahoj, api-router jako takový mi funguje, ale potřeboval bych mít ošetřené i výjimky (hlavně BadRequest) a posílat je taky jako JSON a ne jako klasický HTML error. Nedokážu toho ale docílit.

Nette moc neovládám a nedokážu ErrorPresenter v API modulu donutit, aby posílal JSON response. Vždycky dostanu jen klasický Error500 a logu je Nette\Application\AbortException, který následuje po JsonResponse. Použil jsem kód ErrorPresenteru, který je v ukázkovém projektu na Githubu.

<?php

declare(strict_types=1);

namespace ResourcesModule;

use App\Http\ApiResponse;
use Nette\Application\IResponse;
use Nette\Application\Request;

final class Error4xxPresenter extends AbstractController
{
	public function run(Request $request): IResponse
	{
		$exception = $request->getParameter('exception');
		/**
		 * @todo Log exception
		 */

		return $this->sendJson($this->apiResponseFormatter->formatException($exception));
	}
}

Nemáte někdo tip jak na to?

Pavel Janda
Člen | 977
+
0
-

Jsi si jistý, že se ti tento presenter spouští? V závislosti na tom potom můžeme hledat dál 👍

forkman
Člen | 72
+
0
-

Ano, jsem si jistý, že se ten presenter spouští (dal jsem si tam echo :-D ). Ale taky se přiznám, že přesně nevím, co dělá. Předpokládal jsem, že když vyhodím výjimku, zejména BadRequest, kterou neošetřím, chytí ji ErrorPresenter a pošle JSON response se správným obsahem a hlavičkou. Můžu si to výjimku samozřejmě ošetřit a poslat si tam ten JSON response sám, ale pak mám samozřejmě HTTP status 200 a to já nechci.

Pavel Janda
Člen | 977
+
0
-

@forkman Nevím, jak přesně vypadá tvá appka, ale můžeš si například v nějakém předkovi svých presenterů přepsat metodu sendJson tak, aby posílal tvůj vlastní JsonResponse, která bude umět posílat i status kód. Příklad:
Místo:

class UI\Presenter
	public function sendJson($data): void
	{
		$this->sendResponse(new Responses\JsonResponse($data));
	}

->

abstract class ApiPresenter
	public function sendJson($data, int $code): void
	{
		$this->sendResponse(new ApiJsonResponse($data, null, $code));
	}

final class ApiJsonResponse
	public function __construct(private $payload, private string $contentType = null, private int $code = 200)

	public function send(IRequest $httpRequest, IResponse $httpResponse): void
	{
		$httpResponse->setContentType($this->contentType, 'utf-8');
		$httpResponse->setCode($this->code);
		echo Json::encode($this->payload);
	}

Editoval Pavel Janda (3. 11. 2020 14:51)