Forbiden rule with a condition in htaccess - .htaccess

I have this rule to forbidden URLs that not contain "view-ports" string:
RewriteCond %{THE_REQUEST} !view-ports
RewriteRule ^ - [F]
How can I change it to forbidden only URLs with the condition above and not end with a "/"
So for example the URLs below should be allowed:
https://www.sample.com/list/
https://www.sample.com/list/cities/
https://www.sample.com/view-ports?q=832
https://www.sample.com/data/view-ports?l=131
.
.
.
but for example the URLs below should be forbidden:
https://www.sample.com/list
https://www.sample.com/list/cities
https://www.sample.com/q=1312324
https://www.sample.com/data/l=131
.
.
.
I tried:
RewriteCond %{REQUEST_URI} !/$
RewriteCond %{THE_REQUEST} !view-ports
RewriteRule ^ - [F]
It works but the problem is it forbiddens the root itself also:
https://www.sample.com/

I managed to find the answer by myself.
RewriteCond %{REQUEST_URI} !/$
RewriteCond %{THE_REQUEST} !view-ports
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ - [F]
That solved the root directory 403 error.

Related

Redirect / remove links by question mark

I need to remove all links that have a question mark. These are links not indexed by Google.
I can't find a solution to this problem.
Example:
http://example-page.pl/pl?start=18 --> http://example-page.pl/pl
HTACCESS:
...
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
RewriteCond %{THE_REQUEST} ^GET.*index\.php [NC]
RewriteRule (.*?)index\.php/*(.*) /$1$2 [R=301,NE,L]
...
Use a RewriteCond to check if there is a query string, then using RewriteRule redirect only the first part of the url.
Input: http://example-page.pl/pl?start=18
RewriteCond %{QUERY_STRING} .
RewriteRule ^(.*)$ /$1? [R,L]
Output: http://example-page.pl/pl
You can view this working via htaccess.madewithlove.be.

htaccess no-trailing-slash policy: non existing urls (404) should not redirect

If I open a non existing url on my site like www.domain.de/abcde/ (with trailing slash) the url redirects to www.domain.de/abcde (without trailing slash) and opens the 404 site after.
But the 404 site should come directly when the url does not exist (without redirecting for the non-trailing-slash policy).
What do I need to add to my htaccess? Thank you!
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [R=301,L]
------
starkeens suggestion does only work on a clean htaccess, but I got some more code. It does not work together with the other lines. All the code:
RewriteEngine on
RewriteBase /
# redirect urls without www. to url with www.
RewriteCond %{HTTP_HOST} ^domain\.de$
RewriteRule ^(.*)$ http://www.domain.de/$1 [L,R=301]
# hide the suffix of urls
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(.+)\.html\ HTTP/
RewriteRule (.*).html$ /$1 [R=301,L]
# start redirect everything to the subfolder
RewriteCond %{HTTP_HOST} ^(www\.)?domain\.de [NC]
# except these folders:
RewriteCond %{REQUEST_URI} !^/downloads [NC]
RewriteCond %{REQUEST_URI} !^/cms [NC]
RewriteCond %{REQUEST_URI} !^/vorschau [NC]
RewriteCond %{REQUEST_URI} !^/domain/.*$
RewriteRule ^(.*)$ /subfolder/$1
# end redirect everything to the subfolder
# no-trailing-slash policy
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [R=301,L]
Any new suggestions? :)
TRY :
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ - [R=404,L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [R=301,L]
Finally i got a solution that seems to work.. maybe anyone got the same issue and needs the code. Comments for optimization are welcome!
# trailing Slashes
# to enforce a no-trailing-slash policy with subfolder
# is the request for a non-existent file?
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# if so, skip the next RewriteRule
RewriteRule .? - [S=1]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [R=301,L]
Now only existing files get the redirect of my no-trailing-slash policy. Non existing files aren't redirected and occur a 404 page directly, as wished.

htaccess rewrite and pass top directory name

Below works for passing directory names while doing a htaccess rewrite:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/([^/]+) /index.php?xa=$1&xb=$2&xc=$3&xd=$4 [NC]
RewriteRule ^([^/]+)/([^/]+)/([^/]+) /index.php?xa=$1&xb=$2&xc=$3 [NC]
RewriteRule ^([^/]+)/([^/]+) /index.php?xa=$1&xb=$2 [NC]
However when adding to above, the final line to also catch server.com/whatever situations:
RewriteRule ^([^/]+) /index.php?xa=$1 [NC]
I get a 500 server error...
How come?..
Thanks!
There are 2 problems:
RewriteCond before first rule is being applied to very next RewriteRule only
No anchors $ in your regex for RewriteRule.
Here is the fixed code:
RewriteEngine On
# ignore all rules below from files and directories
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/([^/]+)/?$ /index.php?xa=$1&xb=$2&xc=$3&xd=$4 [L,QSA]
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/?$ /index.php?xa=$1&xb=$2&xc=$3 [L,QSA]
RewriteRule ^([^/]+)/([^/]+)/?$ /index.php?xa=$1&xb=$2 [L,QSA]

%2520 (Double space) in URL for URL with spaces

My URL structure is like
http://www.example.com/folder/index.php?dir=dir1
To be able to access it from
http://www.example.com/folder/dir1
and at the same time redirect the 1st URL to 2nd one, my htaccess (in 'folder') is
Options +FollowSymLinks
RewriteEngine On
RewriteBase /folder
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule .* - [L]
RewriteCond %{QUERY_STRING} ^dir=(.*)$ [NC]
RewriteRule ^ %1? [L,R=301]
RewriteRule ^(.+)/? index.php?dir=$1 [L,QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*)$ index.php?dir=$1 [L,QSA]
The trouble is that if any directory name in URL contains a 'space', the URL shows %2520 instead of the 'space'.Please advice in modifying the htaccess so it shows %20 or preferrably a simple 'space'?
try adding a NE on the redirect ie
RewriteRule ^ %1? [L,R=301,NE]
EDIT
Since you've read my htaccess, do you see any possiblity of shortening it further
Below are a couple of comments
Options +FollowSymLinks
RewriteEngine On
RewriteBase /folder
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule .* - [L]
RewriteCond %{QUERY_STRING} ^dir=(.*)$ [NC]
RewriteRule ^ %1? [L,R=301]
#this looks redundant with last rule, and could be deleted?
RewriteRule ^(.+)/? index.php?dir=$1 [L,QSA]
#this says if not an existing file
RewriteCond %{REQUEST_FILENAME} !-f
#and this says if it IS an existing directory
#Is this what you wanted, or should it be not an existing directory i.e
# RewriteCond %{REQUEST_FILENAME} !-d instead
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*)$ index.php?dir=$1 [L,QSA]

URL Rewrite Including Trailing Slash If Not Present

I've got this RewriteRule to work.
RewriteBase /my/path/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /my/path/index.php [L]
So URLs with a trailing slash work. http://localhost/my/path/foo/bar/
The problem is that URLs without the trailing slash will break relative links. Plus it dosen't look good.
This reaches the maximum number of internal redirects.
RewriteRule ^/my/path/(.*[^/])$ $1/ [R]
RewriteRule . /my/path/index.php [L]
And this will do... http://localhost/my/path/index.php/bar/
RewriteRule . /my/path/index.php
RewriteRule ^/my/path/(.*[^/])$ $1/ [R,L]
Any Ideas or solutions?
The confusing feature of mod_rewrite is that, after an internal redirect, even one qualified with [L], the entire set of rules is processed again from the beginning.
So you redirect a nonexistent path to index.php, but then the rules for adding a slash kick in and you don't get the result you want.
In your case you simply need to put the file nonexistence condition on both of the redirect rules:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule [^/]$ %{REQUEST_URI}/ [L,R]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ /my/path/index.php [L]
Or maybe move this condition to the top of the file:
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L] # redirect to same location to stop processing
RewriteRule [^/]$ %{REQUEST_URI}/ [L,R]
RewriteRule ^ /my/path/index.php [L]
There's also an undocumented trick to stop processing after an internal redirect which should make more complex rulesets easier to write – using the REDIRECT_STATUS environment variable, which is set after an internal redirect:
RewriteCond %{ENV:REDIRECT_STATUS} . # <-- that's a dot there
RewriteRule ^ - [L] # redirect to same location to stop processing
RewriteRule [^/]$ %{REQUEST_URI}/ [L,R]
RewriteRule ^ /my/path/index.php [L]

Resources