Symfony: адрес электронной почты как параметр запроса

У меня возникли проблемы с передачей адреса электронной почты в URL-адресе приложения symfony.

URL выглядит как

example.com/unsubscribe/email/[email protected]

Это всегда приведет к sfError404Exception, за исключением случаев, когда период удален. После выполнения некоторых поисковых запросов единственное решение, которое я еще видел, это то, что htaccess обходит URL из-за присутствующего периода. Однако, когда я добавляю предлагаемое исправление к htaccess, вот так:

# we skip all files with .something
RewriteCond %{REQUEST_URI} \..+$
RewriteCond %{REQUEST_URI} [email protected]+    #skip email address
RewriteCond %{REQUEST_URI} \.epl$
RewriteCond %{REQUEST_URI} !\.html$ 
RewriteCond %{REQUEST_URI} !\.rhtml$
RewriteRule .* - [L]

Я получаю тот же 404. Он также возвращает 404, когда я использую передний контроллер непосредственно в URL-адресе (example.com/index.php/unsubscribe/email/[email protected]). Я попытался поместить экранированную версию непосредственно в адресную строку, например example.com/unsubscribe/me%40example%2Ecom, и это работает, но только в firefox, больше нигде.

Я потратил около 2 часов на форум, отвечая на поиски ада, и у меня заканчиваются идеи.

Любые мысли?

Спасибо.

Обновление: вот соответствующий раздел routing.yml:

unsubscribeform:
  url:  /unsubscribe/email/:email
  param: { module: subscribe, action: index }

Обновить: трассировка стека... похоже, что он не получает никакой информации о маршруте, чтобы перейти ко мне

404 | Not Found | sfError404Exception
Empty module and/or action after parsing the URL "/unsubscribe/email/[email protected]" (/).
stack trace

1. at ()
  in SF_SYMFONY_LIB_DIR/controller/sfFrontWebController.class.php line 44 ...
          41.
          42.       if (empty($moduleName) || empty($actionName))
          43.       {
          44.         throw new sfError404Exception(sprintf('Empty module and/or action after parsing the URL "%s" (%s/%s).', $request->getPathInfo(), $moduleName, $actionName));
          45.       }
          46.
          47.       // make the first request
2. at sfFrontWebController->dispatch()
  in SF_SYMFONY_LIB_DIR/util/sfContext.class.php line 159 ...
         156.    */
         157.   public function dispatch()
         158.   {
         159.     $this->getController()->dispatch();
         160.   }
         161.
         162.   /**
3. at sfContext->dispatch()
  in /home/web/htdocs/index.php line 10 ...
           7. require_once(SF_ROOT_DIR.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'ProjectConfiguration.class.php');
           8.
           9. $configuration = ProjectConfiguration::getApplicationConfiguration(SF_APP, SF_ENVIRONMENT, SF_DEBUG);
          10. sfContext::createInstance($configuration)->dispatch();

11.

Ответ 1

По умолчанию Symfony рассматривает . и / как разделители параметров.
Это упрощает сопоставление URL-адреса:

/some/path/:param.:ext

Но не помогает с адресами электронной почты.

К счастью, вы можете переопределить разделитель ., указав свой собственный шаблон.
Просто добавьте строку requirements ниже к вашей маршрутизации:

unsubscribeform:
  url:  /unsubscribe/email/:email
  param: { module: subscribe, action: index }
  requirements: { email: .+ }

.+ в требовании является регулярным выражением, соответствующим чему-либо. . соответствует любому символу, а символ + соответствует одному или нескольким.

(Протестировано в Symfony 1.4)

Ответ 2

Я не знаю, что вы делаете в Symfony, но может быть ясно, что следующее не является допустимым URL:

example.com/unsubscribe/email/[email protected]

Что вы почти наверняка хотите (и это верно для всех браузеров!):

http://example.com/unsubscribe/email/me%40example.com

Примечание. Символ @не является безопасным и должен быть закодирован. символ безопасен (RFC1738). Если вы не избежите символа @, это почти наверняка вызовет большие неприятности, поэтому (избегая этого, почти наверняка не будет, но вам не нужно, чтобы я этого не сделал).

Проблемы будут возникать, если не избежать этого, потому что @зарезервирован как разделитель при передаче параметров аутентификации (например, http://username:[email protected]/url/). Некоторые синтаксические анализаторы URL будут работать так, чтобы вы действительно намеревались набрать% 40, если @после домена в URL-адресе, но другие не будут.

Вместо того, чтобы просто кодировать символ @статически, вы должны использовать одну из функций кодирования URL-адреса PHP на адрес электронной почты (например, $emailAddress = urlencode ($ emailAddress ); "), чтобы другие символы в адресе также были экранированы надлежащим образом. Не испытывайте соблазнов покинуть это до более позднего времени или" после того, как вы его заработаете" сделайте это с самого начала и спасите себя и конечных пользователей головной болью!: -)

Примечание. Существует несколько способов кодирования URL-адреса на PHP, поэтому вам нужно будет прочитать страницу документации для urlencode() и сравнить ее с другими подходами, такими как rawurlencode(), чтобы убедиться в том, что вы действительно хотите в своем случае.

Ответ 3

Ваша проблема не в правилах перезаписи. Учитывая, что Symfony выбрасывает исключение, запрос обращается к Symfony.

Можете ли вы отправить трассировку для исключения? Если у вас есть sf_logging_enabled, он должен записать некоторую довольно полезную информацию для отладки маршрутизации.