I have a custom route on my site at /search
. This page has a couple of forms on it (defined with FormBase).
When I am logged in, the form appears to work.
When I am anonymous, many many requests occur when I submit and causes a "too many redirects" error in the browser.
Here is my routing.yml
mymodule.search:
path: '/search'
defaults:
_title_callback: 'Drupal\mymodule\Controller\SearchPage::title'
_controller: 'Drupal\mymodule\Controller\SearchPage::build'
requirements:
_permission: 'access content'
Here is one of the forms:
<?php
namespace Drupal\mymodule\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Drupal\Component\Utility\Xss;
use Drupal\Component\Utility\Unicode;
/**
* Class KeywordForm.
*
* @package Drupal\mymodule\Form
*/
class KeywordForm extends FormBase {
/**
* Symfony\Component\HttpFoundation\RequestStack definition.
*
* @var \Symfony\Component\HttpFoundation\RequestStack
*/
protected $requestStack;
/**
* Constructor for our class.
*/
public function __construct(RequestStack $request_stack) {
$this->requestStack = $request_stack;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('request_stack')
);
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'iana_keyword_form';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$keywords = Xss::filter($this->requestStack->getCurrentRequest()->get('keywords'));
$site_ids = $this->requestStack->getCurrentRequest()->get('site_id');
$sort_by = $this->requestStack->getCurrentRequest()->get('sort_by');
$sort_order = $this->requestStack->getCurrentRequest()->get('sort_order');
$form['#attributes']['class'][] = 'search-result__form';
if (!is_array($site_ids)) {
$site_ids = [];
}
$form['keywords'] = [
'#type' => 'textfield',
'#cache' => ['contexts' => ['url.query_args:keywords']],
'#default_value' => Unicode::strlen($keywords) ? $keywords : '',
'#prefix' => '<div class="search-box__input js-search-input">',
'#suffix' => '</div>',
'#attributes' => [
'placeholder' => Unicode::strlen($keywords) ? $keywords : t('Search for...'),
],
];
$form['site_id'] = [
'#type' => 'hidden',
'#value' => $site_ids,
];
$form['sort_by'] = [
'#type' => 'hidden',
'#value' => $sort_by,
];
$form['sort_order'] = [
'#type' => 'hidden',
'#value' => $sort_order,
];
$form['submit'] = [
'#type' => 'submit',
'#value' => $this->t('Search'),
'#attributes' => [
'class' => [
'search-box__button',
],
'data-twig-suggestion' => 'search_results_submit',
],
];
$form['#cache']['contexts'][] = 'session';
return $form;
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$form_state->setRedirect(
'mymodule.search',
[
'keywords' => $form_state->getValue('keywords'),
'site_id' => $form_state->getValue('site_id'),
'sort_by' => $form_state->getValue('sort_by'),
'sort_order' => $form_state->getValue('sort_order'),
],
[
'query' => [
'keywords' => $form_state->getValue('keywords'),
'site_id' => $form_state->getValue('site_id'),
'sort_by' => $form_state->getValue('sort_by'),
'sort_order' => $form_state->getValue('sort_order'),
],
]
);
}
}
It looks like at some point, I hit this bit of code in the FormBuilder class:
// If the form returns a response, skip subsequent page construction by
// throwing an exception.
// @see Drupal\Core\EventSubscriber\EnforcedFormResponseSubscriber
//
// @todo Exceptions should not be used for code flow control. However, the
// Form API does not integrate with the HTTP Kernel based architecture of
// Drupal 8. In order to resolve this issue properly it is necessary to
// completely separate form submission from rendering.
// @see https://www.drupal.org/node/2367555
if ($response instanceof Response) {
throw new EnforcedResponseException($response);
}
Here is what Google Chrome devtools window shows for network activity:
What is going on here, and how can I fix this? I need the values attached to the URL when the form is submitted.
All of the Forms are displayed on the sidebar and header as blocks injecting those forms. Only 3 forms exist, keyword and a simple checkbox filter.
For the life of me, I can't see what is wrong.
The cache_render table is filling up with various search URLs, it should not, though no matter what I set #cache to, it does.