Problem/Motivation
index.php contains far too much logic. This file is not contained in /core - the more logic that is contained with in it there more susceptible it is to change during the 8.x release cycle. This means it is harder to give simple instructions on upgrading Drupal - i.e download and copy the core directory over should be what we are aiming for.
Proposed resolution
Use the same pattern in the front controller scripts as Symfony (see #13). Especially ensure that DrupalKernel
can be instantiated and used in the same way as a Symfony application kernel. Also preserve the option to wrap the application kernel from within the front controller script.
DrupalKernel::createFromRequest()
throws exceptions, e.g. when there is an invalid HOST
header on the request. In order to get rid of the try...catch
block in the front controller it is therefore necessary to replicate the initialization logic in DrupalKernel::handle()
such that the kernel can be constructed without the static factory method. In order to make this work it is necessary to extract common initialization logic from DrupalKernel::createFromRequest()
into various methods:
- Load
bootstrap.inc
inDrupalKernel::bootEnvironment()
- Find site path and initialize settings singleton in new
DrupalKernel::initializeSettings()
method - Redirect users to install script in
DrupalKernel::handle()
This results in the following front controller script:
/**
* @file
* The PHP page that serves all page requests on a Drupal installation.
*
* All Drupal code is released under the GNU General Public License.
* See COPYRIGHT.txt and LICENSE.txt files in the "core" directory.
*/
use Drupal\Core\DrupalKernel;
use Symfony\Component\HttpFoundation\Request;
$autoloader = require_once __DIR__ . '/core/vendor/autoload.php';
$kernel = new DrupalKernel('prod', $autoloader);
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);
Remaining tasks
Agree location of logic- Review
- Commit
User interface changes
None
API changes
None.
Beta phase evaluation
Issue category | Task |
---|---|
Issue priority | Major |
Prioritized changes | The main goal of this issue is reduce fragility by making it easier to upgrade Drupal by having less logic outside /core . @alexpott, as a framework manager, agrees that we should make this change before 8.0.0. |
Disruption | Disruptive for sites with custom front controllers because it will require a BC break, i.e. it would be necessary to manually replicate changes to the new front controller script. |
Comment | File | Size | Author |
---|---|---|---|
#124 | patch-interdiff.txt | 1.66 KB | znerol |
#124 | move_all_the_logic_out-2389811-124.patch | 15.21 KB | znerol |
#114 | interdiff.txt | 3.14 KB | znerol |
#114 | move_all_the_logic_out-2389811-114.patch | 15.19 KB | znerol |
#103 | interdiff.txt | 1.07 KB | znerol |
Comments
Comment #1
alexpottComment #2
benjy CreditAttribution: benjy commentedYes, +1 to this. Putting the logic on \Drupal works for me, I can't think of a better place to put it.
One question, is "frontController" the best we can do? It makes sense but at the same time, it's different to how any other "controller" works in core, eg a class.
Couple of doc things;
"as included in index.php"
Longer than 80chars.
Comment #3
BerdirI think we had this a while ago (as a function) but it was reverted at some point.
Comment #4
tstoecklerYes, we had
drupal_handle_request()
inbootstrap.inc
. I don't really care either way, as long as the code can be autoloaded.Comment #5
cosmicdreams CreditAttribution: cosmicdreams commented@#2: "Front controller" is what the text books say we should name it:
from Wikipedia:
"The Front Controller Pattern is a software design pattern listed in several pattern catalogs. The pattern relates to the design of web applications. It "provides a centralized entry point for handling requests." Front controllers are often used in web applications to implement workflows."
/Drupal::frontcontroller should be our centralized entry point.
Comment #6
alexpottThe reason I'm keep to move this out of index.php is that it keeps the instructions for a certain type of user (think dreamhost) simple. We should never really change anything outside of /core once 8.0.0 is out. This means that changing .htaccess, web.config, composer.json, composer.lock or any other file is acceptable and easy to maintain.
I can't think of a better name than frontController() open to suggestions.
Comment #7
mpdonadio`frontController` is a noun, which implies that it is an object, or provides access to an object. Nearly everything else in that class does this, and the docblock does say that it is the "Static Service Container wrapper." Functions that don't provide access to objects, like ::l() and ::url() are really just helper functions for the objects.
`\Drupal\Core\DrupalKernel` may be a better place for this, and may also give us a chance to refactor that class / interface into something a little cleaner, and provide a middleware to bootstrap in a different manner if it wants to. I would also suggest `\Drupal\Core\Drupalkernel::processRequest()` and also returning the $response object that gets created.
Comment #8
znerol CreditAttribution: znerol commentedWith the current approach it is possible to wrap the application kernel from within the front controller script. Not sure whether this is relevant, now that we have stack middlewares, but they wrap the http kernel, not the application kernel.
Maybe introduce
DrupalFrontController
which implements theKernelInterface
andTerminableInterface
Looking at
Request::createFromGlobals()
andResponse::send()
I do not expect them to throw exceptions which could be meaningfully caught with the If you have just changed code message. Exceptions thrown interminate()
cannot influence the output because at this point in time the response is already sent. Therefore we could move the messytry/catch
intoDrupalFrontController::handle()
and even write unit-tests for it.See also the Symfony SE front controller script.
Comment #9
mpdonadioI'll work on this if there is agreement on an approach. #8 seems like a good idea.
Comment #10
peterx CreditAttribution: peterx commentedOne common change in Drupal is to move the code out of Web root. The changes are not obvious. They could be made easier by defining the Drupal and Web roots at the start then documenting the change you can make when core is moved outside of Web root.
We do something similar in .htaccess with comments about changing redirections.
I suggest something like the following with a page somewhere on Drupal.org explaining how to change $drupal_root:
$web_root = __DIR__;
$drupal_root = __DIR__;
// $drupal_root = '/home/example/drupal';
... #8 code modified ...
$autoloader = require_once $drupal_root . '/core/vendor/autoload.php';
Comment #11
David_Rothstein CreditAttribution: David_Rothstein commentedDéjà vu!
This was previously done earlier in the Drupal 8 cycle (#1831998: Reduce index.php for easier upgrading) but then was slowly whittled away and eventually removed. Given that history, I would suggest adding a code comment to index.php here explaining why we put no actual logic directly in the file - then maybe it will stick this time.
That makes more sense to me too, or possibly handleRequest()? - keeping in mind that the earlier issue that did this called it drupal_handle_request(). Either "handle" or "process" sounds good to me.
Comment #12
mpdonadioI got bored last night, and wrote up a quick patch. I started down the road in #8, but it became apparent that 95% of KernelInterface wasn't needed, so I made DrupalFrontControllerInterface / DrupalFrontController and wired it up that way. Besides, it keeps the kernel doing kernely things, and the front controller as just the front controller. Just waiting for TestBot to give the OK of the POC patch.
Comment #13
znerol CreditAttribution: znerol commentedI believe we should make it easy to use
DrupalKernel
in modern code. Therefore let's do the following:DrupalKernel::createFromRequest()
optional, i.e. move the initialization code toDrupalKernel::handle()
. In the long run we probably should get rid ofDrupalKernel::createFromRequest()
completely.try/catch
block from the front controller toDrupalKernel::handle()
.That makes it possible to use the following standard pattern in
intex.php
(and alsohttp[s].php
):As a consequence some of the setup code now is duplicated in
prepareLegacyRequest()
. On the other hand, the installer-redirection logic now is inside the standard request-response flow. I think we do not need that logic in legacy requests anyway.Comment #14
znerol CreditAttribution: znerol commentedFix
run-test.sh
, alsoResponse::prepare()
is not expected to be called from the front controller.Comment #15
mpdonadioHad this done before @znerol posted #13, but was waiting to see if anything major came out of TestBot before I posted it to the issue. I think this will come up green, and the exception handling works with my test scripts.
#13 has some static vs object context problems, so I couldn't try the HTTP exception handling with it, but it looks like the better thing to do.
Comment #18
benjy CreditAttribution: benjy commentedCreate is spelt wrong :) Looks pretty good to me.
Comment #19
znerol CreditAttribution: znerol commentedComment #20
znerol CreditAttribution: znerol commentedComment #21
znerol CreditAttribution: znerol commentedDiscussed this with @dawehner and @mpdonadio in IRC, conclusion is that we want to go with approach in #14, i.e. the front controller script should instantiate a kernel. Test failure in
ConfigExportUITest
is due to adventurous global tainting code inconfig_export_test
. This is easy to rewrite properly. Interdiff is against #14.Comment #22
znerol CreditAttribution: znerol commented#21 contains debugging stuff. Rerolling, interdiff is still against #14.
Comment #25
znerol CreditAttribution: znerol commentedBumped into #2409247: Generated proxy classes break DrupalKernelTest when running from the UI while trying to fix the test failures in
DrupalKernelTest
. Let's roll back the changes to that test for the moment.Comment #26
jibranI think this is rebase gone wrong.
Comment #27
BerdirNo, just an incomplete interdiff ;)
Comment #28
znerol CreditAttribution: znerol commentedLet's try to reduce code changes such that its not necessary to touch tests.
Comment #29
znerol CreditAttribution: znerol commentedOpened #2409547: Remove config_export_test.module
Comment #30
znerol CreditAttribution: znerol commentedComment #31
jibranCan't we use app variable here? Or is it not available yet?
Comment #32
znerol CreditAttribution: znerol commentedbootEnvironment()
is static, so regrettably no.Comment #33
mpdonadioThis needs a reroll due to #2221699: HTTP_HOST header cannot be trusted. I'll take care of it since I still have my testing scripts handy for checking the things that can't be handled by unit/web testing.
Comment #34
Damien Tournoud CreditAttribution: Damien Tournoud commentedAll this sounds like a regression to me.
@znerol:
DrupalKernel::createFromRequest()
is that way for a reason: our whole processing, the kernel, the container, etc. all depends on the settings, and as a consequence all depend on the request. This is not "old" code (as opposed to "modern"), it is a conscious architecture decision.If we want to reduce the amount of code in the front controller, the answer is to add a convenience function somewhere, not to butcher the architecture of the kernel.
Comment #35
mpdonadio@damz, the patch in #15 is essentially what you described; a helper object rather than a helper method, though.
There was discussion this weekend about which approach was better on IRC, and we decided on this. I forget who was in on it, though.
Comment #36
mpdonadioThink this is good, and should come up green.
Comment #37
znerol CreditAttribution: znerol commented@Damien Tournoud: The very goal of this issue is to get rid of the
try...catch
inindex.php
. This is only possible if the front controller only calls code that either does not throw exceptions or is capable of handling them.Several approaches have been proposed and explored:
/Drupal
(#1, #6)DrupalFrontController
class #8 (implemented in #15)DrupalKernel::handle()
#13ffOption 1 is essentially what was there prior to the kernel-bootstrap patch but additionally removes the exception handling from the front controller. Whether or not to bury everything into one static function was discussed during review of said patch and it was a conscious architecture decision to better, bring our front controller closer inline with a Symfony kernel app. (@neclimdul #2016629-227: Refactor bootstrap to better utilize the kernel)
Option 2 is only marginally better in the current implementation. It would be acceptable if
DrupalFrontController
would implement the SymfonyHttpKernelInterface
and theTerminableInterface
.Option 3 just moves some bits of the Kernel around such that there is no need for
DrupalFrontController
at all. My statement about deprecatingDrupalKernel::createFromRequest()
was a bit premature, because we still need it in various places where it would be inconvenient to follow the front controller pattern.Comment #38
Damien Tournoud CreditAttribution: Damien Tournoud commented@znerol: Given how
DrupalKernel
is currently structured, only one site path can be handled in a given instance.Changing this to allow multiple independent requests to be processed (potentially at the same time) by a single instance of
DrupalKernel
is a relatively large undertaking, that is extremely far from being done by the current patch.Looking at the current architecture, it is not even possible to do so properly, because several methods on
DrupalKernelInterface
are bound to a specific site anyway (->getServiceProviders
,->discoverServiceProviders
,->updateModules
,->handlePageCache
, etc.).That puts option #3 completely off the table. I suggest we go with #2, which sounds like the cleaner given the current state of the
DrupalKernel
architecture.Comment #39
znerol CreditAttribution: znerol commentedI completely agree. Neither of the three approaches attempts to change that. I assume that you misunderstood option #3 somehow. In fact it does the same as #2 but without introducing an additional front controller class.
Comment #40
Damien Tournoud CreditAttribution: Damien Tournoud commented@znerol: I understood option #3, and I'm saying it's not a practical option at all. The current patch tries to make
DrupalKernel
handle multiple independent requests and it is utterly insufficient.Just as an example, in the implementation from #36,
->handle
calls->initializeSettings
, which is going to detect the site path based on the request, but none of the rest of the call is actually re-entrant. If ever the site path changes between two requests, things are going to be utterly broken, because the container doesn't support that: the container is not going to be booted again, so you are going to end up with a new site path, but still the old list of modules, the old container, etc.Let me re-iterate: Given how
DrupalKernel
is currently structured, only one site path can be handled in a given instance.Changing that (which #3 is trying to do) is hard, and I suggest option #2 (adding a multi-site
DrupalFrontController
in front of the currentDrupalKernel
) is a better idea at this stage.Comment #41
znerol CreditAttribution: znerol commentedThanks for the clarification and the example. It seems to me that reusing the application kernel for multiple requests is a pretty exotic thing to do. I've never encountered a Symfony application which actually tried this. On the other hand, reusing the same http kernel for subrequests is quite common and that's also supported by Drupal.
That said, it is actually easy to protect against the scenario presented in #40. The only thing to do is to throw an exception if anyone tries to set the site path on a booted kernel.
Finally let me point out that even
DrupalKernel::createFromRequest()
does not protect against crazy people attempting tohandle()
different requests with the same Kernel.Comment #42
hussainwebIt's like the tiniest nitpick ever, but here it goes. I hope it gets the issue going again. I would have really liked this in beta5/6. It would have given me more confidence in planning out the composer approach for building a site I am planning.
Comment #43
dawehnerIsn't that now a duplicate of an issue tstoeckler was working on recently and got rtbc?
Comment #44
znerol CreditAttribution: znerol commented@dawehner: Which one do you mean? #2406681: Add an autoload.php in the repo root to control the autoloader of front controllers? I do not see any significant overlap there.
Comment #47
Mile23The front controller should grab the global and environmental parameters and inject them into the kernel.
The kernel should be an object that encapsulates all the behavior, but which requires that you inject parameters.
Basically the kernel is the object that forces you to start the injection of parameters for everything else.
Hence:
Superglobal in the kernel. Nope. :-)
__DIR__ and require_once in a static kernel method. Nope. :-)
Comment #48
cosmicdreams CreditAttribution: cosmicdreams commented@47:
Are you saying that you would want the base_url and the core_root to be injected?
Comment #49
alexpott@mile23 that is an existing issue.
The global is only used if something serious has gone wrong - and this generic exception catch completely breaks Drupal's exception handling so I think this should be removed too.
Comment #50
znerol CreditAttribution: znerol commentedI disagree. The standard exception handling is not affected by this change because that happens in the http kernel. What we are doing here is moving the stuff from index.php one layer down to
DrupalKernel
(the application kernel).Comment #51
znerol CreditAttribution: znerol commentedRerolled.
Comment #52
alexpott@znerol yep it is unaffected I'm just pointing out that currently we register an exception handler in DrupalKernel (
set_exception_handler('_drupal_exception_handler');
) and it can never actually be hit because of thiscatch
.Comment #53
znerol CreditAttribution: znerol commented@alexpott: I do not quite understand. Does this patch alter the behavior in this regard?
Comment #54
alexpott@znerol nope not at all. All I was trying to say is that...
Is completely wrong both before and after this patch and therefore discussing whether or
$GLOBALS['base_url']
should be in DrupalKernel or not is moot.Comment #55
Crell CreditAttribution: Crell at Palantir.net commentedWhy is the prepare() being moved inside the Kernel? I don't think I've ever seen that done inside an HttpKernelInterface implementation. (Although I admit I haven't surveyed all Symfony-using projects.) One method call is not a big expectation for the rare person writing a new front controller.
Comment #56
znerol CreditAttribution: znerol commentedSymfony SE front controller script, Symfony HTTP Cache Kernel, laravel front controller script.
IMHO
prepare()
clearly belongs into the application kernel, and not the front controller script.Comment #57
znerol CreditAttribution: znerol commentedAlso note, that in Symfony
prepare()
is called from a response listener for uncached requests.Comment #58
Crell CreditAttribution: Crell at Palantir.net commentedInteresting. That must have changed at some point because that didn't used to be the default in Symfony SE. I withdraw my objection.
Comment #59
almaudoh CreditAttribution: almaudoh commentedComment #60
znerol CreditAttribution: znerol commentedDrupalKernel::createFromRequest
changed. The class loader stuff probably should go into the newinitializeSettings()
method.Comment #61
znerol CreditAttribution: znerol commentedI think this is at least major. If we ship with the current crap-loaded front-controller then sites will have a hard time to customize it in a sane way.
Comment #62
znerol CreditAttribution: znerol commentedComment #64
znerol CreditAttribution: znerol commentedComment #66
znerol CreditAttribution: znerol commentedUhm, that was the wrong patch. Ignore #64, interdiff is against #61.
Comment #68
znerol CreditAttribution: znerol commentedInteresting. Seems like
TestDiscovery
also should be blowing up inHEAD
.Comment #69
znerol CreditAttribution: znerol commentedFiled #2474817: DrupalKernel::classLoader not updated when switching to apcu either through settings.php or automatically.
Comment #72
mpdonadioReroll b/c #2474817: DrupalKernel::classLoader not updated when switching to apcu either through settings.php or automatically is in, but this take care of that already. Or am I misreading #66?
Comment #74
znerol CreditAttribution: znerol commentedWeird. #72 looks fine. I cannot reproduce the test failures on my local machine.
Reupload.
Comment #76
webchickAhhhh. :) Much better.
Comment #77
znerol CreditAttribution: znerol commentedReroll
Comment #78
alexpottReally liking this change.
This makes heaps of sense - can we add a unit test for it and should be be throwing a more specific exception?
Comment #79
znerol CreditAttribution: znerol commentedI think we use
LogicException
in some other places.Comment #80
alexpottSorry should have caught this last time.
Needs a leading slash ... we're in a class now :)
Comment #81
znerol CreditAttribution: znerol commentedOh, right!
Comment #82
dawehnerHere is a question, maybe its just dump.
So we have two places where we call bootEnvironment from: ::handler() and ::createFromRequest(), but both places have a kernel $kernel already. Given that I'm curious why bootEnvironment has to be static, because in case it isn't we could use $this->root instead.
Comment #83
znerol CreditAttribution: znerol commentedbootEnvironment()
is also called statically from withinrebuild.php
and I do not see an obvious way on how to fix that.Comment #84
dawehnerMh right, I just had a look at the patch file for itself, too bad.
Comment #85
dawehnerI like the general work forward.
Comment #87
xjmComment #89
znerol CreditAttribution: znerol commentedReroll.
Comment #90
znerol CreditAttribution: znerol commentedProper conflict interdiff.
Comment #91
alexpottThe patch looks good after resolving the conflicts. Thanks @znerol.
Comment #92
Mile23Aw yeah.
Comment #93
cosmicdreams CreditAttribution: cosmicdreams commentedHey, this looks awesome. I don't want to sidetrack things but I have a question that relates to the work here.
Would it be possible / crazy to convert the string ('prod') to a constant in this line:
That way we could pull index.php out of the git repo and have it vary for different environments. Does that make sense?
Comment #94
neclimdulI'm not sure why we're keeping createFromRequest still. If you use it though you'll hit settings initialization twice with is fairly expensive.
Shouldn't this stay in the front controller
Comment #95
neclimdulSorry, I got distracted and forgot to follow up and on reading the issue on the prepare.
I disagree with moving it still. A listener and hard coded into the kernel have different effects on modularity and testing. Moving has no real benefit either.
Comment #96
Mile23I'm pretty sure this isn't used anywhere other than perhaps simpletest, which has its own kernel subclass anyway.
I'd love to see the environment hooked into something useful, so we can support lightweight functional testing with fixtures, but that's out of scope here, too.
If you have a use-case in mind, create a follow-up, please. :-)
Comment #97
znerol CreditAttribution: znerol commentedNot sure about the benefit of that. In which case do we want to swap that out?
Comment #98
fgmA case to consider is non-Drush / non-Console CLI applications, (e.g. Beanstalkd queue runner), for which anything HTTP-related is entirely irrelevant, and need to build fake headers for the CLI "request" in their own bootstrap.
The less HTTP they have to fake, the simpler and more robust it is for these.
Comment #99
znerol CreditAttribution: znerol commentedRe #94.1:
We use that in the following cases for legacy scripts and in tests. In both cases it is desirable to initialize the settings.
Given that
createFromRequest()
did not change in this patch but merelyDrupalKernel::handle()
, the important question is whether the latter method is used anywhere on an application kernel instance created with the static factory instead of directly with constructor. In order to find those cases, it is necessary to filter out occurrences where the http kernel is invoked (i.e. subrequests etc.).The only questionable file
ExceptionHandlingTest.php
is a false positive.There is nothing in core which calls
DrupalKernel::createFromRequest()
followed byhandle()
. The reason why the static factory is still necessary is its usage in legacy scripts and drush.Re #94.2:
The purpose of the Response::prepare() is to tweak
For example it removes the response body if the incoming request used the
HEAD
verb. It's obvious that this should not be done before storing the response in the internal page cache. Therefore a response subscriber would only work for us if the page cache is disabled otherwise another mechanism is necessary. It would be possible to add another early middleware in order to make it pluggable.I still do not think it is necessary to make it pluggable. If there is a technical reason to do it, then I'd prefer to move the call back to the front controller, because adding a new middleware for that single function call seems like overkill.
@all: Especially those with Symfony experience, please help us decide whether there are situations where running
$response->prepare($request)
insideDrupalKernel::handle()
would be wrong.Comment #100
Mile23The first line of createFromRequest is this:
$core_root = dirname(dirname(dirname(__DIR__)));
. So automatically it's breaking isolation.Semi-related: Reading over DrupalKernel right now it still kind of irks me that we can't inject DRUPAL_ROOT. The constructor says this:
$this->root = dirname(dirname(substr(__DIR__, 0, -strlen(__NAMESPACE__))));
. Makes me itch. We could test the kernel with vfsstream if this were to change.I think those legacy scripts and drush need to get broken and re-factored a bit, but I beat my head against that when it *wasn't* beta time and no one cared, so I'm not holding out hope.
I'm not sure that's the case. The render process can change headers, and the headers can be cached. Also, if parts of the response are cached we don't need to rebuild them on the next similar request.
DrupalKernel::handle() is a shim for HttpKernel::handle(). I prefer the thin shim approach for overridden methods like this.
Of course, if there's an overriding design need, then yay. So what's the overriding design need?
@fgm mentions CLI apps having needs, but really, those should be addressed in other ways. For instance, if there's a need for CLI clients to clear the cache or run cron in an easy way, then let's build CliKernel and give it methods like clearCache($type='all');
Comment #101
znerol CreditAttribution: znerol commentedThe
PageCache
middleware stores/delivers the wholeResponse
object including headers, status and content. The response event is emitted by the http kernel (i.e. the innermost kernel which is wrapped by several middlewares, including the page cache one). I.e.,PageCache::set()
is invoked with the result ofHttpKernel::handle()
.Response::prepare()
adapts the response according to user agent characteristics and also removes the content if it was generated as a result of aHEAD
request. Calling that beforePageCache::set()
would lead to a cache-poisoning issue. It follows thatResponse::prepare()
cannot be in a response listener because that runs beforePageCache::set()
on a cache miss.So really we have three options where to call that method:
HEAD
, but that deviates from Symfony front controllers)patch
)It would be great if we could stick to the scope of this issue and concentrate on picking the right choice here.
Comment #102
neclimdulThanks znerol for addressing my concerns. I'm not sure I agree about prepare() still but I'm not sure its worth blocking.
Doing one more review, I had one more question. Currently if I want to customize/replace/or remove the hard coded catch message I could replace the front controller but now you have to replace DrupalKernel or patch it. Neither option is very reasonable. Should that not either be in the front controller or configurable in some way?
Comment #103
znerol CreditAttribution: znerol commentedThe point of this issue is to remove the
try...catch
from the front controller. What about another setting?Comment #104
alexpottIn think changing this #103 is out-of-scope. Personally I'd love to remove the try catch but let's discuss that in another issue and just do the refactoring here.
Comment #105
neclimdulI was actually mindful of scope when bringing it up but this would be a regression. Also the scope of this issue was to make maintenance and upgrades easier but adding the requirement of possibly having to maintain an alternative kernel or patching core is worse then the current situation.
Comment #106
alexpottThis looks like it is has several problems compared with HEAD. Firstly if $catch is TRUE then it'll never be thrown again which means the error will not be caught be drupal's exception handler and therefore it won't be correctly logged.
Maybe the best thing to do is just leave this in index.php and file a separate issue to discuss it's removal or move to somewhere else - for example the exception handler itself.
Comment #107
znerol CreditAttribution: znerol commentedExceptions caught here are those which are thrown before our exception handler is installed (and before there is a container). We could add an
error_log()
though.Comment #108
znerol CreditAttribution: znerol commentedCould you please provide a use-case where this would be necessary with #103.
Comment #109
neclimdulI'm not sure that is a problem. $catch is actually true by default and the $catch logic is actually run after the logging would have happened. In that respect it should be exactly the same as HEAD only one method call removed from its original location. Its the last thing run in the last handle method.
You would set it to FALSE to catch all exception in your front controller for what ever reason. Debugging or very specific logic I guess. Side note, I tried to rationalize this as an option instead of using a setting but its the behaviour of all exceptions all the way up the stack-middleware tree though so I think it would be fairly ineffective at targeting something specific like the "rebuild" message.
Comment #110
znerol CreditAttribution: znerol commentedOk, that's not quite true. Exception caught here are those which the exception handler fails to handle.
You set
$catch
toFALSE
in unit tests. This is the one and only reason for that parameter. Perhaps it would be clearer if it would be named$return_response_whatever_it_takes = TRUE
(this is what we want in production).Comment #111
neclimdulYeah, alex corrected me on IRC. I don't know what I was thinking.
His concern then is actually probably legitimate then because if a random page(not the entire site) is throwing an exception its going to probably slip through without the logging.
Comment #112
znerol CreditAttribution: znerol commentedTry this experiment. Turn off the database, add a breakpoint on
Drupal\Core\Database\Driver\mysql\Connection::open()
where thePDO
object is constructed (line 92) and then step through the exception handling.HEAD
: Thethrow
at the end of thecatch
block inindex.php
sends us to_drupal_exception_handler()
, that throws again because there is no Database (and therefore no config) and sends us back to the front controller and then again back to the error handler and so fort until finally something breaks that loop - I have no idea what.Because we do not
throw
again in thepatch
we do not enter that feedback loop. Alex is right indeed that in that case we side-step the exception handler. I think it is wrong to rethrow if$catch
isFALSE
, on the other hand we probably want to give the exception handler a chance to log something if possible. So perhaps we should simply forward to the exception handler from thecatch
clause and only add the rebuild message if that throws also.Comment #113
znerol CreditAttribution: znerol commentedFiled #2483587: Bootstrap errors masked due to Drupal::hasService only checking for presence of a service, not whether it is actually initialized
Comment #114
znerol CreditAttribution: znerol commentedLet's extract the exception handling code into its own method and give the Drupal exception handler a chance to log it.
Comment #115
znerol CreditAttribution: znerol commentedComment #118
mpdonadioSetting this back to Needs Review based on #114 being green after the re-queue from the testbot sadness today.
I manually tested both the hostname length protection and the trusted host mechanism, and both triggered the proper path through DrupalKernel::handleException()
Comment #120
webchickLet's be bold, and see if this addresses alexpott's concerns.
Comment #124
znerol CreditAttribution: znerol commentedReroll after #2491155: Update drupal.org and kernel.org URLs in core modules (Follow-up to 2489912).
Comment #125
Crell CreditAttribution: Crell at Palantir.net commentedBlindly re-RTBCing after a successful reroll...
Comment #126
alexpottYep my concerns are addressed - this is really great work work - thanks @znerol for persevering :)
Committed 90d6fb1 and pushed to 8.0.x. Thanks!
I've improved the beta evaluation.
Comment #127
alexpottComment #129
yched CreditAttribution: yched commentedw00t !! Awesome !