Zmena textu HTTP status code 404, 500

Tomas8698
Člen | 109
+
0
-

Ahojte, momentálne riešim ako zadefinovať presný text, ktorý pri skúšaní neúspešného requestu vypíše v response. Zatiaľ som to nikdy neriešil a v docs som našiel:

$httpResponse->setCode(Nette\Http\Response::S404_NOT_FOUND);

Dá sa do tohto nadefinovať text alebo je to čisto len na priradenie HTTP codu?, nerozumiem tomu správne ako to funguje.

Za každú radu ďakujem.

Michal Kumžák
Člen | 106
+
0
-

Pokud chceš vlastní chybové stránky, tak mrkni sem https://doc.nette.org/cs/configuring#… na nastavení error presenteru. Pokud sis nette nainstaloval přes composer, tak tam výchozí nastavení i errorPresenter máš již předvytvořený.

Tomas8698
Člen | 109
+
0
-

Ja pripravujem JSON ktorý sa zavolá pri Get, Post alebo delete requests. Odošle odpoveď response, ak vyjde request tak to už mám spravené, chcel som sa spýtať či sa dajú zadefinovať aj Response ak nevyjde request aj je chyba 404,500

Polki
Člen | 553
+
0
-

@Tomas8698
No jasně. Upravíš si ErrorPresenter.

m.brecher
Generous Backer | 735
+
0
-

Ahoj,

pokud dojde v aplikaci k chybě, měla by se vypsat podrobná chybová hláška v debugovacím režimu a v produkčním režimu jenom nějaká obecná, aby se uživatelé nevyplašili a hacker to měl obtížnější.

Při chybě se vyhodí nějaká výjimka, která nějaký text chyby obsahuje a číselný kód 403, 404, .....

Výjimky jsou v zásadě dvojího typu:

  • generované samotnou aplikací, kde chybové hlášky píše programátor ($presenter->error(‚Něco se porouchalo…‘, 500)), nebo je vyhazuje framework, php apod…

Výjimky doporučuji kvalitně ošetřit neprůstřelně napsaným ErrorPresenterem, který současně vypíše i rozumné chybové hlášky. Protože důležitější než chybové hlášky je bezpečně výjimky ošetřit.

V sandboxu projektu Nette jsou dva error presentery a sice ErrorPresenter a Error4×xPresenter a návazné chybové šablony, které profesionálním způsobem ošetří výjimky v aplikaci. Tohle bych všude použil ;)

Tomas8698
Člen | 109
+
0
-

Ja sa ospravedlňujem asi som zle vysvetlil pracujem na webe, kde tvorím backendovu časť a pomocou JSON-nu predávam informácie Front-endu. Pri dobrom requeste odovzdá informácie pri zlom potrebujem aby som pri code 404 zadefinoval text, ktorý tam sa predá

Tomas8698
Člen | 109
+
0
-

Aha už to chápem, moja chyba ďakujem pekne 🙂

Polki
Člen | 553
+
0
-

m.brecher napsal(a):
($presenter->error(‚Něco se porouchalo…‘, 500))

Pozor. V Presenteru metoda Error vygeneruje Nette\Application\BadRequestException, která označuje 4XX chyby a kód chyby 500 je tady tedy neplatný.

Tomas8698 napsal(a):
Ja sa ospravedlňujem asi som zle vysvetlil pracujem na webe, kde tvorím backendovu časť a pomocou JSON-nu predávam informácie Front-endu. Pri dobrom requeste odovzdá informácie pri zlom potrebujem aby som pri code 404 zadefinoval text, ktorý tam sa predá

$this->getHttpResponse()->setCode(IResponse::S403_FORBIDDEN);
$this->sendJson([
	'status' => 'error',
	'data' => [
		'code' => IResponse::S403_FORBIDDEN,
		'message' => 'Nemáš oprávnění hihi.',
	]
]);
Tomas8698
Člen | 109
+
0
-

@Polki čiže ten kód bude v presenteri kde odosiela $data JSON že? Alebo to dat do errorPresen?

