Unexpected behavior with custom .htaccess rewrite rules - regex

So I have been working on some rewrite rules which aren't working as expected. These are some sample requests I am trying to rewrite:
/ -> /index.php?page=Home
/Home -> /index.php?page=Home
/Teaching/Foo -> /index.php?page=Teaching&id=Foo
/Teaching/Bar -> /index.php?page=Teaching&id=Bar
/Download/ue8 -> /index.php?action=Download&id=ue8
/Download/24a -> /index.php?action=Download&id=24a
(default) -> /index.php?page=Home
** OR ALTERNATIVELY **
(default) -> /index.php?page=FileNotFound
(and maybe rewrite the visible URL to /FileNotFound)
I mainly want to hide as much of the urls as possible and prevent both directory listing and direct access to my files located in specific folders and only allow access to downloadable files via /Download/FileId while having my usual pages for different lectures accesible via /Teaching/SomeLecture.
So far I have been using this snippet for the /Home and /Teaching stuff:
RewriteEngine On
RewriteBase /
# Redirect Trailing Slashes
RewriteRule ^(.*)/$ /$1 [L,R=301]
# Handle Front Controller
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^Teaching/([A-Za-z0-9]*)$ index.php?page=Teaching&id=$1 [L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^Home$ index.php?page=Home [L]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s(.*)/index\.php [NC]
RewriteRule ^ %1 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [L,R=301]
I am not completely sure about all of these directives and I noticed, that there are currently some flaws to it.
Trying to access a non-existant file, e.g. /Files/Bad/Path.pdf, forwards the user to /?page=Home which should be redirected either to /, /Home or display the contents of /index.php?page=FileNotFound without changing the URL at all or redirecting to /FileNotFound depending on the rule of (default). I am not really sure which solution might be the most suitable in this scenario.
Trying to access some folders which do exist results in an infinite redirection loop while folders which do not exist apparently redirect to /. In both cases it feels right to redirect to /FileNotFound I suppose?
Could you please work out a set of rules that might suit my needs in this case?

You have many redundant directives in your .htaccess. Replace all of your .htaccess with this:
# Turn off mod_spelling
<IfModule mod_speling.c>
CheckSpelling off
CheckCaseOnly off
</IfModule>
Options -MultiViews
RewriteEngine On
RewriteBase /
# block direct access to file and directories in these directories
RewriteCond %{REQUEST_URI} !\.(?:jpe?g|gif|bmp|png|tiff|css|js)$ [NC]
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^(Templates|Files) - [NC,F]
# remove index.php
RewriteCond %{THE_REQUEST} /index\.php [NC]
RewriteRule ^(.*?)index\.php$ /$1 [L,R=301,NC,NE]
# Redirect Trailing Slashes
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
# Handle Front Controller
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(Download|Teaching)/([\w-]+)/?$ index.php?page=$1&id=$2 [L,QSA,NC]
RewriteRule ^(Home)?/?$ index.php?page=Home [L,NC,QSA]
Make sure to clear your browser cache before testing this.

Related

remove folder from url using .htaccess

I know there are plenty of other questions similar to this one, i tried followinf some of those, but with no luck.
I have a website called test.com and i need, when someone seraches for test.com to show the content in test.com/home, without having home in the uerl.
My htaccess file at the moment looks like this:
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule /(.*) home/$1 [L]
RewriteRule /home/(.*) /$1 [L,R=302]
RewriteOptions inherit
RewriteCond %{HTTP_HOST} ^test\.com$ [OR]
RewriteCond %{HTTP_HOST} ^www\.test\.com$
but when i type test.com it shows a list of folders, not the content inside home.
What am i doing wrong?
thanks
You can simplify your rules to this in root .htaccess
RewriteEngine on
RewriteBase /
RewriteRule ^$ home/ [L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^((?!home/).+)$ home/$1 [L,NC]
Make sure to clear your browser cache before testing this.

Apache .htaccess file not rewriting properly

I have an .htaccess file. It needs to rewrite URLs in two cases: for the MVC framework and in a more special case. I want to rewrite any requests to "/resources/newspaper" if the user doesn't have a cookie named "cfnw-hash". I've tried putting the code before the MVC code and after it. Doesn't work. It worked before switching over to the MVC framework, though I really don't have enough .htaccess knowledge to see if that's causing the issue. Here's code:
Options -Indexes
<IfModule mod_rewrite.c>
Options -Indexes
RewriteEngine On
RewriteBase /
# Force to exclude the trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.*)/$
RewriteRule ^(.+)/$ $1 [R=307,L]
# Allow any files or directories that exist to be displayed directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?$1 [QSA,L]
</IfModule>
RewriteEngine On
RewriteCond %{HTTP_COOKIE} !cfnw-hash [NC]
RewriteRule \/resources\/newspaper.* http://www.example.com/error/401 [R=401,NC,L]
Combine your rules and I think you RewriteRule might not be matching because of the prepending / and also the cookie matching. Try this. Notice the cookie part that you update with your cookie.
Options -Indexes
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_COOKIE} !cookie_name=specific_value; [NC]
RewriteRule ^resources/newspaper/?(.*) http://www.example.com/error/401 [R=401,NC,L]
# Force to exclude the trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.*)/$
RewriteRule ^(.+)/$ $1 [R=307,L]
# Allow any files or directories that exist to be displayed directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?$1 [QSA,L]
</IfModule>
Have it this way:
<IfModule mod_rewrite.c>
Options -Indexes
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_COOKIE} !cfnw-hash [NC]
RewriteRule ^resources/newspaper /error/401 [R=401,NC,L]
# Force to exclude the trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.*)/$
RewriteRule ^(.+)/$ $1 [R=307,L]
# Allow any files or directories that exist to be displayed directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?$1 [QSA,L]
</IfModule>
Test this after clearing your browser cache.

