Removing query_string from wildcard subdomain rewrite - .htaccess

My goal is to point:
http://xyz.domain.com/abc to http://www.domain.com/dir/file.php?var=xyz
(In other words, anything with http://_____.domain.com/abc would read from http://www.domain.com/dir/file.php?var=_____.)
I used this in my .htaccess file at the root of the website (http://www.domain.com/.htaccess):
RewriteCond %{HTTP_HOST} !^www.domain.com [NC]
RewriteCond %{HTTP_HOST} ^(www.)?([a-z0-9-]+).domain.com [NC]
RewriteRule ^abc/*$ dir/file.php?var=%2 [NC,L]
It worked, but then it automatically redirected to http://xyz.domain.com/abc/?var=xyz when I just wanted http://xyz.domain.com/abc without the query string showing up.
I considered adding a %{QUERY_STRING} line to the above but got stuck when trying to match the two RewriteCond's vars to each other.
Then I found this at http://www.askapache.com/htaccess/modrewrite-tips-tricks.html#Removing_Query_String
RewriteCond %{THE_REQUEST} ^GET\ /.*\;.*\ HTTP/
RewriteCond %{QUERY_STRING} !^$
RewriteRule .* http://www.askapache.com%{REQUEST_URI}? [R=301,L]
...which I'm guessing it's the right code to get rid of something like this on a regular domain? I tried making it suitable for wildcard subdomains by changing it to this:
RewriteCond %{THE_REQUEST} ^GET\ /.*\;.*\ HTTP/
RewriteCond %{QUERY_STRING} !^$
RewriteCond %{HTTP_HOST} !^www.domain.com [NC]
RewriteCond %{HTTP_HOST} ^(www.)?([a-z0-9-]+).domain.com[NC]
RewriteRule .* http://%2.domain.com%{REQUEST_URI}? [R=301,L]
But it doesn't work. SO...can anyone help?

There's a Module called mod_dir that redirects the browser when it thinks you are trying to access a directory but are missing the trailing slash. When I test on my apache it only happens when the directory actually exists, I get redirected with a trailing slash, but the rewrite happens and I see the query string. Try forcing, internally, the trailing slash and when rewriting to dir/file, expressly use a trailing slash:
# Force trailing slash when accessing /abc without one
RewriteRule ^abc$ /abc/ [NC,L]
# these are the same
RewriteCond %{HTTP_HOST} !^www.domain.com [NC]
RewriteCond %{HTTP_HOST} ^(www.)?([a-z0-9-]+).domain.com [NC]
# Match against a trailing slash
RewriteRule ^abc/$ dir/file.php?var=%2 [NC,L]

Related

.htaccess Display shorter url in address bar that points to a real server folder path

I'm trying to shorten my urls in the address bar and for Google indexation purposes. For example, a real server directory path
http://www.somewebsite.com/path1/path2/path3/
would display
http://www.somewebsite.com/path3/
I've found many similar topics but no answer that seems to work for this particular case.
I have for example:
RewriteRule ^path3(.*)$ path1/path2/path3$1 (tried with with [L], [QSA,l], [R=301,...]...)
But this simply does a redirect and does not keep the short address in the browser.
My .htaccess file looks as follow:
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
# Use UTF-8 encoding for anything served as `text/html` or `text/plain`.
AddCharset UTF-8 .html
# Force www.
RewriteCond %{HTTP_HOST} !=""
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTPS}s ^on(s)|
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# remove .php; use THE_REQUEST to prevent infinite loops
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]
#Trying to have a shorter url in address bar
RewriteRule ^path3(.*)$ path1/path2/path3$1
Converting my comments to answer so that solution can be easily found for the problem stated.
There are couple of issues with the rules shown in question:
Since target paths are pointing to an existing directory and you don't have trailing / in target it is causing an external redirect by mod_dir module of Apache that appends a / at the end of directory path and performs a 301 redirect.
Incorrect positioning of rule.
Not critical but missing L and NE (no escape) flag from redirect rules which may cause problems for some cases.
With those suggestion final working .htaccess can be like this:
# Use UTF-8 encoding for anything served as `text/html` or `text/plain`.
AddCharset UTF-8 .html
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
# Force www.
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTPS}s ^on(s)|
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L,NE]
# remove .php and index; use THE_REQUEST to prevent infinite loops
RewriteCond %{THE_REQUEST} \s/+(.*?/)?(?:index|(\S+?))\.php[/\s?] [NC]
RewriteRule ^ /%1%2 [R=301,L,NE]
# remove slash if not directory
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} /$
RewriteRule (.*)/$ $1 [R=301,L,NE]
# rewrite path3/ to /path1/path2/path3/
RewriteRule ^path3/.*$ path1/path2/$0 [L,NC]
# add .php to access file, but don't redirect
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteCond %{REQUEST_URI} !/$
RewriteRule ^(.*?)/?$ $1.php [L]
The example you provided works for myself on my own test website, using the below .htaccess rewrite:
RewriteEngine On
RewriteRule ^test2.txt/?$ /test.txt
This lets me have an optional trailing slash, and show the content of test.txt on /test2.txt.
Assuming your rewrite engine is on, can you replicate this behaviour? What version of Apache are you using? Is the path handled by a CMS at all?

Remove trailing slash using .htaccess for multiple urls

Last week I have posted something similar like the question whereas I wanted to know how to remove trailing slash using .htaccess for a particular page and rest pages will be redirect with trailing slash.
abc.com/demo/ should redirect to abc.com/demo
And I got the solution as following.
RewriteEngine on
RewriteCond %{REQUEST_URI} ^/demo/ [NC]
RewriteRule ^demo/$ /demo [L,R]
RewriteCond %{REQUEST_URI} !^/demo [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)([^/])$ /$1$2/ [L,R=301]
But now I need for multiple urls. eg. demo2, demo3, demo4 etc, so in those scenario how will be the code, need suggestion.
abc.com/demo2/ redirect to abc.com/demo2
abc.com/demo3/ redirect to abc.com/demo3
abc.com/demo4/ redirect to abc.com/demo4
To remove traling slash from multiple uris ,you could a regular expression capture-group that matches more then one values at one time something like the following :
RewriteCond %{REQUEST_URI} ^/(demo1|demo2|demo3|demo4)/$ [NC]
RewriteRule /$ /%1 [L,R]
The %1 in the above rule is a RewriteCond backreference and it holds the value matched inside
(demo1|demo2|......) regex pattern ie: demo1 .
You can use the following htaccess to remove and add traling slashes .
RewriteEngine on
# remove traling slash from spacifc uris
RewriteCond %{REQUEST_URI} ^/(demo1|demo2|demo3|demo4)/$ [NC]
RewriteRule /$ /%1 [L,R]
# add traling slash to other uris except the spacifc ones
RewriteCond %{REQUEST_URI} !^/(demo1|demo2|demo3|demo4)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)([^/])$ /$1$2/ [L,R=301]
Make sure to clear your browser cache before testing this.

Disable the start slash being removed in url rewrites

Allright so I have a website where I want traffic to go from
http -> https
non www -> www
So the final url should look like: https://www.x.net
I set up some rewrite rules in my htaccess, which look like the following:
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI}$1 [R=301,L]
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI}$1
It works fine, everything gets redirected but the only problem is the following type of urls.
x.com/help
What happens is it will redirect to
https://www.x.comhelp
It removes the slash between com and help, I couldn't find an answer on Google so that's why I though, maybe my StackOverflow friend could help me out :)
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI}$1 [R=301,L]
You should not use both the %{REQUEST_URI} server variable and the $1 backreference together. Use one or the other, see below...
You would need to change your directives to the following. This uses a backreference to the RewriteRule pattern which notably excludes the slash, so this must be included in the substitution:
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule (.*) https://www.%{HTTP_HOST}/$1 [R=302,L]
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}/$1 [R=302,L]
Alternatively, use the %{REQUEST_URI} server variable instead. (This includes the slash prefix.)
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=302,L]
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L]
Change the 302 (temporary) redirect to a 301 (permanent) redirect when you are sure it's working OK. (301 redirects are cached by the browser, so make sure your caches are cleared before testing.)

.htaccess makes subdirectory appear in URL

I've been searching for this but I'm really newbie with .htacces (I find it a hell) and I cannot get the way to solve this.
I have the root folder in my server, redirecting the default domain URL to the folder "web". I have another folder, let's say subfold, and inside this, I have another folder: mobile.
What I want is that if someone types www.adomain.com it goes to root/subfold, without showing the subfold. I've done it this way:
RewriteEngine on
Options +FollowSymLinks
RewriteBase /
RewriteCond %{HTTP_HOST} ^www\.adomain\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/subfold/ [NC]
RewriteRule (.*)$ /subfold/$1 [L]
RewriteCond %{HTTP_HOST} www\.maindomain\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/web/ [NC]
RewriteRule (.*)$ /web/$1 [L]
However, when I go to www.adomain.com/mobile it shows in the URL www.adomain.com/subfold/mobile/
My aim is that if I go to the mobile subfolder, in the URL it should show www.adomain.com/mobile
Obviously, I would like not to have to write a redirect everytime I add a subfolder, it it was possible.
How should I do that?
Thanks for your time and help!
You're getting redirected because your accessing a directory without a trailing slash. The mod_dir module, on by default, will redirect the browser and add a trailing slash if someone tries to access a directory without a trailing slash. This is because there is a information disclosure issue with indexing directories. You can either turn this off:
DirectorySlash Off
and risk having the contents of your directories get listed, even if there's an index.html file. Or add a bunch of rules to ensure there's a trailing slash:
RewriteEngine on
Options +FollowSymLinks
RewriteBase /
# redirect for trailing slash:
RewriteCond %{HTTP_HOST} ^www\.adomain\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/subfold/ [NC]
RewriteCond %{DOCUMENT_ROOT}/subfold%{REQUEST_URI} -d
RewriteRule (.*[^/])$ /$1/ [L,R=301]
RewriteCond %{HTTP_HOST} ^www\.adomain\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/subfold/ [NC]
RewriteRule (.*)$ /subfold/$1 [L]
# redirect for trailing slash
RewriteCond %{HTTP_HOST} www\.maindomain\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/web/ [NC]
RewriteCond %{DOCUMENT_ROOT}/web%{REQUEST_URI} -d
RewriteRule (.*[^/])$ /$1/ [L,R=301]
RewriteCond %{HTTP_HOST} www\.maindomain\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/web/ [NC]
RewriteRule (.*)$ /web/$1 [L]

Force trailing slash

I'm trying to force a trailing slash to my URLs, but I can't make it work the way I want. This is my .htaccess file:
RewriteEngine on
#Force trailing slash
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !index.php
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ /$1/ [L,R=301]
#Subdomains
RewriteCond %{HTTP_HOST} !^www\.example\.com [NC]
RewriteCond %{HTTP_HOST} ^([^/.]+)\.example\.com$
RewriteCond $1/%1 !^([^/]+)/\1$
RewriteRule ^/([^/]+)? /%1%{REQUEST_URI} [L]
#Point everything to page.php
RewriteCond %{HTTP_HOST} !^www\.example\.com [NC]
RewriteCond $1 !^(.*).(php|css|js|png|jpg|gif|htm|html)$
RewriteRule ^(.*)$ page.php?q=$1 [L,NC]
If I go to "en.example.com/about" I'm redirected to "en.example.com/en/about/", which is an invalid page.
How can I make this work?
The problem here is that the L flag causes a restart of the rewriting process with the rewritten URL (I’ve already told you that, didn’t I?):
Remember, however, that if the RewriteRule generates an internal redirect (which frequently occurs when rewriting in a per-directory context), this will reinject the request and will cause processing to be repeated starting from the first RewriteRule.
Now when /about is requested, the first rule get’s applied and redirects to /about/. The subsequent request of /about/ is then processed, at first the third rule is applied and the URL path is rewritten to /page.php. So far, so good.
But now the internal redirect takes place and the rewriting process is restarted with the new URL path /page.php. This is then fetched by the first rule again and redirected externally to /page.php/.
The second rule shouldn’t be applied at all as the pattern ^/ should never match as the per-directory path prefix is removed before testing the pattern when using mod_rewrite in an .htaccess file:
When using the rewrite engine in .htaccess files the per-directory prefix (which always is the same for a specific directory) is automatically removed for the pattern matching and automatically added after the substitution has been done.
But these rules should work:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .*[^/]$ /$0/ [L,R=301]
RewriteCond %{HTTP_HOST} ^([^/.]+)\.example\.com$ [NC]
RewriteCond %1 !=www [NC]
RewriteCond $0/%1 !^([^/]+)/\1$
RewriteRule ^[^/]* /%1%{REQUEST_URI} [L]
RewriteCond %{HTTP_HOST} !=www.example.com [NC]
RewriteCond $1 !.*\.(php|css|js|png|jpg|gif|htm|html)$
RewriteRule .* page.php?q=$0 [L]

Resources