Polki
Člen | 553
+
0
-

@Tomas8698
To už záleží na tvojí implementaci.

Já bych to ale udělal tak, že by zmíněný kód byl v action metodě Error4×xPresenteru a v Error500Presenteru by bylo:

public function run(Nette\Application\Request $request): Nette\Application\Response
{
	$exception = $request->getParameter('exception');

	if ($exception instanceof Nette\Application\BadRequestException) {
		[$module, , $sep] = Nette\Application\Helpers::splitName($request->getPresenterName());
		return new Responses\ForwardResponse($request->setPresenterName($module . $sep . 'Error4xx'));
	}

	$this->logger->log($exception, ILogger::EXCEPTION);

	return new Responses\JsonResponse([
		'status' => 'error',
		'data' => [
			'code' => Http\IResponse::S500_INTERNAL_SERVER_ERROR,
			'message' => 'Error na straně serveru.',
		]
	]);
}

Samozřejmě, pokud používáš aplikaci ne jen jako API, ale máš tam zároveň i nějakou klasickou Nette aplikaci, tak je dobré celé API mít v modulu (například ApiModule), který bude mít vlastní Error presentery, aby se ti nestávalo, že když nastane chyba u uživatele, tak by místo krásné chybové stránky viděl JSON.

No a v klasickém Presenteru pak bude použití klasické:

public function actionEdit(int $id): void
{
	if (!$this->getHttpRequest()->isMethod($this->requestedMethod)) {
		$this->error('Bohužel tato metoda není povolená', IResponse::S405_METHOD_NOT_ALLOWED);
	}
	if (!$this->getUser()->isAllowed('Resource', 'Privilege')) {
		$this->error('Bohužel nemáte dostatečná oprávnění', IResponse::S401_UNAUTHORIZED);
	}

	throw new Exception(); // pro simulaci Error500
}

Ještě doplňuji Error4×xPresenter pro úplnost:

final class Error4xxPresenter extends Nette\Application\UI\Presenter
{
	public function startup(): void
	{
		parent::startup();
		if (!$this->getRequest()->isMethod(Nette\Application\Request::FORWARD)) {
			$this->error();
		}
	}

	public function actionDefault(Nette\Application\BadRequestException $exception): void
	{
		$this->getHttpResponse()->setCode($exception->getCode());
		$this->sendJson([
			'status' => 'error',
			'data' => [
				'code' => $exception->getCode(),
				'message' => $exception->getMessage(), // Nebo IDEÁLNĚ nějaká tvoje univerzální hláška
			]
		]);
	}
}

Editoval Polki (6. 10. 2021 16:24)

Marek Bartoš
Nette Blogger | 1165
+
-2
-

Status a code klíče jsou zbytečné. Kód je v http header a sám o sobě určuje, zda status je chybový nebo ne.

Polki
Člen | 553
+
0
-

@MarekBartoš
To máš pravdu, ale málokdy jsem se setkal s knihovnou, která ověřovala http kódy. Povětšinou se to právě řeší takto.
Moc jsem se nesetkal s lidmi, kteří třeba z CURL vytáhnou CURLinfo a řeší to tímto způsobem. Naopak jsem viděl na projektech spíše to, že se vzala návratová hodnota, s tou se pořítalo, že je v JSONu a obsahuje všechny potřebné informace.

Bohužel už jsem viděl i větší nadnárodní korporace, které jako odpověď posílají vždy HTTP status 200OK a popis chyby je detekovatelný až uvnitř vráceného JSONu/XMLka v property status.

Proto si myslím, že i když je to zbytečné, tak škodu to neudělá a dodávám to tam, aby s tím uměl pracovat každý.

Tomas8698
Člen | 109
+
+1
-

@Polki Dakujem pekne :) vyskusam to

Felix
Nette Core | 1186
+
+2
-

Take pridavam status field do odpovedi. Uz jen proto, ze nekdy si clovek nevystaci s HTTP status codem nebo nejde jednoduse urcit, jestli je to chyba nebo neni.

