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

試著忘記壹切 提交于 2019-12-02 21:57:16

Since Symfony 2.4, the profiler sets two additional settings in the HTTP header: X-Debug-Token and X-Debug-Token-Link. (see http://symfony.com/blog/new-in-symfony-2-4-quicker-access-to-the-profiler-when-working-on-an-api)

These headers contain the token and the direct link to the profiler for the current request. They are always sent if the profiler is enabled.

Not surprisingly, there is already an extension available for Chrome, that checks for the existence of these headers and provide extra information: Symfony2 Profiler shortcut

In my opinion, this is better than any custom html-wrapper, but this only works for GET and maybe POST requests - PUT and DELETE requests are a bit trickier. There you can use a http client, like the chrome-extension POSTMAN and open the profiler manually by opening the link provided in the http-header X-Debug-Token-Link or keep your profiler-page (f.e. http://example.org/_profiler/) opened.

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 }

I am using Chrome Extension and pretty helpful during API development if you don't want to use Event Listener (It didn't work for me): https://chrome.google.com/webstore/detail/symfony2-profiler-shortcu/denlhphadllhcolhlbbbjmhkgbknmmon

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 oute matching, DB queries involved, etc.

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!