How to exclude a subdirectory from an Apache URL rewrite condition - apache

I have the following rewrite conditions applied to the root directory of my Apache2 webserver (in apache.conf)
<IfModule mod_rewrite.c>
Options +FollowSymlinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{SERVER_ADDR} !=127.0.0.1
RewriteCond %{SERVER_ADDR} !=::1
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteCond %{SCRIPT_FILENAME} -d [OR]
RewriteCond %{SCRIPT_FILENAME} -f
RewriteRule "(^|/)\." - [F]
</IfModule>
I have a subdirectory, www.domain.com/subdir that I don't want these rewrites to apply to. How can I exclude subdir from these options?

Actually you just need to move up your last rule of skipping files/directories. Try this code:
Options +FollowSymlinks
RewriteEngine On
# if request is not for a file/directory
RewriteCond %{SCRIPT_FILENAME} -d [OR]
RewriteCond %{SCRIPT_FILENAME} -f
# then skip from rewrites
RewriteRule ^ - [L]
# add www to hostname
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{SERVER_ADDR} !=127.0.0.1
RewriteCond %{SERVER_ADDR} !=::1
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# forward all the requests to `/index.php
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]

Right after this line
RewriteEngine On
Add:
RewriteRule ^/subdir/ - [L]
or
RewriteCond %{THE_REQUEST} \ /+subdir/
RewriteRule ^ - [L]

Related

How I can configure correctly Apache rewrite rule for GET request?

I have the following problem when I try to create a user-friendly URL, it returns a 500 error.
Doesn't work
RewriteEngine On
RewriteRule ^page/(.+)$ /page.php?type=$1 [L]
Works this one only if I change the script name
RewriteRule ^page/(.+)$ /change-page.php?type=$1 [L]
Is there any way to keep page.php that redirects to page? Thank you
Here the full .htaccess configuration
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /
# For LocalHost !.php
RewriteCond %{HTTP_HOST} !=localhost
RewriteCond %{HTTP_HOST} !=127.0.0.1
RewriteCond %{REMOTE_ADDR} !=127.0.0.1
RewriteCond %{REMOTE_ADDR} !=::1
## hide .php extension
# To externally redirect /dir/foo.php to /dir/foo
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+)\.php [NC]
RewriteRule ^ %1 [R=302,L]
# To internally forward /dir/foo to /dir/foo.php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*?)/?$ $1.php [L]
RewriteRule ^page/(.+)$ /page.php?type=$1 [L]
Try these rules:
Options +FollowSymLinks -MultiViews
RewriteEngine On
RewriteBase /
# For LocalHost !.php
RewriteCond %{HTTP_HOST} !=localhost
RewriteCond %{HTTP_HOST} !=127.0.0.1
RewriteCond %{REMOTE_ADDR} !=127.0.0.1
RewriteCond %{REMOTE_ADDR} !=::1
## hide .php extension
# To externally redirect /dir/foo.php to /dir/foo
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+)\.php[?\s] [NC]
RewriteRule ^ %1 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^page/([\w-]+)/?$ page.php?type=$1 [L,QSA,NC]
# To internally forward /dir/foo to /dir/foo.php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^(.*?)/?$ $1.php [L]
You should try following rules in your .htaccess file. Please make sure to clear your browser cache before testing your URLs.
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /
# For LocalHost !.php
RewriteCond %{HTTP_HOST} !=localhost
RewriteCond %{HTTP_HOST} !=127.0.0.1
RewriteCond %{REMOTE_ADDR} !=127.0.0.1
RewriteCond %{REMOTE_ADDR} !=::1
## hide .php extension
# To externally redirect /dir/foo.php to /dir/foo
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+)\.php [NC]
RewriteRule ^ %1 [R=302,L]
# To internally forward /dir/foo to /dir/foo.php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*?)/?$ $1.php [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^page/([\w-]+)/?$ page.php?type=$1 [L,NC]

showing error on htaccess address rewrite

