I need to rewrite URL's of this form:




I've done this in my .htaccess:

RewriteCond %{REQUEST_URI}  ^/change-email\.htm$
RewriteCond %{QUERY_STRING} ^e=(.*)&h=(.*)$
RewriteRule ^(.*)$ /change-email/?e=%1&h=%2 [R=301,L]

but this is rewriting:




Note that it is removing the @ symbol. Any suggestions on how to make this work?



http://www.example.com/change-email.htm?e=someone@somewhere.com redirects perfectly


http://example.com/change-email.htm?e=someone@somewhere.com redirects to

http://example.com/change-email/?e=someonesomewhere.com (@ symbol removed)

Here's my complete .htaccess:

RewriteEngine On

RedirectMatch 301 /images/(.*) /wp-content/uploads/$1

RewriteRule ^gv5.htm(.*) /get-v5-key/$1 [R=301,L]
RewriteRule ^change-email\.htm(.*)$ /change-email/$1 [R=301,NE,L]
RewriteRule ^unsubscribe\.htm(.*)$ /unsubscribe/$1 [R=301,NE,L]
RewriteRule ^renew-support\.htm(.*)$ /renew-support/$1 [R=301,NE,L]
RewriteRule ^retrieve-license-code\.htm(.*)$ /retrieve-registration-key/$1 [R=301,NE,L]

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

# END WordPress


Answered my own question.

  • After your update... yes, that is a puzzle. There would not seem to be anything in your .htaccess file that would influence this? Have you checked the network traffic directly, to make sure there isn't an additional response by WordPress?! However, a couple of points about your .htaccess file: You should not mix mod_alias (RedirectMatch) and mod_rewrite as the order of execution is unpredictable from server to server. The mod_alias directive should be converted to mod_rewrite. Also, what are you hoping to match with (.*) at the end of your RewriteRule pattern? – MrWhite Nov 10 '14 at 0:32
  • What happens when you request the URL directly? eg. http://example.com/change-email/?e=someone@somewhere.com – MrWhite Nov 10 '14 at 0:37
  • Hah, that strips out the @ too. Doesn't matter what page or parm name either, it strips out the @. Looks like something in WordPress for sure. – nemmy Nov 10 '14 at 0:41
  • @w3d not quite sure what you mean by the mod_alias part. The (.*) is intended to match anything I guess. I use multiple parms on most pages with long and short form names (to stop links wrapping in emails for example). Can I dispense with it? – nemmy Nov 10 '14 at 0:47
  • Yes, it does look like a WordPress issue. Is the @ actually being removed from the browsers address bar? (In which case WordPress itself would seem to be triggering an external redirect - which should show in the network traffic.) – MrWhite Nov 10 '14 at 0:52

You might be able to resolve this by using the NE (noescape) flag on the RewriteRule directive? However, this is admittedly a little puzzling, as even special characters shouldn't be removed entirely, just converted to their hexcode equivalent. The NE flag allows special characters to be passed through untouched.

However, your current rules can be greatly simplified and improved.

Currently, every single request is being processed by the RewriteRule pattern ^(.*)$, so this is inefficient. You only need to process requests for /change-email.htm, so this can be rewritten as a one liner (no RewriteCond directives are required):

RewriteRule ^change-email\.htm$ /change-email/ [R=301,NE,L]

Note that the RewriteRule is processed first. Only when the RewriteRule pattern matches are the preceeding RewriteCond directives processed.

You don't need to match against the query string since you aren't doing anything with it, except passing it straight through to the substitution - which is the default behaviour.

  • Thanks, that's a great simplification which I've put in place. However, it didn't solve my problem. I've got another re-write rule that is passing the @ character just fine. This one isn't however. I think the problem must lay in Wordpress somewhere. Poking about to see if I can find it! – nemmy Nov 9 '14 at 23:43
  • Yes, I think there must be other factors at play here. By itself the above RewriteRule should work OK, in fact the NE flag is not strictly necessary here. Presumably you are also internally rewriting the request back to the .htm version of the URL? Is that functioning correctly? (Or is that not necessary?) – MrWhite Nov 9 '14 at 23:59
  • OK, I've worked out the cause. I just have no idea of the solution. See notes in question. – nemmy Nov 10 '14 at 0:09

Problem was a WordPress one. It was stripping out the @ when re-writing the non www address to the www address. Problem resolved by adding my old redirect code (which I thought I could dispense with) to top of the .htaccess file:

RewriteCond %{HTTP_HOST} ^example\.com$
RewriteRule (.*) http://www.example.com/$1 [R=301,L]
  • Thanks for the feedback. I'm guessing that WordPress is perhaps (blindly) sanitizing the request URI to prevent XSS attacks?! Anyway, it's better (quicker and less work for your server) to do this type of redirection in .htaccess (or better still in your server config if you have your own server). – MrWhite Nov 10 '14 at 1:24
  • 1
    @w3d The WordPress parameter-handling code is a disaster. I'm not surprised that it corrupted the data, and I would bet that it was unintentional on the part of the WordPress developers. – 200_success Nov 10 '14 at 2:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.