.htaccess remove query string, keeping SEO style url - .htaccess

Question:
Is it possible to clear the %{QUERY_STRING} without breaking any functionality of what I've accomplished in my .htaccess file.
I want to prevent users from adding ?foo=bar to the end of the url overwriting any predefined $_GET vars
(external re_write) Example:
From: example.com/foo/bar/hello/world?test=blah
To: example.com/foo/bar/hello/world
So far I have been able to accomplish this (internally):
From: example.com/foo/bar/hello/world
To: example.com/index.php?foo=bar&hello=world
.htaccess
# To externally redirect /dir/foo.php to /dir/foo
RewriteCond %{THE_REQUEST} ^GET\s.+\.(?:html?|php|aspx?) [NC]
RewriteRule ^(.+)\.php$ /$1 [R=301,L,NC]
# To externally redirect /dir/index to /dir/
RewriteCond %{THE_REQUEST} ^GET\s((.+)?(\/)?)?(index) [NC]
RewriteRule ^(([^/]+/)*)index$ /$1 [R=301,L,NC]
# To internally redirect /dir/foo to /dir/foo.php
RewriteCond %{REQUEST_URI} !\.php$ [NC]
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule . %{REQUEST_URI}.php [L]
# Prevent Rewrite on existing directories, files, and links
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L] #^ - [L]
# To internally rewrite directories as query string
RewriteRule ^([^/=]+)=([^/]*)(/(.+))?\/?$ /$4?$1=$2 [N,QSA]
RewriteRule ^([^/=]+)/([^/=]+)(/(.+))?\/?$ /$4?$1=$2 [N,QSA]
RewriteRule ^([^/=]+)(/(.+))?\/?$ /$3?$1 [N,QSA]
What I've tried:
#if there is a query string
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule (.*) $1? [R=301,L] #remove query string
-
#if there is a query string
RewriteCond %{QUERY_STRING} !=""
RewriteRule (.*) $1? [R=301,L] #remove query string
-
#if there is a query string
RewriteCond %{QUERY_STRING} !=""
RewriteRule ^(.*)$ $1? [R=301,L] #remove query string
I read somewhere, and experienced it, that applying the above breaks anything I've already accomplished. Completely clearing the whole url if they are masked $_GET vars. Even crashes apache 0.o (forgive me for any silly regex or .htaccess code, they're aren't my strong suite and most of it was snippets I found on SO)
is this possible? something I'm doing wrong?
thanks

Try:
RewriteCond %{THE_REQUEST} \?[^\ ]+
RewriteRule (.*) /$1? [R=301,L] #remove query string
You need to match against the actual request because you're building a query string with these rules:
# To internally rewrite directories as query string
RewriteRule ^([^/=]+)=([^/]*)(/(.+))?\/?$ /$4?$1=$2 [N,QSA]
RewriteRule ^([^/=]+)/([^/=]+)(/(.+))?\/?$ /$4?$1=$2 [N,QSA]
RewriteRule ^([^/=]+)(/(.+))?\/?$ /$3?$1 [N,QSA]
When these rules loop around, the %{QUERY_STRING} variable will have stuff in it and your rules will clobber them. If you match against the actual request, your rewrites won't get affected.

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?

Clean URLs in a subfolder

