I'm having some issues with passing an email address in a url to a symfony app.
The url looks like
example.com/unsubscribe/email/[email protected]
It will always result in a sfError404Exception
, except when the period is removed. After doing some googling around, the only solution I've yet seen is that htaccess is bypassing the url because of the period present. However, when I add the suggested fix to htaccess, like so:
# 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]
I get the same 404. It also returns 404 when I use the front controller directly in the url (example.com/index.php/unsubscribe/email/[email protected]
). I've tried putting the escaped version directly into the address bar, eg example.com/unsubscribe/me%40example%2Ecom
and this works, but only in firefox, nowhere else.
I've spent about 2 hours in forum answer googling hell at this point and I'm running out of ideas.
Any thoughts?
Thanks.
Update: Here is the relevant section of the routing.yml:
unsubscribeform:
url: /unsubscribe/email/:email
param: { module: subscribe, action: index }
Update: Stack trace ... looks like its not getting any route information to go on to me
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.
By default, Symfony treats .
and /
as parameter separators.
That makes it very easy to match a url like so:
/some/path/:param.:ext
But doesn't help with email addresses.
Fortunately, you can override the .
separator by specifying your own pattern.
Just add the requirements
line below to your routing:
unsubscribeform:
url: /unsubscribe/email/:email
param: { module: subscribe, action: index }
requirements: { email: .+ }
The .+
in the requirement is a regular expression matching anything. The .
matches any character, and the +
means match one-or-more.
(Tested in Symfony 1.4)
I don't know what you are doing in Symfony but it may help to be clear that the following is not a valid URL:
example.com/unsubscribe/email/[email protected]
What you almost certainly want (and this is true for all browsers!) is:
http://example.com/unsubscribe/email/me%40example.com
Note: The @ symbol is not safe and must be encoded, the . symbol is safe however (RFC1738). If you don't escape the @ symbol it will almost certainly cause big trouble so (escaping the . almost certainly won't, but you don't need to so I wouldn't).
Problems will occur with not escaping it because @ is reserved as a separator when passing authentication parameters (e.g. http://username:[email protected]/url/). Some URL parsers will work out that you really meant to type %40 if @ occurs after the domain in the URL, but others won't.
Rather than just encoding the @ symbol statically you should use one of PHP's URL encoding functions on the email address( e.g. "$emailAddress = urlencode($emailAddress);") to ensure other characters in the address are also escaped properly. Don't be tempted to leave this till later or 'after you get it working' do it from the start and save yourself and the end users a headache! :-)
NB: There are several ways to encode URL's in PHP, so you will need to read through the documentation page for urlencode() and compare it with other approaches like rawurlencode() to be sure it's what you really want in your case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With