Skip to content

[HttpKernel] Catch HttpExceptions when templating is not installed #26138

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 29, 2018
Merged

[HttpKernel] Catch HttpExceptions when templating is not installed #26138

merged 1 commit into from
Apr 29, 2018

Conversation

junowilderness
Copy link
Contributor

@junowilderness junowilderness commented Feb 11, 2018

Q A
Branch? 3.4
Bug fix? yes
New feature? no
BC breaks? ?
Deprecations? no
Tests pass? ?
Fixed tickets #25844
License MIT
Doc PR symfony/symfony-docs#...
  • Test manually
  • Check for BC breaks
  • Needs tests


public function onKernelException(GetResponseForExceptionEvent $event)
{
if ($this->container->has('twig')) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead we could remove the service definition within a compiler pass? So it would have zero runtime overhead if twig is available

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dmaicher Thank you for reviewing. Yes, that's a good idea. Do you feel TwigBundle or HttpKernel should have that compiler pass logic? I think TwigBundle but I'd like to hear your opinion.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would create the compiler pass inside HttpKernel and use it accordingly in the FrameworkBundle like done for example here: https://github.com/symfony/symfony/blob/master/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php#L31

@@ -36,5 +36,9 @@ public function process(ContainerBuilder $container)
$container->removeDefinition('twig.exception_listener');
}
}

if ($container->hasDefinition('twig.exception_listener')) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dmaicher What do you think of putting the responsibility in the existing TwigBundle compiler pass?

@junowilderness
Copy link
Contributor Author

I don't understand enough about SF tests to know why tests are failing.

@nicolas-grekas
Copy link
Member

I'd like to propose an alternative, see #26928.

@junowilderness
Copy link
Contributor Author

#26928 is simpler.

@nicolas-grekas
Copy link
Member

Reopening as discussed in #26928

@@ -67,6 +67,12 @@
<argument type="service" id="router" on-invalid="ignore" />
</service>

<service id="http_exception_listener" class="Symfony\Component\HttpKernel\EventListener\HttpExceptionListener">
<tag name="kernel.event_subscriber" />
<argument type="service" id="service_container" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the argument is never used, it should be removed

<service id="http_exception_listener" class="Symfony\Component\HttpKernel\EventListener\HttpExceptionListener">
<tag name="kernel.event_subscriber" />
<argument type="service" id="service_container" />
<argument>%kernel.debug%</argument>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not make this depend on the debug parameter, let's remove it.

@@ -36,5 +36,9 @@ public function process(ContainerBuilder $container)
$container->removeDefinition('twig.exception_listener');
}
}

