Problem/Motivation
Even thought the how redirection is solved in RemotePostWebformHandler is aligned with an old change record that explains how redirection should be solved when "Redirecting when not in context of a controller" it is does not working properly anymore. (Maybe it has this unexpected side effect since Drupal 9.2 when Session management changed: https://www.drupal.org/node/3006306)
Steps to reproduce
When a Webform uses the built-in Remote post handler and..
* the "Custom error response redirect URL" is configured
* and "Use AJAX" feature is disabled on the Webform
* the remote post (API call) fails for any reasons
then the following error gets logged every time
RuntimeException: Failed to start the session because headers have already been sent by "vendor/symfony/http-foundation/Response.php" at line 368. in Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage->start() (line 152 of vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php)
When "Use AjAX" feature is enabled, there is no error like this.
I have also attached a modified Webform Contact form as a POC (exported via Features).
Proposed resolution
Probably the good-old "Redirecting when not in context of a controller" is not working anymore. A simple and clean solution could be throwing a special exception instead in this layer and catching that with a \Symfony\Component\HttpKernel\KernelEvents::EXCEPTION subscriber and performing the redirection there.
Fun fact, Drupal core already has a similar solution in place that in the context of the Form API is considered an unwanted solution/technical dept: #2367555: Deprecate EnforcedResponseException support.
Related classes:
* https://github.com/drupal/core/blob/10.1.2/lib/Drupal/Core/Form/Enforced...
* https://github.com/drupal/core/blob/10.1.2/lib/Drupal/Core/EventSubscrib...
(This solution does not warrant that the exception subscriber only acts on HTML requests!)
This approach could work but it would still generate another noise in the logs, since the remote post handler is called from an entity storage post save hook, therefore when an exception is thrown in that layer it gets automatically logged. We would probably need a workaround for that too and ignore the special "WebformRedirectAfterFailedRemotePostException".
Remaining tasks
User interface changes
API changes
Data model changes
| Comment | File | Size | Author |
|---|---|---|---|
| #4 | 3380667-4.patch | 652 bytes | jrockowitz |
| webfrom_contact_remote_post.tar_.gz | 2.32 KB | mxr576 |
Issue fork webform-3380667
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
mxr576Comment #3
mxr576Comment #4
jrockowitz commentedI can replicate the issue using the example webform.
A lot of people are running into this error. I having a hard time finding a solution.
The attached patch simply exits the entire request which does remove the error.
Comment #5
jrockowitz commentedComment #6
jrockowitz commentedComment #7
jrockowitz commentedThe one-line fix seems safe. Creating an MR for 6.3.x.
Comment #9
jrockowitz commentedComment #14
danflanagan8This change is causing trouble for a webform I have that has handlers configured after the remote post. In my case I have a custom handler that unsets some webform data prior to saving; something similar could be done with the OOTB Action handler. If the remote post runs into an error, the subsequent handlers don't run and we end up saving submission data that we don't want to save.
Luckily, I'm already using an extension of the OOTB remote post handler, so I can just override the handlerError method and be on my way.