i am want to convert url:
/tld/?=com to /tld/com/
my full htaccess code is as below:
Options -Indexes
RewriteEngine On
RewriteBase /
RewriteCond %{THE_REQUEST} \s/+(whois|error)(?:\.php)?[\s?] [NC]
RewriteRule ^ /%1/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !\.(php?|jpg|gif|png|css|js|html|json|xml|eot|svg|ttf|woff|woff2|zip|csv|xlsx|webp|txt|gz|rar)$ [NC]
RewriteRule [^/]$ %{REQUEST_URI}/ [L,R=301,NE]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+?)/?$ $1.php [L]
##### Rewite #####
##RewriteRule ^([^/]*)\$ /tld.php?tld=$1 [L]
RewriteRule ^([^/]+)\$ /tld.php?tld=$1 [L]
but its show 500 error so please help
Have it this way:
Options -Indexes -MultiViews
RewriteEngine On
RewriteBase /
RewriteCond %{THE_REQUEST} \s/+(whois|error)(?:\.php)?[\s?] [NC]
RewriteRule ^ /%1/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !\.(php?|jpg|gif|png|css|js|html|json|xml|eot|svg|ttf|woff|woff2|zip|csv|xlsx|webp|txt|gz|rar)$ [NC]
RewriteRule [^/]$ %{REQUEST_URI}/ [L,R=301,NE]
# ignore all rules below this for files and directories
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{ENV:REDIRECT_STATUS} .
RewriteRule ^ - [L]
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^(.+?)/?$ $1.php [L]
RewriteRule ^tld/([\w-]+)/?$ tld.php?tld=$1 [L,QSA]

How to redirect and in the same time allow any files in directory .htaccess?

currently, I've used this code in my htaccess
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Allow any files or directories that exist to be displayed directly
RewriteCond ${REQUEST_URI} ^.+$
RewriteCond %{REQUEST_FILENAME} \.(gif|jpe?g|png|js|css|swf|php|ico|txt|pdf|xml)$ [OR]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -l
RewriteRule ^ - [L]
Options -Indexes
This will hide my directory and let me view my file, but how to put together redirect (code below) into above code?
RewriteCond %{HTTP_HOST} !^www\.nextdomain\.com$ [NC]
RewriteRule ^(.*)$ https://www.nextdomain.com/$1 [L,R=301]
Okay here the answers after get guide from #Nic3500
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L]
RewriteCond %{HTTP_HOST} !^www\.nextdomain\.com$ [NC]
RewriteRule ^(.*)$ https://www.nextdomain.com/$1 [L]
# Allow any files or directories that exist to be displayed directly
RewriteCond ${REQUEST_URI} ^.+$
RewriteCond %{REQUEST_FILENAME} \.(gif|jpe?g|png|js|css|swf|php|ico|txt|pdf|xml)$ [OR]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -l
RewriteRule ^ - [L]

htaccess mod_rewrite: Simplifying URL

I've been having trouble with the following rewrite. I'm certain mod_rewrite is enabled but not sure where I am going wrong.
I'm try to change the following pattern:
/profile/?userid=157&username=FirstL
to:
/profile/FirstL
I've tried many different rules, but the two I felt were the closest to being correct aren't working at all. My current failures below:
RewriteEngine On
RewriteCond %{THE_REQUEST} \ /profile/+\?userid=$([^&\ ]+)&username=$([^&\ ]+)
RewriteRule ^ /%1? [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)$ /profile/?userid=$1&username=$2 [L,QSA]
 
