Zmena textu HTTP status code 404, 500
- Tomas8698
- Člen | 109
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
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ý.
- m.brecher
- Generous Backer | 873
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 Error4xxPresenter a návazné chybové šablony, které profesionálním způsobem ošetří výjimky v aplikaci. Tohle bych všude použil ;)
- Polki
- Člen | 553
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.',
]
]);
- Polki
- Člen | 553
@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ě Error4xxPresenteru 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 Error4xxPresenter 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 | 1280
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
@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
@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
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 Error4xxPresenter:
<?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.