Project

General

Profile

Actions

Bug #99417

closed

No way to get frontend.typoscript (TypoScript setup) in Middleware when page was cached

Added by David Bascom over 1 year ago. Updated about 1 year ago.

Status:
Resolved
Priority:
Should have
Assignee:
-
Category:
Caching
Start date:
2022-12-23
Due date:
% Done:

100%

Estimated time:
TYPO3 Version:
11
PHP Version:
Tags:
Complexity:
hard
Is Regression:
Sprint Focus:

Description

Currently (Version 12.1) there seems to be no possibilty to get the Typoscript Setup in a Middleware, if the page was previously cached.

This problem is probably related to the changes made in
https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/12.1/Feature-98914-TypoScriptAsRequestAttribute.html

How to reproduce:

- write a Middleware that tries to access the TypoScript-Array using `$request->getAttribute('frontend.typoscript')->getSetupArray()` and hook it in at a place, where the Frontend is usually initialized (e.g. after `typo3/cms-frontend/shortcut-and-mountpoint-redirect`)
- Clear the cache in the backend
- First page load works
- Second page load (from cache) will result in the Fatal error "Setup array has not been initialized. This happens in cached Frontend scope where full TypoScript is not needed by the system."

Many of our extensions rely on getting settings from TypoScript to process the request (e.g. EXT:nnrestapi).
Currently we have no idea how to solve this problem other than caching the complete TypoScript setup ourselves or deactiving the frontend cache completely.


Related issues 3 (0 open3 closed)

Related to TYPO3 Core - Feature #97816: New TypoScript parserClosed2022-06-27

Actions
Related to TYPO3 Core - Task #98659: More effective FE TypoScript cache layerClosed2022-10-19

Actions
Related to TYPO3 Core - Task #101031: Remove deprecated code in extbase ConfigurationManagerClosed2023-06-13

Actions
Actions #1

Updated by David Bascom over 1 year ago

An ugly workaround:

Add a fake USER_INT to the frontend.controller configuration from your middleware.
This will force the TypoScript Setup to be reloaded on every page load.

$request->getAttribute('frontend.controller')->config['INTincScript'][] = [];
Actions #2

Updated by Christian Kuhn over 1 year ago

  • Status changed from New to Needs Feedback

Hey. Thanks for the report.

Loading full FE TS for fully cached pages (no user_int on page) is quite a performance hog and not done as you figured out already and as stated by the exception. This is done by intention.

I wonder on why you run into this in v12 only: TS isn't loaded in v11 for fully cached pages either, if I'm not mistaken. The point of fully cached pages is that as little setup is done as possible so the page can be retrieved from cache to create the response as fast as possible. TS calculation is thus restricted to condition evaluation to fetch the correct page cache entry, then check for user_ints and push out the content without creating further TS if there is no user_int. As a result, full cached page requests can be done in about 10-20ms if the system is well configured.

I did not dig very deep into your nnrestapi code, but maybe v12 can help you differently: Since https://review.typo3.org/c/Packages/TYPO3.CMS/+/76106 the FE TS can be fully cached (even across pages if identical and conditions verdicts are identical). This makes loading FE TS with USER_INT's much quicker (see my measurements with https://forge.typo3.org/issues/98659#note-2, especially scenario 5 compared to 2), removing the main performance hog of USER_INT's from v11 and before: USER_INT's are still a bit slower than a full cached page hit, but the overhead is significantly lower. Maybe you could transition your code to a casual USER_INT now and go with the casual plugin rendering instead with your extension?

Actions #3

Updated by Christian Kuhn over 1 year ago

Actions #4

Updated by Christian Kuhn over 1 year ago

  • Related to Task #98659: More effective FE TypoScript cache layer added
Actions #5

Updated by David Bascom over 1 year ago

Hello Christian!

Thanks for your suggestions and the deep-dive here!
Maybe we didn't notice that this actually happens since v11 because we had a other project setup with an USER_INT on the page.