I've read and followed guides and looked for answers to other people's questions, but I'm struggling with url rewriting and htaccess.
I have a subfolder on my site with an index page which handles query strings to bring up dynamic content. I'd like the variable to appear to be a subfolder name e.g.
http://mywebsite.com/subfolder/index.php?v=variable
to
http://mywebsite.com/subfolder/variable
The .htaccess file I've made is at http://mywebsite.com/subfolder/ i.e. the same folder as index.php
How can I get this to work? Any help gratefully appreciated.
You can use these rules inside your /subfolder/.htaccess
RewriteEngine On
RewriteBase /subfolder/
RewriteCond %{THE_REQUEST} \s/subfolder/index\.php\?v=([^&\s]+) [NC]
RewriteRule ^ %1? [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]+)$ index.php?v=$1 [L]
Update (passing two values)
RewriteEngine On
RewriteBase /subfolder/
RewriteCond %{THE_REQUEST} \s/subfolder/index\.php\?v=([^&\s]+)&v2=([^&\s]+)\s [NC]
RewriteRule ^ %1/%2? [R=301,L]
RewriteCond %{THE_REQUEST} \s/subfolder/index\.php\?v=([^&\s]+)\s [NC]
RewriteRule ^ %1? [R=301,L]
# Don't touch to existing files/folders
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
# Rewrite /xxx to /index.php?v=xxx
RewriteRule ^([^/]+)$ index.php?v=$1 [L]
# Rewrite /xxx/yyy to /index.php?v=xxx&v2=yyy
RewriteRule ^([^/]+)/([^/]+)$ index.php?v=$1&v2=$2 [L]
Use this in your .htaccess:
RewriteEngine On
RewriteCond %{QUERY_STRING} v=(.+)$ [NC]
RewriteRule ^ subfolder/%1? [R=301,L,NE]
This grabs the variable using %{QUERY_STRING} and then appends it to the rewrite using %1. You'll see I've added a ? onto the end of the rewrite. That is to stop the original query from appearing on the end of the URL.
I've used R=301 which is a permanent redirect. You might want to changes this to R=302 while you're testing, as this is temporary.
You can view a test of this rule working here: https://htaccess.madewithlove.be?share=7b6832e9-2c05-5d1d-916c-e4dd0f5b1da6
Make sure you clear your cache before testing this.

.htaccess rule, rewrite key in url

Let's say we have an url like this:
http://domain.com/?theme_of_site=parameter_value
http://domain.com/?type_of_site=parameter_value
domain.com - stable/static, always the same
theme_of_site & type_of_site - stable/static, the same when choosen
parameter_value - dynamic
It's like to have always the url's like:
http://domain.com/?theme=parameter_value
http://domain.com/?type=parameter_value
How can I write this in .htaccess?
For the below discussion:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# Start by redirecting the original links from type_of_site= to type=
# Only if the browser's original request contains the strings
RewriteCond %{THE_REQUEST} theme_of_site=([^&]+)
RewriteCond %{THE_REQUEST} type_of_site=([^&]+)
RewriteRule (.*) $1?theme=%1&type=%2 [L,R=301]
RewriteCond %{THE_REQUEST} theme_of_site=([^&]+)
RewriteRule (.*) $1?theme=%1 [L,R=301]
RewriteCond %{THE_REQUEST} type_of_site=([^&]+)
RewriteRule (.*) $1?type=%1 [L,R=301]
# Then, after performing the initial redirects to change the browser
# URL, rewrite the parameters internally
# Match both present:
RewriteCond %{QUERY_STRING} theme=([^&]+)
RewriteCond %{QUERY_STRING} type=([^&]+)
RewriteRule (.*) $1?theme_of_site=%1&type_of_site=%2 [L]
# Then match each individually
RewriteCond %{QUERY_STRING} theme=([^&]+)
RewriteRule (.*) $1?theme_of_site=%1 [L]
RewriteCond %{QUERY_STRING} type=([^&]+)
RewriteRule (.*) $1?type_of_site=%1 [L]
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
Query string parameters need to be captured in RewriteCond. You can match (theme|type) and capture the value, then rewrite it internally using the (theme|type)_of_site in a RewriteRule.
RewriteEngine On
# Match the theme or type paramater in `%1` and capture its value in `%2`
RewriteCond %{QUERY_STRING} (theme|type)=([^&]+)
# Rewrite The parameter name to include _of_site using the values captured above
# for all URLs as captured in $1
RewriteRule (.*) $1?%1_of_site=%2 [L]
The simple example above works only if either of the parameters is specified. If you need to be able to handle both at once like example.com/?type=abc&theme=123 it gets a little more complex:
# Start by redirecting the original links from type_of_site= to type=
# Only if the browser's original request contains the strings
RewriteCond %{THE_REQUEST} theme_of_site=([^&]+)
RewriteCond %{THE_REQUEST} type_of_site=([^&]+)
RewriteRule (.*) $1?theme=%1&type=%2 [L,R=301]
RewriteCond %{THE_REQUEST} theme_of_site=([^&]+)
RewriteRule (.*) $1?theme=%1 [L,R=301]
RewriteCond %{THE_REQUEST} type_of_site=([^&]+)
RewriteRule (.*) $1?type=%1 [L,R=301]
# Then, after performing the initial redirects to change the browser
# URL, rewrite the parameters internally
# Match both present:
RewriteCond %{QUERY_STRING} theme=([^&]+)
RewriteCond %{QUERY_STRING} type=([^&]+)
RewriteRule (.*) $1?theme_of_site=%1&type_of_site=%2 [L]
# Then match each individually
RewriteCond %{QUERY_STRING} theme=([^&]+)
RewriteRule (.*) $1?theme_of_site=%1 [L]
RewriteCond %{QUERY_STRING} type=([^&]+)
RewriteRule (.*) $1?type_of_site=%1 [L]