if ($container->hasDefinition('twig.exception_listener')) {
$container->removeDefinition('http_exception_listener');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest to not conditionally unregister the listener, let it be, that's not a measurable overhead anyway

protected $container;
protected $debug;

public function __construct(ContainerInterface $container, $debug = false)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can be removed (alongside with properties) since we're not gonna use it


public function onKernelException(GetResponseForExceptionEvent $event)
{
if (!$this->debug) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest an alternative logic in the method:
when the event already contains a response, this listener should just do nothing.
otherwise and if possible, it would be great if creating the response could be delegated to then ExceptionHandler (the Debug component is already a required dependency)

Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(see previous review)

@nicolas-grekas nicolas-grekas changed the title Fix bug #25844 [HttpKernel] Catch HttpExceptions without templating installed [HttpKernel] Catch HttpExceptions when templating is not installed Apr 23, 2018
@nicolas-grekas
Copy link
Member

@cilefen up to finish this one? Otherwise no pb, please advise and we'll take over.

@junowilderness
Copy link
Contributor Author

I will look look at it today.

$flattenException = FlattenException::create($event->getException());
$handler = new ExceptionHandler(false);
$response = new Response($handler->getContent($flattenException));
$event->setResponse($response);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nicolas-grekas This does not actually work as expected in the dev environment. In fact I do no understand how to detect the environment without injecting it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nicolas-grekas ... and indeed I may be way "off the mark" in terms of what you wrote about delegating to the ExceptionHandler.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I was wrong, kernel.debug may be required to populate the first argument of ExceptionHandler's constructor.
About the implementation, I suggest to borrow from ExceptionHandler::sendPhpResponse()

Copy link
Contributor

@dmaicher dmaicher Apr 23, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nicolas-grekas hmm but should this new listener really stream/echo the response to the client directly? I think it should just set the response on the event and nothing else?

Edit: I mean its just this line? https://github.com/symfony/symfony/pull/26928/files#diff-3d3b8968ae2d94a9aab7078dec41e607R228

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not call sendPhpResponse but take inspiration from it. Eg header management is missing right now .

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ok got it 👍 yes makes sense to use HttpExceptionInterface::getHeaders() also


public function onKernelException(GetResponseForExceptionEvent $event)
{
if ($event->hasResponse()) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also I am not sure if this evaluates to true often in the production environment without twig installed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should evaluate to false unless one handled the exception, either via twigbundle or any other mean, isn't it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nicolas-grekas The issue at hand is that (I think) there is never a response on $event when twig is not installed. But as I think you mentioned above we need to also check if the environment is debug (in which case the twig debug handler should activate). Does that make sense?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should forget about Twig here, it's totally independent code. What matters is if there is a listener that already set a response, and if not, then generate one. This question doesn't need to wonder about debug or not.
There are ppl that do set responses here, while not using twig (eg for APIs.)

@nicolas-grekas
Copy link
Member

@dmaicher I'm wondering: the approach with the global exception handler I proposed in the front controller is also able to deal with fatal errors.
What does the approach in this PR has that's making it better?
That's an honest question :)

@dmaicher
Copy link
Contributor

@nicolas-grekas sure let's discuss it 😊

What does the approach in this PR has that's making it better?

  • In my opinion the front controller should be a really lightweight "wrapper" around the kernel and just send the response to the client that has been returned by the kernel
  • if using WebTestCase on some API project (no custom exception listeners, no TwigBundle) you want to assert 404 responses for example: How to do it when that logic is in the front-controller?
  • people have to update their front controllers to benefit from this feature? 😃

is also able to deal with fatal errors.

Currently I'm using Symfony\Component\Debug\ErrorHandler::register(); for that in my front controllers so that they are turned into exceptions 😋

@nicolas-grekas
Copy link
Member

nicolas-grekas commented Apr 23, 2018

Currently I'm using ErrorHandler::register(); for that in my front controllers so that they are turned into exceptions

but FrameworkBundle::boot() already does the same, isn't it? So fatals are already turned into exceptions on prod also and you could remove the line you added in your front controller, isn't it?

@dmaicher
Copy link
Contributor

but FrameworkBundle::boot() already does the same, isn't it? So fatals are already turned into exceptions on prod also and you could remove the line you added in your front controller, isn't it?

true! I just double checked it and you are right 😉 This particular project was started with Symfony 2.3 ages ago and I remember back then there was some reason for this. But now it works fine 👍 😃

@nicolas-grekas
Copy link
Member

nicolas-grekas commented Apr 25, 2018

I don't have the double display on my side. I'm not testing with Apache but with php -S, but it shouldn't make a difference. Can you try again from a fresh install? If my linked patch above is OK to you, would you borrow it and update the PR accordingly?

@junowilderness
Copy link
Contributor Author

@nicolas-grekas Your diff works for me, and seems simpler. The only question I have in fact is whether it intended that a production environment 404 should look like this:

screen shot 2018-04-25 at 10 34 34 am

@nicolas-grekas
Copy link
Member

whether it intended that a production environment 404 should look like this

yes it is IMHO: we need to provide some default page, we have one in Debug. If this doesn't fit, then we should update Debug (ie fix #22964)
And ppl are still free to register their own listener if the default doesn't fit.
But this PR is not the place to work on the display.

@junowilderness
Copy link
Contributor Author

@nicolas-grekas I see. I've just now switched to your diff. I haven't rebased or squashed yet.

@nicolas-grekas
Copy link
Member

nicolas-grekas commented Apr 25, 2018

Thanks. It'd be awesome if you could squash and add a test case if possible... :)

@junowilderness
Copy link
Contributor Author

@nicolas-grekas It is rebased and squashed. I stole the test addition you made in #26928.

Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I stole the test addition you made in #26928.

that didn't work actually as an exception is thrown there.
I pushed a test on your fork instead :)

All good on my side, thank you!

@nicolas-grekas
Copy link
Member

Thank you @cilefen.

@nicolas-grekas nicolas-grekas merged commit 4e527aa into symfony:3.4 Apr 29, 2018
nicolas-grekas added a commit that referenced this pull request Apr 29, 2018
…nstalled (cilefen)

This PR was merged into the 3.4 branch.

Discussion
----------

[HttpKernel] Catch HttpExceptions when templating is not installed

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | ?
| Deprecations? | no
| Tests pass?   | ?
| Fixed tickets | #25844
| License       | MIT
| Doc PR        | symfony/symfony-docs#... <!--highly recommended for new features-->

- [x] Test manually
- [x] Check for BC breaks
- [x] Needs tests

<!--
- Bug fixes must be submitted against the lowest branch where they apply
  (lowest branches are regularly merged to upper ones so they get the fixes too).
- Features and deprecations must be submitted against the master branch.
- Replace this comment by a description of what your PR is solving.
-->

Commits
-------

4e527aa bug #25844 [HttpKernel] Catch HttpExceptions when templating is not installed
This was referenced Apr 30, 2018
@junowilderness junowilderness deleted the 25844 branch May 1, 2018 15:58
nicolas-grekas added a commit that referenced this pull request May 29, 2018
This PR was merged into the 3.4 branch.

Discussion
----------

[HttpKernel] fix registering IDE links

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #27194
| License       | MIT
| Doc PR        | -

Reverts some changes made in #27074 in `FrameworkBundle::boot()` that create the linked issue. Leverages changes done in #26138 instead.

Commits
-------

92e3023 [HttpKernel] fix registering IDE links
nicolas-grekas added a commit to nicolas-grekas/symfony that referenced this pull request Jun 6, 2018
…lating is not installed (cilefen)"

This reverts commit b213c5a, reversing
changes made to 61af0e3.
nicolas-grekas added a commit that referenced this pull request Jun 6, 2018
…templating is not installed (cilefen)" (nicolas-grekas)

This PR was merged into the 3.4 branch.

Discussion
----------

Revert "bug #26138 [HttpKernel] Catch HttpExceptions when templating is not installed (cilefen)"

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #27212
| License       | MIT
| Doc PR        | -

This reverts commit b213c5a, reversing
changes made to 61af0e3.

This breaks BC and is more like a new feature, let's move this on master.

Commits
-------

c6acad7 Revert "bug #26138 [HttpKernel] Catch HttpExceptions when templating is not installed (cilefen)"
nicolas-grekas added a commit that referenced this pull request Jun 6, 2018
* 3.4:
  Revert "bug #26138 [HttpKernel] Catch HttpExceptions when templating is not installed (cilefen)"
nicolas-grekas added a commit that referenced this pull request Jun 6, 2018
* 4.0:
  Revert "bug #26138 [HttpKernel] Catch HttpExceptions when templating is not installed (cilefen)"
nicolas-grekas added a commit that referenced this pull request Jun 6, 2018
* 4.1:
  Revert "bug #26138 [HttpKernel] Catch HttpExceptions when templating is not installed (cilefen)"
This was referenced Jun 25, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants