I made a mistake in changing my WordPress permalinks, but by the time I’d discovered it my blog had already been indexed. Fixing the permalinks meant breaking those indexed URLs, leading to a bad user experience, but leaving them as is wasn’t really an option.
Last night, after getting 404′d while using Google to search my own blog, I realized I had to do something.
First I looked at Apache mod_rewrite and the URL rewriting guide (as well as this cheat sheet from ilovejackdaniels), Then, frustrated, I found some items in the WordPress Codex, including this one about conflicts between .htaccess files/rules and this about problems with subdirectories inside the WordPress root.
The suggestions in both boil down to creating a specific error document:
Create a file on your website. Call it onerror.html. It can be empty or have just <html></html> in it for all that it matters.
In WordPress’s .htaccess file, add this to the top of the file:
ErrorDocument 401 /path/to/onerror.html
ErrorDocument 403 /path/to/onerror.html
The explanation, though even the poster doesn’t claim to know that it’s the correct explanation, is that the rules are additive, and WordPress is greedy with trying to get requests directed to its own URL parsing routines. The ErrorDocument is supposed to keep more of the processing in mod_rewrite.
But after all that, and only limited success achieving what I wanted, I realized that what I really wanted was not to parse requests before WordPress had a chance at them (as would happen with rewrite rules), but to handle requests that WordPress’ internal rules couldn’t match.
What I ended up doing is writing a tiny plugin that hooked into the template_redirect hook. The short of it is that if WordPress thinks it’s 404′d, and I can divine some meaning from the requested URL, then I redirect to browser (including a
HTTP/1.1 301 Moved Permanently statement). Voila, it works.