Unfortunately the problem is more complex with the EXT:nnrestapi because we never render a page in the frontend and this way can not user a USER_INT object. We use a Middleware to return the RestApi JSON Response before any page-elements are rendered. But then again, we need an initialized frontend, because we might be rendering Content elements manually to return the rendered markup.

We could take care of the caching ourselves – but would need some Utitily to manually fetch and parse the full TypoScript of the current page.

If you could point me to the right direction I would be very thankful :)

Actions #6

Updated by Christian Kuhn over 1 year ago

Well, the TS parsing code is currently in (TSFE) TypoScriptFrontendController getFromCache().
Extbase has some similar code at some point.

This is currently an intermediate step: At the moment, multiple middlewares deal with TSFE: One creates the instance and set some properties, some others call methods on TSFE and set further properties. This is of course very ugly. Further refactorings will streamline this by moving more state as request attributes around (especially the cache details), with then inlining according TSFE methods to the middlewares to reduce the middleware->TSFE dependencies and ultimately making it an object that is only created by the last request handler middleware. I hope we will see some further progress on this in v12, but I can't promise to still fully finish this. Doing this, we'll also establish a FE TS factory (next to the already established TypoScriptStringFactory, PageTsConfigFactory and UserTsConfigFactory), which will further simplify everything.

If you need a middleware now that does similar setup, you could dig into ext:redirects RedirectHandler and RedirectService, which sets up an early TSFE in bootFrontendController(), even though this is ugly as well. This could be a hint for your middleware, though. But I can't promise it does not break when we continue refactoring TSFE and the middlewares.

Actions #7

Updated by Benni Mack about 1 year ago

  • Target version changed from 12.2 to 12.3
Actions #8

Updated by Christian Kuhn about 1 year ago

  • Status changed from Needs Feedback to Closed

Closing here for now. Please re-open or create a fresh issue and link to this one if there is currently more to deal with.

Actions #10

Updated by Christian Kuhn about 1 year ago

  • Status changed from Closed to Needs Feedback

pushed a WIP to mitigate (!) this: https://review.typo3.org/c/Packages/TYPO3.CMS/+/78007 ... @David Bascom could you play around with the WIP patch to see if that "solves" your issue? note you'll this is only to not-crash in v12, it does not really solve your misuse.

Actions #11

Updated by David Bascom about 1 year ago

Hello Christian!

Thanks for having a look at this topic!

As fas as I can see in the commit, the code will now catch the Exception - but unfortunately this is not really solving the problem. There are several use-cases where developers might need a way to manually initialize the frontend typoscript. An example would be: A cronjob should send out an E-Mail. The content of the E-Mail should be editable by the backend-user on a page in the backend.

Content-Elements can only be rendered on-the-fly, if TYPO3 has access to the TypoScript rendering setup. (Thinking of it, this might even be a problem when dynamically generating links to the frontend from a context in which the TypoScript-Setup is not available)

Another example would be: An extension that kicks in as Middleware has no way to access the TypoScript Setup of a page if the page was cached. This is fine as long as the response of the middleware can also be cached - but this ist not always the case.