RewriteEngine On
RewriteRule ^([^/]*)$ /profile/?userid=$1&username=$2 [L]
Full htaccess:
Options +FollowSymLinks -Multiviews
RewriteEngine On
RewriteCond %{THE_REQUEST} \ /profile/+\?userid=$([^&\ ]+)&username=$([^&\ ]+)
RewriteRule ^ /profile/%1/%2? [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^profile/([^/]+)/([^/]+)$ /profile/?userid=$1&username=$2 [L,QSA]
RewriteBase /
DirectorySlash Off
RewriteRule ^admin$ /admin/index.php [L,E=LOOP:1]
RewriteCond %{ENV:REDIRECT_LOOP} !1
RewriteRule ^admin/index.php$ /admin [R=301,L]
# remove .php
RewriteCond %{THE_REQUEST} ^GET\ (.*)\.php\ HTTP
RewriteRule (.*)\.php$ $1 [R=301]
# remove index
RewriteRule (.*)/index$ $1/ [R=301]
# remove slash if not directory
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} /$
RewriteRule (.*)/ $1 [R=301]
# add .php to access file, but don't redirect
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteCond %{REQUEST_URI} !/$
RewriteRule (.*) $1\.php [L]
#Force non-www:
RewriteCond %{HTTP_HOST} www.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
You're losing the userID part of the URL, so when you try to internally rewrite that back, there's nothing there:
RewriteRule ^([^/]+)$ /profile/?userid=$1&username=$2 [L,QSA]
This rule says the first match is the "userid" and the second match is the "username", and you only have one match, and on top of that, it doesn't even begin with "profile".
You'll need to include the userid somewhere in the URL, otherwise there's no way to extract it.
RewriteEngine On
RewriteCond %{THE_REQUEST} \ /profile/+\?userid=([^&\ ]+)&username=([^&\ ]+)
RewriteRule ^ /profile/%1/%2? [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^profile/([^/]+)/([^/]+)$ /profile/?userid=$1&username=$2 [L,QSA]

Htaccess recursive file rewrite

I would like to know if there is a better way to achieve this sort or redirection :
# Apache configuration
Options -Indexes
Options +FollowSymLinks
# Rewrite engine configuration
RewriteEngine On
RewriteBase /
# Force domain www (302 redirect)
RewriteCond %{HTTP_HOST} ^([^\.]+\.[^\.0-9]+)$
RewriteRule ^/?(.*)$ http://www.%1/$1 [L,R=302]
# Request redirection (/module/TLD/module/DOMAIN/module/SUB/data/public/...)
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{HTTP_HOST} ^(.+)\.([^\.]+)\.([^\.0-9]+)$
RewriteCond %{DOCUMENT_ROOT}/module/%3/module/%2/module/%1/data/public/%{REQUEST_URI} -f
RewriteRule ^/?(.+)$ /module/%3/module/%2/module/%1/data/public/$1 [L]
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{HTTP_HOST} ^(.+)\.([^\.]+)\.([^\.0-9]+)$
RewriteCond %{DOCUMENT_ROOT}/module/%3/module/%2/module/%1/data/public/%{REQUEST_URI}/index.php -f
RewriteRule ^/?(.+)/?$ /module/%3/module/%2/module/%1/data/public/$1/index.php [L]
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{HTTP_HOST} ^(.+)\.([^\.]+)\.([^\.0-9]+)$
RewriteCond %{DOCUMENT_ROOT}/module/%3/module/%2/module/%1/data/public/%{REQUEST_URI}/index.html -f
RewriteRule ^/?(.+)/?$ /module/%3/module/%2/module/%1/data/public/$1/index.html [L]
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{HTTP_HOST} ^(.+)\.([^\.]+)\.([^\.0-9]+)$
RewriteCond %{DOCUMENT_ROOT}/module/%3/module/%2/module/%1/data/public/index.php -f
RewriteRule ^/?$ /module/%3/module/%2/module/%1/data/public/index.php [L]
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{HTTP_HOST} ^(.+)\.([^\.]+)\.([^\.0-9]+)$
RewriteCond %{DOCUMENT_ROOT}/module/%3/module/%2/module/%1/data/public/index.html -f
RewriteRule ^/?$ /module/%3/module/%2/module/%1/data/public/index.html [L]
# Request redirection (/module/TLD/module/DOMAIN/data/public/...)
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{HTTP_HOST} ^.+\.([^\.]+)\.([^\.0-9]+)$
RewriteCond %{DOCUMENT_ROOT}/module/%2/module/%1/data/public/%{REQUEST_URI} -f
RewriteRule ^/?(.+)$ /module/%2/module/%1/data/public/$1 [L]
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{HTTP_HOST} ^.+\.([^\.]+)\.([^\.0-9]+)$
RewriteCond %{DOCUMENT_ROOT}/module/%2/module/%1/data/public/%{REQUEST_URI}/index.php -f
RewriteRule ^/?(.+)/?$ /module/%2/module/%1/data/public/$1/index.php [L]
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{HTTP_HOST} ^.+\.([^\.]+)\.([^\.0-9]+)$
RewriteCond %{DOCUMENT_ROOT}/module/%2/module/%1/data/public/%{REQUEST_URI}/index.html -f
RewriteRule ^/?(.+)/?$ /module/%2/module/%1/data/public/$1/index.html [L]
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{HTTP_HOST} ^.+\.([^\.]+)\.([^\.0-9]+)$
RewriteCond %{DOCUMENT_ROOT}/module/%2/module/%1/data/public/index.php -f
RewriteRule ^/?$ /module/%2/module/%1/data/public/index.php [L]
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{HTTP_HOST} ^.+\.([^\.]+)\.([^\.0-9]+)$
RewriteCond %{DOCUMENT_ROOT}/module/%2/module/%1/data/public/index.html -f
RewriteRule ^/?$ /module/%2/module/%1/data/public/index.html [L]
# Request redirection (/module/TLD/data/public/...)
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{HTTP_HOST} ^.+\.([^\.0-9]+)$
RewriteCond %{DOCUMENT_ROOT}/module/%1/data/public/%{REQUEST_URI} -f
RewriteRule ^/?(.+)$ /module/%1/data/public/$1 [L]
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{HTTP_HOST} ^.+\.([^\.0-9]+)$
RewriteCond %{DOCUMENT_ROOT}/module/%1/data/public/%{REQUEST_URI}/index.php -f
RewriteRule ^/?(.+)/?$ /module/%1/data/public/$1/index.php [L]
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{HTTP_HOST} ^.+\.([^\.0-9]+)$
RewriteCond %{DOCUMENT_ROOT}/module/%1/data/public/%{REQUEST_URI}/index.html -f
RewriteRule ^/?(.+)/?$ /module/%1/data/public/$1/index.html [L]
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{HTTP_HOST} ^.+\.([^\.0-9]+)$
RewriteCond %{DOCUMENT_ROOT}/module/%1/data/public/index.php -f
RewriteRule ^/?$ /module/%1/data/public/index.php [L]
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{HTTP_HOST} ^.+\.([^\.0-9]+)$
RewriteCond %{DOCUMENT_ROOT}/module/%1/data/public/index.html -f
RewriteRule ^/?$ /module/%1/data/public/index.html [L]
# Request redirection (/data/public/...)
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{DOCUMENT_ROOT}/data/public/%{REQUEST_URI} -f
RewriteRule ^/?(.+)$ /data/public/$1 [L]
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{DOCUMENT_ROOT}/data/public/%{REQUEST_URI}/index.php -f
RewriteRule ^/?(.+)/?$ /data/public/$1/index.php [L]
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{DOCUMENT_ROOT}/data/public/%{REQUEST_URI}/index.html -f
RewriteRule ^/?(.+)/?$ /data/public/$1/index.html [L]
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{DOCUMENT_ROOT}/data/public/index.php -f
RewriteRule ^/?$ /data/public/index.php [L]
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{DOCUMENT_ROOT}/data/public/index.html -f
RewriteRule ^/?$ /data/public/index.html [L]
# Request redirection (main index file)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ /index.php [L,PT]
For exemple, i redirect a request like http://www.testdomain.com/test/file.css to these possibles paths :
/module/com/module/testdomain/module/www/data/public/test/file.css
/module/com/module/testdomain/data/public/test/file.css
/module/com/data/public/test/file.css
/data/public/test/file.css
If none of these paths are correct, i fall back to /index.php. And, for a request with empty uri, i try to dispatch it like http://www.testdomain.com/index.html or http://www.testdomain.com/index.php. Is there a better way to achieve this sort of rewriting ?
What you are trying to do is verbose and somewhat bizarre, and the bizarre nature is what caught my interest. :-) However, I assume that you must have your reasons.
One advantage of being verbose is that you can define exactly what you want to achieve and in one .htaccess file, so if it aint' broke ... Though you are doing quite a few regexp and stat probes in this logic chain, so I am nore sure that I would recommend this as a general approach.
Also any 'options' would also impact the semantics of what you are trying to achieve, but you could use the recursive nature of the rewrite engine to advantage, for example if /module/TLD/module/DOMAIN/module/SUB/data/public/ then the URI must be interpreted in that context, hence something like
# If we have a file match, then we're done
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
# Skip the four directory rewrites except on first pass
RewriteCond %{ENV:REDIRECT_PASS} !=""
RewriteRule ^ - [E:PASS=OK, SKIP=5]
RewriteRule ^ - [E:PASS=OK]
# Redirect to correct subdirectory
RewriteCond %{HTTP_HOST} ^(.+)\.([^.]+)\.([^.\d]+)$
RewriteCond %{DOCUMENT_ROOT}/module/%3/module/%2/module/%1/data/public/ -d
RewriteRule ^.*$ /module/%3/module/%2/module/%1/data/public/$0 [L]
RewriteCond %{HTTP_HOST} ^.+\.([^.]+)\.([^.\d]+)$
RewriteCond %{DOCUMENT_ROOT}/module/%2/module/%1/data/public/ -d
RewriteRule ^.*$ /module/%2/module/%1/data/public/$0 [L]
RewriteCond %{HTTP_HOST} ^.+\.([^.\d]+)$
RewriteCond %{DOCUMENT_ROOT}/module/%1/data/public/ -d
RewriteRule ^.*$ /module/%1/data/public/$0 [L]
RewriteRule ^.*$ /data/public/$0 [L]
# Etc ... your URIs now include the correct prefix.
Note
A bare ^ always matches
A bare - in the subst string means leave unchanged
Don't include leading / in PER_DIR (eg. .htaccess patterns
$0 is the entire match string -- saves using brackets if you want the whole thing
You don't need to escape . inside a [] selector.
Read up on setting and using environment variables. If you set the variable PASS then this appears as REDIRECT_PASS after an internal redirect.
You will also need to enable rewrite logging and go through your logs to debug this. Have fun.