'How to display the symfony profiler for API request made in the browser?

I'm developing a REST api with Symfony2 + FOSRest bundle.

I would like to know if there is any way for a call to the api in dev mode (app_dev.php) from the browser (corresponding to a Accept: text/html,application/xhtml+xml header) to display the response in the "specified format", wrapped in html with the profiler provided by symfony.

It would allow to debug calls to the api directly in the browser.


Edit: I don't want to debug the HTTP request but the whole process (route matching, DB queries involved, etc). That's why I want to have access to the symfony profiler.



Solution 1:[1]

The reason the WebDebugToolbar isn't displayed when developing a JSON or XML API is that the toolbar is set to only be injected into HTML-type responses.

To overcome this you could add a kernel.response Event Listener in your Bundle which converts your JSON or XML responses into HTML.

namespace Acme\APIBundle\Event\Listener;

use Symfony\Component\HttpKernel\Event\FilterResponseEvent;

class ConvertToHtmlResponse {
  public function onKernelResponse(FilterResponseEvent $event) {
    if (!$event->isMasterRequest()) {
      return;
    }

    $request = $event->getRequest();

    // Only send back HTML if the requestor allows it
    if (!$request->headers->has('Accept') || (false === strpos($request->headers->get('Accept'), 'text/html'))) {
      return;
    }

    $response = $event->getResponse();
    switch ($request->getRequestFormat()) {
      case 'json':
        $prettyprint_lang = 'js';
        $content = json_encode(json_decode($response->getContent()), JSON_PRETTY_PRINT);
        break;

      case 'xml':
        $prettyprint_lang = 'xml';
        $content = $response->getContent();
        break;

      default:
        return;
    }

    $response->setContent(
      '<html><body>' .
      '<pre class="prettyprint lang-' . $prettyprint_lang . '">' .
      htmlspecialchars($content) .
      '</pre>' .
      '<script src="https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/run_prettify.min.js"></script>' .
      '</body></html>'
    );

    // Set the request type to HTML
    $response->headers->set('Content-Type', 'text/html; charset=UTF-8');
    $request->setRequestFormat('html');

    // Overwrite the original response
    $event->setResponse($response);
  }
}

Then you just need to register the listener inside your bundle to the kernel.response event, which I suggest you do only in the dev environment config.

services:
  # ...
  acme.listener.kernel.convert_html:
    class: Acme\APIBundle\Event\Listener\ConvertToHtmlResponse
    tags:
      - { name: kernel.event_listener, event: kernel.response }

Solution 2:[2]

You can just open a seperate browser and browse to .../app_dev.php/_profiler/ there you will find all your requests done to app_dev.php including route matching, DB queries involved, etc.

Solution 3:[3]

With the FOSRestBundle, I use a special template to display the data in an html page, therefore with the debug toolbar.

In my controller with annotations (you also use corresponding methods):

@View(template="AppBundle:Api:data.html.twig", templateVar="data")

And in the template, choosing whatever format you fancy:

<body>
    <pre>{{ data | serialize('json') }}</pre>
</body>

It is obviously a quick&dirty solution, but does the job. It also limits the ability to display actual html pages on those routes.

Solution 4:[4]

I use my WithProfilerTrait which applies the toolbar only if you navigate to the URL in the browser and skips the change, if it's an ajax request.

// in Controller:
return $this->withProfiler($response, $request->isXmlHttpRequest());
trait WithProfilerTrait
{
    protected function withProfiler(Response $response, bool $skip = false): Response
    {
        if ($skip === true) {
            return $response;
        }

        $wrappedContent = '<body><pre>' . $response->getContent() . '</pre></body>';
        $response->headers->set('Content-Type', 'html');
        return $response->setContent($wrappedContent);
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 gou1
Solution 4 auipga