Rewrite urls to not include file extensions but allow subdomains to act normally

I need to
Remove the file extension from all of the urls on my site (mywebsite.com/about.html >> mywebsite.com/about/)
Always add a trailing / to the end of the url (mywebsite.com/about >> mywebsite.com/about/)
Allow for an exception that one of the nav items links to a pdf, not an html document (mywebsite.com/calendar.pdf >> mywebsite.com/calendar/
Allow subdomains to go to their folder instead of being rewritten (My folder tree is public_html>my main site files and a dev folder>(inside dev folder) index.html) I need the subdomain to link to that dev folder, currently the url rewriting changes dev.mywebsite.com to public_html/dev.html
This is my current, hacked together htaccess file:
RewriteEngine On
RewriteRule ^calendar/?$ files/2013-2014_calendar.pdf
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]+)/$ $1.html
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule (.*)$ /$1/ [R=301,L]
Sorry, this might be a duplicate or semi-duplicate. I looked around as much as I could but couldn't find anything that applied to my situation exactly or that I understood. Thanks guys!
Try this code:
RewriteEngine On
RewriteBase /
# skip dev. subdomain
RewriteCond %{HTTP_HOST} ^dev\. [NC]
RewriteRule ^ - [L]
# calendar rule
RewriteRule ^calendar/?$ files/2013-2014_calendar.pdf [L]
# hide .html rules
RewriteCond %{THE_REQUEST} \s/+(.+?)\.html[\s?] [NC]
RewriteRule ^ %1/ [R=301,L,NE]
# add a trailing slash
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule [^/]$ %{REQUEST_URI}/ [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1.html -f
RewriteRule ^(.+?)/?$ $1.html [L]

Deny direct access to php files

I wrote this code to redirect everything to index.php.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA]
I want to somehow adjust !-f to allow .php files to be 301 redirected to / without getting into a redirection loop. I have /foo/bar/218 that loads index.php which requires view/foo_bar.php. I want /view/foo_bar.php to be inaccessible via the address bar.
You can try these rules:
# redirect .php requests to /
RewriteCond %{THE_REQUEST} \.php[\s?] [NC]
RewriteRule ^ / [L,R=302]
# existing rules without .php files
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule !\.php$ index.php [QSA]

Apply rewrite rule for all but all the files (recursive) in a subdirectory?

I have an .htaccess file in the root of the website that looks like this
RewriteRule ^some-blog-post-title/ http://website/read/flowers/a-new-title-for-this-post/ [R=301,L]
RewriteRule ^some-blog-post-title2/ http://website/read/flowers/a-new-title-for-this-post2/ [R=301,L]
<IfModule mod_rewrite.c>
RewriteEngine On
## Redirects for all pages except for files in wp-content to website/read
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !/wp-content
RewriteRule ^(.*)$ http://website/read/$1 [L,QSA]
#RewriteRule ^http://website/read [R=301,L]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
My intent is to redirect people to the new blog post location if
they propose one of those special blog posts.
If that's not the case
then they should be redirected to http://website.com/read.
Nothing from http://website.com/wp-content/* should be redirected.
So far conditions 1 and 3 are being met. How can I meet condition 2?
Note: I want to redirect to /read even for content that exists to prevent any images, CSS, or javascript from working, except those in /wp-content
Make your first rule as:
## Redirects for all pages except for files in wp-content to website/read
RewriteRule !^wp-content/ http://website.com/read%{REQUEST_URI} [NC,L,R=302]