It would be ideal if the core had a method to manually trigger the (re)parsing of the TypoScript setup - even on a cached page. This reminds me a lot of many, many discussions and problems developers have had in the past while trying to accomplish a similar task (https://stackoverflow.com/questions/68005010/typo3-v10-how-to-access-tsfe-in-backend-scheduler-task/68020537#68020537).

Thanks for your thoughts on this!

Actions #12

Updated by Helmut Hummel about 1 year ago

  • Target version changed from 12.3 to Candidate for Major Version
  • TYPO3 Version changed from 12 to 11
  • PHP Version deleted (8.1)

Hi David,

David Bascom wrote in #note-11:

As fas as I can see in the commit, the code will now catch the Exception - but unfortunately this is not really solving the problem. There are several use-cases where developers might need a way to manually initialize the frontend typoscript.

While this likely is true, it has been like so since the early days of TYPO3.
Gradually the APIs got better so that now less burden is put onto devs having such needs.

An example would be: A cronjob should send out an E-Mail. The content of the E-Mail should be editable by the backend-user on a page in the backend.

The goto way to do such a feature now would be to initiate a full frontend rendering bottom to top. There are multiple ways to achieve this.
Have a look at the PageErrorHandler for some code that currently still is necessary. https://packagist.org/packages/helhum/typo3-frontend-request might be useful as alternative.

In any case, making the API more straightforward to render a page is an ongoing process. It is done step by step and for sure can not be handled in a single ticket.

Content-Elements can only be rendered on-the-fly, if TYPO3 has access to the TypoScript rendering setup. (Thinking of it, this might even be a problem when dynamically generating links to the frontend from a context in which the TypoScript-Setup is not available)

Sure. That is how TYPO3 currently works. To render a TypoScript object reliably, currently the complete frontend needs to be booted and set up.
Very unlikely this can easily be changed. If you want to render a TypoScript the most reliable way is to do what typoscript_rendering does, or maybe even use typoscript_rendering, as it provides an entry point where everything is set up exactly for this use case. https://github.com/helhum/typoscript_rendering

It will be impossible to render content objects with less setup overhead, as long as content objects access state outside of their configuration (like an Extbase plugin pulling in global TS configuration). So TYPO3 can go in at least two different directions: 1. Always require a full (or partial boot), but wrap that into a nice API, 2. restrict what content objects can actually access.

Another example would be: An extension that kicks in as Middleware has no way to access the TypoScript Setup of a page if the page was cached. This is fine as long as the response of the middleware can also be cached - but this ist not always the case.

Either you want a fully cached response (your middleware response must also be cached), or you need to tell TYPO3, that the request can not be cached. Currently the most reliable way to do so, is to add a _INT element on the page. There is no other reliable way to achieve that otherwise.

It would be ideal if the core had a method to manually trigger the (re)parsing of the TypoScript setup - even on a cached page.

There is a way, which is to either have a _INT element on the cached page OR (if you really know how to not affect other requests than the ones that need it) to force TypoScript parsing https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/10.0/Deprecation-88792-ForceTemplateParsingInTSFEAndTemplateService.html#migration

This reminds me a lot of many, many discussions and problems developers have had in the past while trying to accomplish a similar task (https://stackoverflow.com/questions/68005010/typo3-v10-how-to-access-tsfe-in-backend-scheduler-task/68020537#68020537).

Again here. There are multiple ways to approach this. I would start with rethinking where I put configuration (e.g. site settings), how I create links (use router obtained from site) and how to render content objects (see above).

Since this isn't a request only related to TYPO3 12, I change the target version from 12 to "next major".

I'm still struggling what else to do with this ticket, since the request is valid in general, but currently the conversation is a mixture of general ideas, support requests, concrete todos.

I'd rather close this one here and ask everybody involved creating multiple tickets with different scopes instead.

Like:

  1. Feature: add API to render an arbitrary content object from within all contexts (backend, cli)
  2. Feature: allow rendering HTML mails from within all contexts (especially cli)
  3. Bugfix: mitigate ecxeption in FrontendConfigurationManager

...

Does this work for everybody?

Actions #13

Updated by Helmut Hummel about 1 year ago

  • Status changed from Needs Feedback to Rejected
Actions #14

Updated by Christian Kuhn about 1 year ago

  • Status changed from Rejected to New
Actions #15

Updated by Gerrit Code Review about 1 year ago

  • Status changed from New to Under Review

Patch set 2 for branch main of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at https://review.typo3.org/c/Packages/TYPO3.CMS/+/78007

Actions #16

Updated by Gerrit Code Review about 1 year ago

Patch set 3 for branch main of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at https://review.typo3.org/c/Packages/TYPO3.CMS/+/78007

Actions #17

Updated by Gerrit Code Review about 1 year ago

Patch set 4 for branch main of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at https://review.typo3.org/c/Packages/TYPO3.CMS/+/78007

Actions #18

Updated by Christian Kuhn about 1 year ago

  • Status changed from Under Review to Resolved
  • % Done changed from 0 to 100
Actions #19

Updated by Christian Kuhn 11 months ago

  • Related to Task #101031: Remove deprecated code in extbase ConfigurationManager added
Actions

Also available in: Atom PDF