Bug #88628
closedRedirect call on controller level is firing the action again
0%
Description
I'm not really sure if this is a bug or something has changed here, but the behaviour in TYPO3 8 is not the same like in TYPO3 9.
It seems that a redirect call ($this->redirect()) on controller level will call the action again which have fired the redirect.
So if I do something like that:
class FormController extends ActionController
{
public function showAction(): void
{
// nothing to do just show the form
}
public function redirectAction(): void
{
$mailData = [
'sender' => $this->settings['senderEmail'],
'senderName' => $this->settings['senderName'],
'subject' => $this->settings['subject'],
'receivers' => explode(',', $this->settings['receiverEmails']),
'html' => '<h1>Redirect Test</h1>',
];
if (MailerUtility::send($mailData)) {
$this->redirect(
null,
null,
null,
null,
$this->settings['redirectPageId']
);
}
}
}
then the mail will be sent only once in TYPO3 8, but twice in TYPO3 9. Without the redirect call, the mail will be sent once in TYPO3 9, too. Maybe someone can tell me more about this behaviour?
Furthermore I have created a little example extension to reproduce this, which you can find in the attachment. The dependencies are set to TYPO3 9, but this example extension works in TYPO3 8, too.
- just install and enable the extension
- include the extension plugin and set some flexform data
- take a look at the frontend rendering of this plugin and submit the example form
Files
Updated by Philipp Faber over 5 years ago
Exactly having the same problem here. I had to add a manual call like this to make it work:
header ("Location: http://". $_SERVER['HTTP_HOST']."/products");
It's a bad hack though. This might have to do sth with the PHP version?
Updated by Ronny Hauptvogel over 5 years ago
@Philipp
I don't think that have something to do with the PHP version, because I have used the same PHP version for both (TYPO3 8 and TYPO3 9, PHP 7.2.X).
Updated by Alexander Schnitzler almost 5 years ago
- Status changed from New to Needs Feedback
I can't reproduce this.
Can you tell me the exact scenario that causes this? I have problems understanding which plugin is on which page and from where you redirect where to.
I'd like to isolate the issues as much as possible.
Updated by Ronny Hauptvogel almost 5 years ago
@Alexander have you tried the attached extension above with TYPO3 9? And if so, did you get one or two mails?
The ticket is a little bit older and I don't know if this behaviour was fixed in the meantime, but I can recheck this.
There was no special scenario:
- Place the extension plugin on a page and set it up
- Open up the page in the frontend
- Submit the form
After that you should be redirected to the page which you have set up in the extension plugin. In my case this was always a another page without any plugin.
Furthermore you should get exactly one mail, but in my case I got always two mails, because the action was called twice if I have used the redirect call.
As I said I will recheck this with the current TYPO3 9 version.
Updated by Ronny Hauptvogel almost 5 years ago
- File example.png example.png added
- File mail-example.png mail-example.png added
@Alexander I have tested the extension against TYPO3 9.5.13 and this behaviour is sadly still present.
So I got two mails instead of one, because the redirectAction will be called twice.
Updated by Riccardo De Contardi almost 5 years ago
- Status changed from Needs Feedback to New
Updated by Alexander Schnitzler over 4 years ago
- Status changed from New to Rejected
- Priority changed from Should have to -- undefined --
So, I digged into this issue and tried the attached extension.
First thing I found is that the action which sends the email is marked as cacheable. In fact all actions in the plugin are cacheable which might not be what you want. As this action either redirects or displays an error I assume, it should not be cached but be dependent on the actual execution.
So much for the theory. It's important to understand why things happen the way they do.
When calling redirect in an action, Extbase (rightfully) assumes that this action shouldn't be cacheable as you don't want to cache the Redirect HTML and just return that when accessing the action without calling it's actual logic.
So, Extbase detects that the action is cachable and therefore converts the USER content object to a USER_INT and redispatches the plugin. That then triggers the second call of the plugin.
Now that we understand the cause, we can think about a solution. The easiest of course is to make your action uncached. That's the correct configuration anyway.
To solve this in Extbase is a bit tricky because we have some kind of race condition here. Extbase only knows that a cached action triggers a redirect as soon as the redirect is triggered. This means, Extbase cannot detect the need to convert the cached plugin to a non-cached one before execution. I am open for ideas but I think that this is something which isn't easily fixable. At least not until Extbase replaces it's inner handling of requests and responses based on a StopActionException instead of a response which then indicates an initiated redirect.
This is something I am working on since TYPO3 10 but the new request/response handling doesn't exist yet. That said, I fear the only solution is the first one, defining actions properly as non-cachable.
I will reject this method for now.
Feel free to add a comment.
Updated by Ronny Hauptvogel over 4 years ago
Ok, thank you for your explanation and your time :).
It's totally fine for me to mark actions with a redirect call as uncachable and now I know what is happening in the background :).
Updated by Michael Stopp over 4 years ago
- Related to Bug #91156: Double Action execution if redirect at its end added
Updated by Bernhard Eckl over 2 years ago
I want to do the following:
if ($GLOBALS['TSFE']->fe_user->user['uid']) {
$this->addFlashMessage('No permission.', '', \TYPO3\CMS\Core\Messaging\AbstractMessage::WARNING);
$this->redirect('list');
}
But just because of the double flash message I have to define the new action as uncacheable. Acutally I removed the redirect and make a condition in the new template not showing the form if not logged in. Is there a better solution I can implement?