Search code examples
.htaccessmod-rewritelitespeed

.htaccess rewrite requests to a subdirectory if they exist, otherwise redirect to a subdomain


I want something very specific to happen with my .htaccess file, but I'm not sure if it's possible. I want links like example.com/ExampleFile.txt to be forwarded to example.com/Other/ExampleFile.txt (as I'm about to move everything into the "Other" directory to do a cleanup of the root directory.) Then if no file is detected in the "Other" directory, I'd like the path that the user originally typed (example.com/ExampleFile.txt) to be sent through to subdomain.example.com/ExampleFile.txt.

Please let me know if this is possible, and if so, what code do I need to add to my .htaccess file? Note that I use LiteSpeed, not Apache.

I can already do the last part with the following piece of code:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ https://subdomain.example.com%{REQUEST_URI} [R=302,L]

Solution

  • Add the following rewrite before your existing redirect to test whether the request maps to a file in the /Other subdirectory before rewriting the request if it is:

    # Rewrite request to the "/Other" subdirectory
    #  - only if the request maps to a file or directory there
    RewriteCond %{DOCUMENT_ROOT}/Other/$1 -f [OR]
    RewriteCond %{DOCUMENT_ROOT}/Other/$1 -d
    RewriteRule (.+) Other/$1 [L]
    

    NB: If the same file exists in both the root (or rather, outside of the "/Other" subdirectory) then the one inside the /Other subdirectory wins.

    If you only want to rewrite actual files and not directories then remove the second condition and OR flag.

    Presumably all requests to the root should be rewritten to /Other/ (since this exists as a directory) so this should be performed unconditionally:

    # Rewrite root to "/Other/"
    RewriteRule ^$ /Other/ [L]
    

    And your existing redirect to subdomain.example.com follows these rewrites.


    UPDATE:

    But I did notice that I can't access files without the file extensions using this method. [...] Any ideas why I can't access files without the extension when using this method? I have a file called ExampleFile.txt in /Other which can be seen at example.com/ExampleFile.txt but not example.com/ExampleFile.

    Because we are having to check whether the requested URL maps to a file (or directory) in the subdirectory before rewriting the URL.

    If you insist on having extensionless URLs for different types of resources (.txt, .html, images, etc.) then you will need to manually check each file extension for which you permit to be extensionless (in much the same way as you have already done for requests outside of the stated subdirectory).

    For example:

    # For files that already have an extension OR directories...
    # NB: Directories could be requested initially with or without the trailing slash
    # Rewrite request to the "/Other" subdirectory
    #  - only if the request maps directly to a file or directory there
    RewriteCond %{DOCUMENT_ROOT}/Other/$1 -f [OR]
    RewriteCond %{DOCUMENT_ROOT}/Other/$1 -d
    RewriteRule (.+) Other/$1 [L]
    
    # Check for ".txt" files...
    RewriteCond %{REQUEST_URI} !(\.\w{2,4}|/)$
    RewriteCond %{DOCUMENT_ROOT}/Other/$1.txt -f
    RewriteRule (.+) Other/$1.txt [L]
    
    # Check for ".html" files...
    RewriteCond %{REQUEST_URI} !(\.\w{2,4}|/)$
    RewriteCond %{DOCUMENT_ROOT}/Other/$1.html -f
    RewriteRule (.+) Other/$1.html [L]
    
    # Check for ".php" files...
    RewriteCond %{REQUEST_URI} !(\.\w{2,4}|/)$
    RewriteCond %{DOCUMENT_ROOT}/Other/$1.php -f
    RewriteRule (.+) Other/$1.php [L]
    
    # Check for ".jpg" files...
    RewriteCond %{REQUEST_URI} !(\.\w{2,4}|/)$
    RewriteCond %{DOCUMENT_ROOT}/Other/$1.jpg -f
    RewriteRule (.+) Other/$1.jpg [L]
    
    # etc.