WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have a custom 404 page, but dont want serve it for every broken asset that may crop up. Instead I want to just serve the Apache 404 as its much faster. I've found the following htaccess rule that will achieve what Im after:

 RewriteEngine On
 RewriteCond %{REQUEST_FILENAME} !-f
 RewriteRule \.(jpg|jpeg|png|gif|ico|swf|bmp|js|css)$ - [nocase,redirect=404,last] 

But rather then manually placing it in the htaccess file before # BEGIN WordPress I'd like to programatically add the rule via the theme, as Im also trying to get my head around WP's rewrite API. My current rules are below with the crucial line added manually for testing:

# BEGIN WordPress
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /
    RewriteRule ^index\.php$ - [L]
    RewriteRule ^assets/css/(.*) /wp-content/themes/tr_roots_0.4.1/assets/css/$1 [QSA,L]
    RewriteRule ^assets/js/(.*) /wp-content/themes/tr_roots_0.4.1/assets/js/$1 [QSA,L]
    RewriteRule ^assets/img/(.*) /wp-content/themes/tr_roots_0.4.1/assets/img/$1 [QSA,L]
    RewriteRule ^plugins/(.*) /wp-content/plugins/$1 [QSA,L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule \.(jpg|jpeg|png|gif|ico|swf|bmp|js|css)$ - [nocase,redirect=404,last] 
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.php [L]

I've been looking a a lot of examples in and effort to try to achieve this, but they seem inordinately complicated, and not directly applicable. Could someone take a stab at putting me in the right direction? This is what I have (not doing the trick) so far:

function tr_flush_rewrites() {
  global $wp_rewrite;

function tr_add_rewrites() {
     global $wp_rewrite;
      $tr_new_non_wp_rules = array(
       '\.(jpg|jpeg|png|gif|ico|swf|bmp)$' => 'nocase,redirect=404,last',
     $wp_rewrite->non_wp_rules = $tr_new_non_wp_rules + $wp_rewrite->non_wp_rules;
add_action('generate_rewrite_rules', 'tr_add_rewrites');
add_action('admin_init', 'tr_flush_rewrites');

Thanks for looking

share|improve this question
why do you use the /assets/js/* etc rules instead of simply loading them from their location? Also flushing rewrite rules is a very expensive thing to do, your admin area is going to be very slow, you can flush rules by visiting the permalinks page. – Tom J Nowell May 13 '14 at 23:11

This very helpful page is unfortunately kind of burried on the codex:

Basically mod_rewrite_rules hook will do the trick.

function faster_htaccess_rules( $rules ){
$faster_rules = <<<EOD
\n # BEGIN faster Apache 404 rules
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule \.(jpg|jpeg|png|gif|ico|swf|bmp)$ - [R=404,L]
#Use instead for network sites
#RewriteRule \.(jpg|jpeg|png|gif|ico|swf|bmp)$ - [nocase,redirect=404,last]
# END faster Apache 404 rules\n\n
return $faster_rules . $rules;
add_filter('mod_rewrite_rules', 'faster_htaccess_rules');

This prepend/apends the desired rules within the # Begin WordPress block, but outside of <IfModule mod_rewrite.c>. I had been exploring add_rewrite_rule() function, but it wont allow you to modify the RewriteRule flags.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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