Htaccess Rewrite single query string

I'm having an issue with a rather old siye. I have some generic URL's with a query string, that i want to 301 redirect, but I don't want to blanket re-direct the urls. I want to choose where each query string is being redirected as there are alot of different categories within the site. For example:
I want to change:
index.php?_a=viewCat&catId=199
to:
/garden-furniture/patio-furniture/garden-benches-garden-seats/cat_199.html
But ill want to change another catid to another URL of my choosing, completely different structure. The problem I'm having is with the code i've got, if I don't have a ? at the end of the destination url, it works, but appends the query string to the end, if I put it on the end, it doesn't redirect at all.
Code I'm using:
RewriteCond %{QUERY_STRING} ^_a=viewCat&catId=199
RewriteRule ^index\.php$ /garden-furniture/patio-furniture/garden-benches-garden-seats/cat_199.html? [L,R=301]
Any help would be appreciated!
EDIT: The rest of my htaccess
RewriteEngine On
RewriteRule ^conservatory/(.*)$ /conservatory-furniture/$1 [R=301,L]
RewriteRule ^dining-room/(.*)$ /dining-room-furniture/$1 [R=301,L]
RewriteRule ^garden/(.*)$ /garden-furniture/patio-furniture/$1 [R=301,L]
RewriteBase /
RewriteCond %{QUERY_STRING} (.*)$
RewriteRule cat_([0-9]+)(\.[a-z]{3,4})?(.*)$ index.php?_a=viewCat&catId=$1&%1 [NC]
RewriteCond %{QUERY_STRING} (.*)$
RewriteRule prod_([0-9]+)(\.[a-z]{3,4})?$ index.php?_a=viewProd&productId=$1&%1 [NC]
RewriteCond %{QUERY_STRING} (.*)$
RewriteRule info_([0-9]+)(\.[a-z]{3,4})?$ index.php?_a=viewDoc&docId=$1&%1 [NC]
RewriteCond %{QUERY_STRING} (.*)$
RewriteRule tell_([0-9]+)(\.[a-z]{3,4})?$ index.php?_a=tellafriend&productId=$1&%1 [NC]
RewriteCond %{QUERY_STRING} (.*)$
RewriteRule _saleItems(\.[a-z]+)?(\?.*)?$ index.php?_a=viewCat&catId=saleItems&%1 [NC,L]
If these are complete URLs, you could anchor the pattern at the start of the string
RewriteRule ^cat_([0-9]+)(\.[a-z]{3,4})?(.*)$ index.php?_a=viewCat&catId=$1&%1 [NC]
this would prevent an URL, which has cat_ inside being rewritten to index.php?....
And since you don't use the trailing optional part, you could eliminate this too
RewriteRule ^cat_([0-9]+) index.php?_a=viewCat&catId=$1&%1 [NC]
Another point is the RewriteCond with query string. If the query string is optional, you could remove the RewriteCond and modify the RewriteRules to
RewriteRule ^cat_([0-9]+) index.php?_a=viewCat&catId=$1 [QSA,NC]
So, all these would become
RewriteRule ^cat_([0-9]+) index.php?_a=viewCat&catId=$1 [QSA,NC]
RewriteRule ^prod_([0-9]+) index.php?_a=viewProd&productId=$1 [QSA,NC]
RewriteRule ^info_([0-9]+) index.php?_a=viewDoc&docId=$1 [QSA,NC]
RewriteRule ^tell_([0-9]+) index.php?_a=tellafriend&productId=$1 [QSA,NC]
RewriteRule ^_saleItems index.php?_a=viewCat&catId=saleItems [QSA,NC,L]