Tomas8698
Člen | 109
+
0
-

@Polki este sa chcem spýtať, trochu som zmeteni prvú časť kódu zadať do error500 a error 400 Presentera a potom aj 3tiu časť pridat do 400?
Myslím tu cast

1. Časť

public function run(Nette\Application\Request $request): Nette\Application\Response
{
	$exception = $request->getParameter('exception');

	if ($exception instanceof Nette\Application\BadRequestException) {
		[$module, , $sep] = Nette\Application\Helpers::splitName($request->getPresenterName());
		return new Responses\ForwardResponse($request->setPresenterName($module . $sep . 'Error4xx'));
	}

	$this->logger->log($exception, ILogger::EXCEPTION);

	return new Responses\JsonResponse([
		'status' => 'error',
		'data' => [
			'code' => Http\IResponse::S500_INTERNAL_SERVER_ERROR,
			'message' => 'Error na straně serveru.',
		]
	]);
}

3. Časť

final class Error4xxPresenter extends Nette\Application\UI\Presenter
{
	public function startup(): void
	{
		parent::startup();
		if (!$this->getRequest()->isMethod(Nette\Application\Request::FORWARD)) {
			$this->error();
		}
	}

	public function actionDefault(Nette\Application\BadRequestException $exception): void
	{
		$this->getHttpResponse()->setCode($exception->getCode());
		$this->sendJson([
			'status' => 'error',
			'data' => [
				'code' => $exception->getCode(),
				'message' => $exception->getMessage(), // Nebo IDEÁLNĚ nějaká tvoje univerzální hláška
			]
		]);
	}
}

Polki
Člen | 553
+
0
-

Takto má vypadat celý ErrorPresenter:

<?php

declare(strict_types=1);

namespace App\Presenters;

use Nette;
use Nette\Application\Responses;
use Nette\Http;
use Tracy\ILogger;

final class ErrorPresenter implements Nette\Application\IPresenter
{
	use Nette\SmartObject;

	/** @var ILogger */
	private $logger;

	public function __construct(ILogger $logger)
	{
		$this->logger = $logger;
	}

	public function run(Nette\Application\Request $request): Nette\Application\Response
	{
		$exception = $request->getParameter('exception');

		if ($exception instanceof Nette\Application\BadRequestException) {
			[$module, , $sep] = Nette\Application\Helpers::splitName($request->getPresenterName());
			return new Responses\ForwardResponse($request->setPresenterName($module . $sep . 'Error4xx'));
		}

		$this->logger->log($exception, ILogger::EXCEPTION);

		return new Responses\JsonResponse([
			'status' => 'error',
			'data' => [
				'code' => Http\IResponse::S500_INTERNAL_SERVER_ERROR,
				'message' => 'Error na straně serveru.',
			]
		]);
	}
}

A takto Error4×xPresenter:

<?php

declare(strict_types=1);

namespace App\Presenters;

use Nette;


final class Error4xxPresenter extends Nette\Application\UI\Presenter
{
	public function startup(): void
	{
		parent::startup();
		if (!$this->getRequest()->isMethod(Nette\Application\Request::FORWARD)) {
			$this->error();
		}
	}


	public function actionDefault(Nette\Application\BadRequestException $exception): void
	{
		$this->getHttpResponse()->setCode($exception->getCode());
		$this->sendJson([
			'status' => 'error',
			'data' => [
				'code' => $exception->getCode(),
				'message' => $exception->getMessage(), // Nebo IDEÁLNĚ nějaká tvoje univerzální hláška
			]
		]);
	}
}

Ale prosím důležité je, aby si jen bezhlavě nekopíroval, ale aby jsi kódu porozuměl. Projdi si to vůči originálu, najdi si rozdíly a popřemýšlej o tom, proč jsou rozdíly takovéto a co to znamená, případně se ještě zeptej, pokud tě déle jak 10 minut nic nenapadne.