Is possible in symfony 3 to generate exception without internal server error?
I want do something action with this exception (add to databases) but do not stop execute application.
I assume what you want to do is not simply catch an exception, but handle (in your case: log) an uncatched exception.
This is a common scenario and is therefore explained in the cookbook. Basically, you create an event listener class which you register as a service for the “kernel.event_listener” event.
I was struggling with this as well because I was generating custom built exceptions, but no matter what I did Symfony would return an http status of 500. I was handling errors in a controlled fashion, and just needed to notify the user, which was more of a status 200 response since it was a message to the user.
Anyways I found that this didn't work:
$event->setResponse(new Response(json_encode($returnArray), 200));
But if I added a header it works, Symfony looks for this header later and respects it. Without the header Symfony just assigns a 500 if you use an /Exception instead of an /HttpException
$event->setResponse(new Response(json_encode($returnArray), 200, array('X-Status-Code' => 200)));
I'm still new to this exception thing, so let me know if something I'm doing is wrong, but that header fixed my problems.
Related
In order for Google Cloud Tasks to automatically be re-queued I need my Laravel 7 app to return a 500 error, but everything short of a call to abort() seems to want to return a 200. I know that this ought to work:
return response('No dice son, you gotta work-a late.', 500);
...but no, the task still receives 200 and thus it's deleted from the queue as though it had succeeded.
The reason I'd prefer to avoid abort('Fall down go boom') is that it also raises an exception in Stackdriver, and that's unnecessary since I'm returning this particular error when a third party's API fails to provide data. In the event of errors on my side I'm killing the job outright.
The flow of my code is that I raise a custom exception when the third-party API returns null, then catch that exception and in the handler I call another method that does the work of cleaning up the job, which is when I intended to return 500... though right now I'm calling abort('No worky').
Is there some minutia in the docs that I managed to overlook?
In order to send HTTP 500, this usually would be:
return abort(500, 'Internal Server Error');
And the method usally doesn't matter, as it is just a helper, which returns Response.
Changing the error message does not chenge the fact that it's an intenral server error - and when returning 500, it is probably normal to have it logged as an error.
I am using latest version laravel(5.6)
Now in my code whenever an exception occurs laravel treating it as a fatal error, stop executing instantly and displaying the error message in some template.
But I don't want that, I want to handle exceptions and display some custom error messages
I found some ways like
changing the APP_DEBUG value in the .env file to false. But this also displays another
page with the message "whoops!some this want wrong";
In Handler.php which is in app/Exceptions, I had put some exceptions in not report zone. But the app is still reporting them
Custom HTTP Error Pages
Laravel makes it easy to display custom error pages for various HTTP
status codes. For example, if you wish to customize the error page for
404 HTTP status codes, create a resources/views/errors/404.blade.php.
This file will be served on all 404 errors generated by your
application. The views within this directory should be named to match
the HTTP status code they correspond to. The HttpException instance
raised by the abort function will be passed to the view as an
$exception variable.
https://laravel.com/docs/5.6/errors#custom-http-error-pages
Really you want to be handling your exceptions. Wrap the code in a try catch and you can do all manner of things (e.g. email / slack / log). Once you have handled the exception you can still use custom http error pages inside the catch so the end user get's a friendly message on a nicely designed page. There is even a report helper built in to allow you to externally log and continue on processing the code.
#Devon's above answer re: Custom HTTP Error Pages gets you exactly what you want also.
Please note few important points :
The App\Exceptions\Handler class is where all exceptions triggered by your application are logged and then rendered back to the user. This class has two method report() and render(), both has their own responsibility.
The report method is used to log exceptions. By default, the report method passes the exception to the base class where the exception is logged. However, you are free to log exceptions however you wish. For example, if you need to report different types of exceptions in different ways, you may use the PHP instanceof comparison operator
The render method is responsible for converting a given exception into an HTTP response that should be sent back to the browser. By default, the exception is passed to the base class which generates a response for you. However, you are free to check the exception type or return your own custom response.
As in your case you want to return custom message for exception, inside render() you may use the PHP instanceof comparison operator and return you own logic.
Example :
if($exception instanceof PostTooLargeException || $exception instanceof FileException){
return response()->json([
'error' => true,
'error_message' => "The file you are trying to upload exceeds the maximum limit. Please try to upload a smaller file."
],200);
}
Go through https://laravel.com/docs/5.6/errors for more datails
I haven't uset custom exceptions before, and now it appears that I might need them but I'm not sure I understood correctly how are they supposed to be used.
Say I have a custom exception like this:
class not_found_exception extends exception{ }
Then I have a bunch of request handler functions (I think they are called controllers in the wild). And each function can throw different types of exceptions. If the URL doesn't match it throws my custom exception, the script will catch that type of exception and skip to next request handler if it's caught. But other types of exception are not supposed to be caught because they mean that the url matches but there's some other error that should be displayed.
The thing is that my custom exception doesn't need an error message because it would not show up anywhere because its supposed to be caught, but other exceptions do. So is it ok to just throw an empty not_found_exception exception?
The short answer is simply: yes. That would be ok.
For further information about best-practices regarding Exception I'll refer you to this blog. It may be written for .NET but the theories can still be applied to PHP.
https://blogs.msdn.microsoft.com/kcwalina/2007/01/30/how-to-design-exception-hierarchies/
I have two problems:
(1.)I want to know that what is the best way to show Error Messages in REST API.
Should I throw Exceptions or
should I use VIEW to show error messages with status code etc. details.
I am using FOSRestBundle to handle rest related tasks.
I am sending API Usage data in each response(without asked by API consumer).
(2.) If I use exception how to add my custom data to in headers with error message.
With RESTful APIs, you always use HTTP codes to provide meaningful messages to the client.
To do this, you use a Response object to send a variety of HTTP codes. Symfony provides a few Exception handling scenarios which will result in 403, 404, or 500 errors, but not as extensive as this list. All exceptions will do is throw the same HTTP codes that you could achieve manually, albeit with more meaningful internal debugging errors in the development environment but with less control.
To send a meaningful HTTP error code (such as an object being successfully created):
use Symfony\Component\HttpFoundation\Response;
$response = new Response(
'A custom message or an XML/JSON/anything object',
Response::HTTP_CREATED,
array('content-type' => 'text/html')
// Can also be application/json or application/xml .. list goes on
);
but since you're using the FOSRestBundle already, you should be reading the documentation about the view layer and how to use it instead. The view layer will already handle these HTTP codes for you and provide responses in multiple formats just like a RESTful interface should.
As you can see here you can add a listener for kernel exceptions.
Inside that listener you can define the headers and status code of the response, like that:
$response = new Response();
$response->setContent($message);
$response->setStatusCode("YOUR_STATUS_CODE");
$response->headers->replace("YOUR_CUSTOM_HEADERS");
// Send the modified response object to the event
$event->setResponse($response);
Personally I prefer throwing exceptions, but try to make them as specific as it gets. This way the consumer of the API is able to handle different types of exceptions.
Nonetheless if a generic exception is thrown (means that something has gone horribly wrong), you can still return a properly formatted response and the consumer will be able to also handle failure
I had the same question and issue. Searching for the answer led me to this question. I eventually managed to get it working and I posted an answer to a similar question (the code in the question is very helpful too) here:
FOSRestBundle configuration of exceptions messages in prod environment
This documentation was also helpful, although not very clear I thought: https://symfony.com/doc/current/bundles/FOSRestBundle/4-exception-controller-support.html
I'm trying to add my custom pages. I'm using Kohana 3.3. The official documentation states that I should ovveride the method hander of native Kohana_Exception class. This is pretty easy to do so I've done that. Now I'm expecting that Kohana would call that method every time an exception or an error occurs. But this is not the case. I've found 2 catch blocks where an exception is caught inside execute_request method of Kohana_Request_Client_Internal class.
First catch
catch (HTTP_Exception $e)
{
// Get the response via the Exception
$response = $e->get_response();
}
Second catch
catch (Exception $e)
{
// Generate an appropriate Response object
$response = Kohana_Exception::_handler($e);
}
As you can see, none of the catch blocks calls handler method overriden by me.
Setting your own exception handler set_exception_handler has no effect since it is applied only to uncaught exceptions and the exceptions like 404 are thrown and caught.
No problems with run-time errors though. This block catches them and explicitly calls overriden handler method.
if (Kohana::$errors AND $error = error_get_last() AND in_array($error['type'],
Kohana::$shutdown_errors))
{
// Clean the output buffer
ob_get_level() AND ob_clean();
// Fake an exception for nice debugging
Kohana_Exception::handler(new ErrorException($error['message'], $error['type'], 0, $error['file'], $error['line']));
// Shutdown now to avoid a "death loop"
exit(1);
}
So my question how do I set up everything to have custom error page for Exception and HTTP_Exception?
PS. I can ovveride HTTP_Exception_404 and HTTP_Exception_500 to have my custom error page displayed, but I don't think that's the best option since it could work for these two, but overriding all possible HTTP_Exceptions is not a good way to go.
PS2. Or I can set my custom view in bootstrap.php:
Kohana_Exception::$error_view = 'custom_error.tpl';
Also don't like that solution.
All links to Kohana's documentation in this post are for version 3.3
You won't get what you want by overwriting just one method. Below I explain the methods that you can overwrite in order to achieve what you want. Just make just sure you put the right code in the right method.
Don't try to do everything in one place. While it will be all in one place is will most likely become a mess.
Kohana_Exception::handler()
Kohana_Exception::handler() is for when exceptions reach the exception handler or like you showed, in the shutdown handler. The last chance you have to display a nice error page in production environments. It outputs the result of Kohana_exception::_handler(), which is a Response object, and is therefor not suited to be called inside Request_Client_Internal::execute_response().
For production: Log the original exception. Since this scenario matches the description of HTTP Status Code 500 (Internal Server Error) Kohana_Exception::handler() should display a 500 error page.
During development you probably want to call parent::handler().
Kohana_Exception::_handler()
Kohana_Exception::_handler() return a Response object, so it is suited to be called in Request_Client_External::execute_response(), Kohana_Exception::handler() and View::__toString().
HTTP_Exception::get_response()
HTTP_Exception::get_response() will get called for exceptions extending HTTP_Exception, with the exception of exceptions extending HTTP_Exception_Expected. A few examples of exceptions extending HTTP_Expected_Exception are the 3xx and 401 HTTP_Exceptions.
By default it returns Kohana_Exception::response().
Overwrite it in specific exceptions to return specific responses for said exception.
Overwrite it in HTTP_Exception when you want the replace the default response.
Kohana_Exception::response()
Kohana_Exception::response() is responsible for collecting the data needed to render the Kohana_Exception::$error_view template. An example of output can be seen on the kohana/errors page of the userguide.
Change Kohana_Exception::$error_view when you want a different layout for the same data.
Overwrite Kohana_Exception::response() to replace the entire thing.
PS. Kevin pointed you to the 3.2 documentation. How to do this is very different for 3.2 and 3.3.