Search code examples
regexapache.htaccessmod-rewritehosting

Apache .htaccess how to serve "example.com/dir/webpage.html" as "example.com/webpage" (hide directory name)


I have a shared hosting plan on a linux machine, I uploaded my static website with a files structure like the following:

public_html/
  --index.html
  --style.css
  --HTML/
    --webpage.html
  --CSS/
  --JS/
  --MEDIA/

Now I'd like it if visitors could just type in the address bar: example.com/webpage and be able to visit what is actually stored in example.com/HTML/webpage.html.

I read the docs regarding Apache mod_rewrite and also many threads here on SO and others, but I cannot figure out why my .htaccess rules don't work. I am sure I haven't properly understood how it works the routing and redirecting of urls, so I may have made some mistakes that I cannot see.

This is my last attempt at serving example.com/dir/webpage.html as example.com/webpage:

RewriteCond %{DOCUMENT_ROOT}/$1 !-f
RewriteCond %{HTTP_HOST} ^(example.com)$
RewriteRule ^/?(HTML)/(.+)\-?(.+)?(.*)?$ %1/$2 [PT]

Here I simply tried to apply to my case the example available in the introduction page of mod_rewrite:

enter image description here

I also tried a bunch of other stuff, but nothing worked. Said so, I have also been able to do other things on my own, but this one in particular I really cannot figure it out. If anyone can help me I would really appreciate it.

This is my .htaccess file with comments explaining what I am doing, everything works as supposed.

# redirect all www and http traffic to https not-www
<If "%{HTTP_HOST} == 'www.example.com' || %{REQUEST_SCHEME} != 'https'">
    Redirect permanent "/" "https://example.com"
</If>

# defining cache settings for static assets
<ifModule mod_expires.c>
    ExpiresActive On
    ExpiresDefault M29030400
    <FilesMatch "\.(webp|mp4|jpg|jpeg|png|svg+xml|webm|pdf)$">
        ExpiresDefault M29030400
        Header append Cache-Control "public"
    </FilesMatch>
    ExpiresByType text/html M3600
    ExpiresByType text/css M3600
    ExpiresByType text/javascript M3600
    ExpiresByType text/plain M3600
</ifModule>

# what to show when resource is missing
ErrorDocument 404 /HTML/404.html

# block requests to files :
<Files ".user.ini"> 
    Require all denied
</Files>
<Files ".htaccess"> 
    Require all denied
</Files>
<Files "php.ini"> 
    Require all denied
</Files>
<Files "error_log"> 
    Require all denied
</Files>

# enable option to rewrite URLs and display them to something nicer
Options +FollowSymLinks -MultiViews 
#Start the engine rewriting
RewriteEngine on

# Prevent hotlinking
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?example\.com/?(.*)?$ [NC]
RewriteRule .*\.(jpg|jpeg|gif|png|bmp|mp4|webp|svg)$ - [F,NC]

# redirect permanently example.com/index.html to example.com
RewriteRule ^index(.*)?$ / [L,R=301]

# the following is code I found on SO to strip html tags
# Remove .html (or htm) from visible URL (permanent redirect)
RewriteCond %{REQUEST_URI} ^/(.+)\.html?$ [NC]
RewriteRule - /%1 [L,R=301]
# Quietly point back to the HTML file (temporary/undefined redirect):
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule - %{REQUEST_URI}.html [END]

Solution

  • So, I was actually able to fix the issue on my own. I'll leave the last piece of code to integrate with the .htaccess above:

    RewriteCond %{REQUEST_URI} !^/dir/
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.+)$ /dir/$1.html
    

    Where dir is the name of the directory to hide.

    EDIT: Also, this piece of code is useless in this case and can be deleted:

    # the following is code I found on SO to strip html tags
    # Remove .html (or htm) from visible URL (permanent redirect)
    RewriteCond %{REQUEST_URI} ^/(.+)\.html?$ [NC]
    RewriteRule - /%1 [L,R=301]
    # Quietly point back to the HTML file (temporary/undefined redirect):
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME}.html -f
    RewriteRule - %{REQUEST_URI}.html [END]
    

    Hopefully it will also be of some degree of usefulness to someone else.