Bug #93195
Updated by Rémy DANIEL about 3 years ago
*Description of the bug* I use f:uri.action to generate a link to an Extbase plugin, with some plugin arguments. There is not RouteEnhancer on the plugin, so a cHash is added to the generated uri. When the target page of the link is a draft version of the page, accessing the generated uri leads to a 404 (cHash comparison failed). *How to reproduce* It is not easy to reproduce, but here is some steps. The issue exists since TYPO3 10. I cannot reproduce it on TYPO3 9. # setup ext:workspace with one draft workspace # create a site with a rootpage and a working TS setup # switch to the draft workspace # on a page, create a TS template with this setup override: <pre> page.10 > page.10 = FLUIDTEMPLATE page.10 { template = TEXT template.value = {f:uri.action(action: 'show', controller: 'Test', extensionName: 'Test', arguments: {foo: 'bar'})} }</pre> # the page has now a live version (uid=1, t3ver_wsid=0) and a draft version (uid=2, t3ver_oid=1, t3ver_wsid=1) # display the preview of the page: you see the uri generated with a cHash # go to the generated url: a 404 is triggered because of a cHash comparison failure *Debugging* When building the cHash, the ID of the page is used along with other parameters in the cHash calculation . When validating the cHash, the ID of the page found by the router is used (see @\TYPO3\CMS\Frontend\Middleware\PageArgumentValidator::getRelevantParametersForCacheHashCalculation@). In most of the case, there is no reason that this page's id change, so this part of the cHash calculation/checking works well. Now, while debugging, I found that when generating the uri, +the uid of the live page is used+. But when the uri is requested and the cHash is validated, the page id is taken from @$request->getAttribute('routing')@ (which is a PageArguments instance). +Here, the page id is the draft uid+. Because the page id are not the same, the cHash comparison could not succeed, and this will trigger a 404. *Fix proposal* The page id used for the cHash calculation should be taken from the same record version when generating and validating the uri. I think the live uid should be used when validating the cHash, because this is always the live uid that is used when generating links (typolink, menus, etc). As a workaround, I used that trick on some links: <pre> {v:page.info(field: '_ORIG_uid') -> f:or(alternative: '{v:page.info(field: \'uid\')}') -> v:variable.set(name: 'targetPageUid')} </pre> The trick is to generate the link with page._ORIG_uid if it exists, and fallback to page.uid. _ORIG_uid is the uid of the draft record.