.htaccess redirect if ANY query string is present?

I have the following .htaccess at present.
<IfModule mod_suphp.c>
suPHP_ConfigPath /home/abc/php.ini
</IfModule>
RewriteEngine on
RewriteCond $1 !^(index\.php|media|css|js|images|robots\.txt)
RewriteRule ^(.*)$ /index.php/$1 [L]
AuthType Basic
AuthName "Está dominado!!"
AuthUserFile "/home/abc/.htpasswds/public_html/passwd"
require valid-user
Now the thing is, I would like to, if any query string is found after a / remove that query string.
So:
If we have:
http://www.abc.com/?somethinghere234
It should redirect to:
http://www.abc.com/
If we have:
htpp://www.abc.com/something/?id212
Redirect to:
htpp://www.abc.com/something/
UPDATE:
I've tried this:
TRY A)
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteCond %{REQUEST_URI} !^/index.php
RewriteRule .* /index.php/ [L,QSA]
Hopping that ^(.*)$ will allow anything on the query string...
I've also tried this:
TRY B)
RewriteEngine on RewriteCond $1
!^(index.php|media|css|js|images|robots.txt)
RewriteCond %{QUERY_STRING} ^(.)$
RewriteRule ^(.)$ http://abc.com/ [L]
This returns a 500 internal server error.
TRY C)
RewriteEngine on
RewriteCond $1 !^(index\.php|media|css|js|images|robots\.txt)
#RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^(.*)$ http://abc.com/ [R=302,L]
I confess I'm kind of lost on this .htaccess sintax.
TRY D)
RewriteEngine on
RewriteCond $1 !^(index\.php|media|css|js|images|robots\.txt)
RewriteCond %{REQUEST_URI} !^/
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^(.*)$ http://abc.com/ [R=302,L]
Please advice,
MEM
The following should work:
RewriteCond %{QUERY_STRING} .
RewriteCond %{REQUEST_URI} !^/index.php
RewriteRule ^ /index.php/? [L]
check if you've got something in QUERY_STRING (yours also accepts an empty string)
your check to prevent endless redirect
redirect to wherever you want.
From the Apache documentation:
When you want to erase an existing
query string, end the substitution
string with just a question mark
EDIT (again): As external redirect (you may not even need the second RewriteCond if you don't have any query string at all in your application):
This will tell the client to request the same URI without query string.
RewriteEngine on
# redirect to same URI, but without query string
RewriteCond %{QUERY_STRING} .
RewriteRule ^ %{REQUEST_URI}? [R=301]
# CodeIgniter "magic"
RewriteCond $1 !^(index\.php|media|css|js|images|robots\.txt)
RewriteRule ^(.*)$ /index.php/$1 [L]
I wasn't sure from your description exactly what you were after, so you should keep or remove the second RewriteCond depending on your specific needs.
RewriteEngine On
# Remove the query string with a redirect
RewriteCond %{QUERY_SRING} !=""
# But only if the path ended with a /
# (remove this to redirect anything with a query string)
RewriteCond %{REQUEST_URI} /$
RewriteRule .* /$0? [R=301,L]
# Then perform your internal rewrite
RewriteCond $1 !^(index\.php|media|css|js|images|robots\.txt)
RewriteRule ^(.*)$ /index.php/$1 [L]
Possibly because you have QSA added on there - it means Query String Append.
RewriteCond %{REQUEST_URI} ^(.*/)([^/]+)$
RewriteRule . %1 [R=301,L]

Resources