Problem/Motivation

Form state has some methods for making redirects but it doesn't allow for redirecting to external URLs because it doesn't create "trusted" redirects. This is generally fine, a module may want to have more control and redirect to a trusted URL.

Timplunkett gave me the following workaround which works for the moment but seems fragile.

  $form_state->setFormState(['redirect' => new TrustedRedirectResponse("http://example.com")]);

Proposed resolution

Allow settings a redirect directly on the form state. something like
$form_state->setRedirectResponse(new TrustedRedirectResponse());

Remaining tasks

User interface changes

No

API changes

API addition.

Data model changes

No

Comments

neclimdul created an issue. See original summary.

neclimdul’s picture

Issue summary: View changes

derp. functional workaround.

dawehner’s picture

Can't you use the following code:

$form_state->setResponse(new TrustedRedirectResponse());
tim.plunkett’s picture

Status: Active » Closed (works as designed)

Oh you totally can. From FormSubmitter::doSubmitForm():

    // If no response has been set, process the form redirect.
    if (!$form_state->getResponse() && $redirect = $this->redirectForm($form_state)) {
      $form_state->setResponse($redirect);
    }

    // If there is a response was set, return it instead of continuing.
    if (($response = $form_state->getResponse()) && $response instanceof Response) {
      return $response;
    }

And we have test coverage for this in \Drupal\Tests\Core\Form\FormSubmitterTest::testHandleFormSubmissionWithResponses().

neclimdul’s picture

*facepalm*

yched’s picture

Stumbled on this as well.

The confusing thing is that :
- FormState::$redirect / FormStateInterface::getRedirect() are documented as being "a URL or a RedirectResponse",
- FormSubmitter::redirectForm() does contain explicit code to handle the case where $form_state->getRedirect() is a RedirectResponse,

while :
- there is in fact no API way to actually set it to be a RedirectResponse :-)
- and the only way to obtain the desired effect is to use a different API ($form_state->setResponse())