我在将 url 中的电子邮件地址传递到 symfony 应用程序时遇到一些问题。
网址看起来像
example.com/unsubscribe/email/[email protected]
它总是会导致
sfError404Exception
,除非删除句号。在进行了一些谷歌搜索后,我见过的唯一解决方案是 htaccess 由于存在句点而绕过了 url。但是,当我将建议的修复添加到 htaccess 时,如下所示:
# we skip all files with .something
RewriteCond %{REQUEST_URI} \..+$
RewriteCond %{REQUEST_URI} !@.+ #skip email address
RewriteCond %{REQUEST_URI} \.epl$
RewriteCond %{REQUEST_URI} !\.html$
RewriteCond %{REQUEST_URI} !\.rhtml$
RewriteRule .* - [L]
我得到了相同的404。当我直接在url中使用前端控制器时,它也会返回404(
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.
默认情况下,Symfony 将
.
和 /
视为参数分隔符。/some/path/:param.:ext
但对电子邮件地址没有帮助。
幸运的是,您可以通过指定自己的模式来覆盖
.
分隔符。requirements
行添加到您的路由中:
unsubscribeform:
url: /unsubscribe/email/:email
param: { module: subscribe, action: index }
requirements: { email: .+ }
需求中的
.+
是匹配任何内容的正则表达式。 .
匹配任意字符,+
表示匹配一个或多个。
(在 Symfony 1.4 中测试)
我不知道你在 Symfony 中做什么,但澄清以下不是有效的 URL 可能会有所帮助:
example.com/unsubscribe/email/[email protected]
您几乎肯定想要的(这对于所有浏览器都是如此!)是:
http://example.com/unsubscribe/email/me%40example.com
注意:@符号不安全,必须进行编码,.然而符号是安全的(RFC1738)。如果你不转义 @ 符号,它几乎肯定会造成大麻烦,所以(转义 . 几乎肯定不会,但你不需要,所以我不会)。
不转义会出现问题,因为@在传递身份验证参数时被保留作为分隔符(例如http://username:[email protected]/url/)。如果 @ 出现在 URL 中的域后面,一些 URL 解析器会判断出您确实要输入 %40,但其他解析器则不会。
不仅仅是静态编码 @ 符号,您应该在电子邮件地址上使用 PHP 的 URL 编码函数之一(例如“$emailAddress = urlencode($emailAddress);”)以确保地址中的其他字符也能正确转义。不要试图把这件事留到以后或“在你让它工作之后”,从一开始就做,这样可以让你自己和最终用户感到头痛! :-)
注意:在 PHP 中对 URL 进行编码的方法有多种,因此您需要通读 urlencode() 的文档页面,并将其与 rawurlencode() 等其他方法进行比较,以确保它是您真正想要的。
您的问题不在于重写规则。考虑到 Symfony 抛出异常,然后请求将发送到 Symfony。
您可以发布异常的回溯吗?如果您启用了 sf_logging_enabled 它应该记录一些非常有用的信息以调试路由。
我找到的这个问题的解决方案是将数据编码为 Base64。
Base64 字符串是 url 安全的,这就是它们可用于在数据 URL 中对数据进行编码的原因。
let safeDataURL = encodeToBase64(email)