bug #17744 Improve error reporting in router panel of web profiler (javiereguiluz)
This PR was squashed before being merged into the 2.7 branch (closes #17744).
Discussion
----------
Improve error reporting in router panel of web profiler
| Q | A
| ------------- | ---
| Bug fix? | yes
| New feature? | no
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | #17342
| License | MIT
| Doc PR | -
### Problem
If you define a route condition like this:
```yaml
app:
resource: '@AppBundle/Controller/'
type: annotation
condition: "request.server.get('HTTP_HOST') matches '/.*\.dev/'"
```
When browsing the Routing panel in the web profiler, you see an exception:
![problem](https://cloud.githubusercontent.com/assets/73419/12930027/553eeb08-cf76-11e5-90b1-ab0de6175d4e.png)
#### Why?
Because the route condition uses the `request` object, but the special `TraceableUrlMatcher` class doesn't get access to the real `request` object but to the special object obtained via:
```php
$request = $profile->getCollector('request');
```
These are the contents of this pseudo-request:
![cause](https://cloud.githubusercontent.com/assets/73419/12930052/804ea248-cf76-11e5-9c38-2e43e1654065.png)
`request.server.get(...)` condition fails because `request.server` is `null`. The full exception message shows this:
![exception](https://cloud.githubusercontent.com/assets/73419/12930079/9c7d6058-cf76-11e5-8eeb-45f5059c824c.png)
### Solution
I propose to catch all exceptions in `TraceableUrlMatcher` and display an error message with some details of the exception:
![error_message](https://cloud.githubusercontent.com/assets/73419/12930106/b29e31d2-cf76-11e5-868c-98d8b0cc4e5b.png)
Commits
-------
1001554
Improve error reporting in router panel of web profiler
This commit is contained in:
commit
9d58ad92fe
@ -18,6 +18,7 @@ use Symfony\Component\Routing\RouteCollection;
|
|||||||
use Symfony\Component\Routing\RouterInterface;
|
use Symfony\Component\Routing\RouterInterface;
|
||||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
use Symfony\Component\HttpKernel\Profiler\Profiler;
|
use Symfony\Component\HttpKernel\Profiler\Profiler;
|
||||||
|
use Symfony\Component\HttpKernel\DataCollector\RequestDataCollector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RouterController.
|
* RouterController.
|
||||||
@ -62,16 +63,39 @@ class RouterController
|
|||||||
|
|
||||||
$profile = $this->profiler->loadProfile($token);
|
$profile = $this->profiler->loadProfile($token);
|
||||||
|
|
||||||
$context = $this->matcher->getContext();
|
/** @var RequestDataCollector $request */
|
||||||
$context->setMethod($profile->getMethod());
|
|
||||||
$matcher = new TraceableUrlMatcher($this->routes, $context);
|
|
||||||
|
|
||||||
$request = $profile->getCollector('request');
|
$request = $profile->getCollector('request');
|
||||||
|
|
||||||
return new Response($this->twig->render('@WebProfiler/Router/panel.html.twig', array(
|
return new Response($this->twig->render('@WebProfiler/Router/panel.html.twig', array(
|
||||||
'request' => $request,
|
'request' => $request,
|
||||||
'router' => $profile->getCollector('router'),
|
'router' => $profile->getCollector('router'),
|
||||||
'traces' => $matcher->getTraces($request->getPathInfo()),
|
'traces' => $this->getTraces($request, $profile->getMethod()),
|
||||||
)), 200, array('Content-Type' => 'text/html'));
|
)), 200, array('Content-Type' => 'text/html'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the routing traces associated to the given request.
|
||||||
|
*
|
||||||
|
* @param RequestDataCollector $request
|
||||||
|
* @param string $method
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function getTraces(RequestDataCollector $request, $method)
|
||||||
|
{
|
||||||
|
$traceRequest = Request::create(
|
||||||
|
$request->getPathInfo(),
|
||||||
|
$request->getRequestServer()->get('REQUEST_METHOD'),
|
||||||
|
$request->getRequestAttributes()->all(),
|
||||||
|
$request->getRequestCookies()->all(),
|
||||||
|
array(),
|
||||||
|
$request->getRequestServer()->all()
|
||||||
|
);
|
||||||
|
|
||||||
|
$context = $this->matcher->getContext();
|
||||||
|
$context->setMethod($method);
|
||||||
|
$matcher = new TraceableUrlMatcher($this->routes, $context);
|
||||||
|
|
||||||
|
return $matcher->getTracesForRequest($traceRequest);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Routing\Matcher;
|
namespace Symfony\Component\Routing\Matcher;
|
||||||
|
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\Routing\Exception\ExceptionInterface;
|
use Symfony\Component\Routing\Exception\ExceptionInterface;
|
||||||
use Symfony\Component\Routing\Route;
|
use Symfony\Component\Routing\Route;
|
||||||
use Symfony\Component\Routing\RouteCollection;
|
use Symfony\Component\Routing\RouteCollection;
|
||||||
@ -40,6 +41,15 @@ class TraceableUrlMatcher extends UrlMatcher
|
|||||||
return $this->traces;
|
return $this->traces;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getTracesForRequest(Request $request)
|
||||||
|
{
|
||||||
|
$this->request = $request;
|
||||||
|
$traces = $this->getTraces($request->getPathInfo());
|
||||||
|
$this->request = null;
|
||||||
|
|
||||||
|
return $traces;
|
||||||
|
}
|
||||||
|
|
||||||
protected function matchCollection($pathinfo, RouteCollection $routes)
|
protected function matchCollection($pathinfo, RouteCollection $routes)
|
||||||
{
|
{
|
||||||
foreach ($routes as $name => $route) {
|
foreach ($routes as $name => $route) {
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Routing\Tests\Matcher;
|
namespace Symfony\Component\Routing\Tests\Matcher;
|
||||||
|
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\Routing\Route;
|
use Symfony\Component\Routing\Route;
|
||||||
use Symfony\Component\Routing\RouteCollection;
|
use Symfony\Component\Routing\RouteCollection;
|
||||||
use Symfony\Component\Routing\RequestContext;
|
use Symfony\Component\Routing\RequestContext;
|
||||||
@ -98,4 +99,23 @@ class TraceableUrlMatcherTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
return $levels;
|
return $levels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testRoutesWithConditions()
|
||||||
|
{
|
||||||
|
$routes = new RouteCollection();
|
||||||
|
$routes->add('foo', new Route('/foo', array(), array(), array(), 'baz', array(), array(), "request.headers.get('User-Agent') matches '/firefox/i'"));
|
||||||
|
|
||||||
|
$context = new RequestContext();
|
||||||
|
$context->setHost('baz');
|
||||||
|
|
||||||
|
$matcher = new TraceableUrlMatcher($routes, $context);
|
||||||
|
|
||||||
|
$notMatchingRequest = Request::create('/foo', 'GET');
|
||||||
|
$traces = $matcher->getTracesForRequest($notMatchingRequest);
|
||||||
|
$this->assertEquals("Condition \"request.headers.get('User-Agent') matches '/firefox/i'\" does not evaluate to \"true\"", $traces[0]['log']);
|
||||||
|
|
||||||
|
$matchingRequest = Request::create('/foo', 'GET', array(), array(), array(), array('HTTP_USER_AGENT' => 'Firefox'));
|
||||||
|
$traces = $matcher->getTracesForRequest($matchingRequest);
|
||||||
|
$this->assertEquals('Route matches!', $traces[0]['log']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user