Search code examples
apache.htaccessmod-rewritewebserver

Rewriting Specific to more General


I'd like to do a mod_rewrite so that:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

Any requests to users/ goes to index.php?login=(whatever).

RewriteRule ^users/(.+) ?login=$1 [NE,L]

Any other requests, outside of users/, goes to the same place.

RewriteRule ^(.+) users/?login=$1 [NE,L]

but the second part is producing a 500 Internal Server Error

I was asked to explain it, so here are some examples:

  • if "domain.com/aaa/" exists, it goes to "domain.com/aaa/"
  • if "domain.com/bbb/" does not exist, it goes to "domain.com/users/?login=bbb"
  • if "domain.com/ccc.html exists, it goes to "domain.com/ccc.html"
  • if "domain.com/ddd.html does not exist, it goes to "domain.com/users/?login=ddd.html"
  • meanwhile, "domain.com/users/eee" goes to "domain.com/users/?login=eee" since that's the primary condition, and the second condition is a fallback or more general catchall.

Solution

  • This should work. You have to repeat the conditions, they don't carry over to the next rule.

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^users/(.+)$ /users/?login=$1 [NE,L]
    
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.+)$ /users/?login=$1 [NE,L]
    

    Assuming that the /users/ directory does actually exist.

    Or this is more efficient, if you're not running any rules later. It prevents any processing of existing items and avoids doubling up the file-system checks.

    RewriteCond %{REQUEST_FILENAME} -f [OR]
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule ^ - [L]
    
    RewriteRule ^users/(.+)$ /users/?login=$1 [NE,L]
    RewriteRule ^(.+)$ /users/?login=$1 [NE,L]