Search code examples
jsonexceptionsymfonyfosrestbundle

Set FOSRestBundle Exception _format


I am using FOSRestBundle in my Symfony 2.3 project.

I am not able to set _format for response exceptions. In my config.yml I have:

twig:
    exception_controller: 'FOS\RestBundle\Controller\ExceptionController::showAction'

Default return is HTML format, but is it possible to set _format = json to return exceptions?

I have more than one bundle, but only one is RestBundle, so other bundles need to set in normal way.


Solution

  • You can write your routes manually and set _format there like this:

    acme_demo.api.user:
        type: rest
        pattern: /user/{username_canonical}.{_format}
        defaults: { _controller: 'AcmeDemoBundle:User:getUser', username_canonical: null, _format: json }
        requirements:
            _method: GET
    

    Edit: Or you can write your own exception handler and do with exceptions whatever you need to do:

    // src/Acme/DemoBundle/EventListener/AcmeExceptionListener.php
    namespace Acme\DemoBundle\EventListener;
    
    use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
    use Symfony\Component\HttpFoundation\JsonResponse;
    use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
    
    class AcmeExceptionListener
    {
        public function onKernelException(GetResponseForExceptionEvent $event)
        {
            // do whatever tests you need - in this example I filter by path prefix
            $path = $event->getRequest()->getRequestUri();
            if (strpos($path, '/api/') === 0) {
                return;
            }
    
            $exception = $event->getException();
            $response = new JsonResponse($exception, 500);
    
            // HttpExceptionInterface is a special type of exception that
            // holds status code and header details
            if ($exception instanceof HttpExceptionInterface) {
                $response->setStatusCode($exception->getStatusCode());
                $response->headers->replace($exception->getHeaders());
            }
    
            // Send the modified response object to the event
            $event->setResponse($response);
        }
    }
    

    And register it as a listener:

    # app/config/config.yml
    services:
        kernel.listener.your_listener_name:
            class: Acme\DemoBundle\EventListener\AcmeExceptionListener
            tags:
                - { name: kernel.event_listener, event: kernel.exception, method: onKernelException }
    

    How to create an Event Listener