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

  • 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.

  • I know this is from 13 but when you get a chance please mark this as the accepted answer. – DᴀʀᴛʜVᴀᴅᴇʀ Jul 26 '16 at 17:30

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.