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, он должен записать некоторую довольно полезную информацию для отладки маршрутизации.