RewriteRule doesn't exclude existing files/directories - apache

So for a website I have an index.php file in my root directory that expects url parameters to determine which contents to echo:
example.com/?p=home
example.com/?p=blog
However, for aesthetical purposes, I wrote a RewriteRule in the .htaccess file in the root directory that redirect the following requests to the index.php in the root directory with URL parameters:
example.com/home → example.com/?p=home
example.com/blog/ → example.com/?p=blog
The rule looks like this:
RewriteEngine On
# This is my rule
RewriteCond %{REQUEST_URI} !^(bootstrap|cms|php|pics|project|install)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ([a-zA-Z]*)/?$ index.php?p=$1 [NC]
# The following rules are used by the CMS I'm using, so I don't want to change those
RewriteRule ^(cms)($|/) - [L]
RewriteRule ^(install)($|/) - [L]
RewriteCond %{REQUEST_URI} !^(\.png|\.jpg|\.gif|\.jpeg|\.bmp)/$
RewriteRule (.*.html|.*.php|.*.htm) cms_worker.php?page=$1 [QSA]
However, using this all CSS and JS files that I included in the index.php using relative links (e.g. <link href="/project/style.css" rel="stylesheet">) aren't loaded as the rule seems to effect those requests as well.
Why is this happening? And how can I solve it? I thought the Rewrite Conditions above the rule should prevent the Rule from being applied when the requested directory or file exists ... I tried adding the first RewriteCond to exclude requests to the specified directories from the Rule, but that didn't work as well.
Edit: It works fine if I access a page without the trailing slash (i.e. example.com/blog). However, when I access the page with the trailing slash (i.e. example.com/blog/), the CSS and JS files aren't being loaded. The network tab of the Chrome dev tools doesn't show anything, but when I open the source code and click on the relative link to the css file, it redirects to example.com/blog/project/style.css instead of example.com/project/style.css

I believe this is due to regex pattern used in your rules. Try these rules:
RewriteEngine On
# This is my rule
RewriteCond %{REQUEST_URI} !^(bootstrap|cms|php|pics|project|install)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([a-z]+)/?$ index.php?p=$1 [NC,L,QSA]
# The following rules are used by the CMS I'm using, so I don't want to change those
RewriteRule ^cms($|/) - [L,NC]
RewriteRule ^install($|/) - [L,NC]
RewriteRule ^(.+?\.(?:html?|php))$ cms_worker.php?page=$1 [QSA,L,NC]
To resolve relative links add <base href="/"> in <head> section of your HTML.

Related

Started implementing .htaccess but when navigating from the reduced URL, when going into a directory it then can't get back

So I have included an htaccess file to my server in the root directory and changed all of the ./ I could find set the absolutes.
However, when I search by URL into one of the directories pressing the home button does not take me home. Instead, it appends the index onto the end:
/website/book/index.php?p=home
Instead of
/website/index.php?p=home
Where have I made a fuddle?
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+[^/])/$ https://%{HTTP_HOST}/paperbound/$1 [R=301,L]
RewriteRule ^([^/\.]+)?$ index.php?p=$1 [L]
RewriteRule ^([^/\.]+)/([^/\.]+)$ index.php?p=$1&id=$2 [NC,L]
</IfModule>
Is the htaccess used. https://sitehost/website/book/2 is URL entered and page retrieved which exists as https://sitehost/website/index.php?p=book&id=2, clicking navlink to return to https://sitehost/website/index.php?p=home, instead places https://sitehost/website/book/index.php?p=home into the URL bar and returns an error as the file does not exist.
With your shown samples/attempts, please try following htaccess rules file. Make sure to keep your index.php file is present in website folder and htaccess is present along side with website folder(not inside it).
Please make sure to clear your browser cache before testing your URLs.
##Enabling rewrite engine here.
RewriteEngine ON
##Checking conditions for non-existing pages here.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
##performing internal rewrite here to index.php file.
RewriteRule ^([^/]*)/([^/]*)/([^/]*)/?$ $1/index.php?p=$2&id=$3 [QSA,L]

Flask - CGI - need to fix issues with htaccess

So I have successfully deployed a Flask app using CGI. In order to get the app working, my .htaccess file had to look like this:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /home/user/public_html/mysite/cgi-bin/main.cgi/$1 [L]
However, I am facing a couple of issues.
mysite.com works, but when I link other pages to the home page, it takes them to mysite.com/cgi-bin/main.cgi. I'd like for the links to take users to mysite.com. Similarly, when I try to link to another page, it goes to mysite.com/cgi-bin/main.cgi/page2, when I actually want it to be mysite.com/page2. How can I fix this?
The following .htaccess content seems to not work:
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]
Header always set Content-Security-Policy "upgrade-insecure-requests;"
I'm not sure if the above two issues are related, but I'd like to fix both.
With your shown samples, please try following Rules. Please make sure your htaccess Rules file is besides your cgi-bin directory/folder. Also clear your browser cache before testing your URLs.
RewriteEngine ON
##Rules for applying https to urls.
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]
##Rules to remove www from urls.
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.*)$ [NC]
RewriteRule ^ https://%1/%{REQUEST_URI} [NE,R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^cgi-bin/main.cgi/page2/?$ cgi-bin/templates/page2/index.html [NC,L]
JS/CS rewrite/redirect:
You may need to use base tag to fix your js and other relative resources. If you are linking js files using a relative path then the file will obviously get a 404 because its looking for URL path. for example if the URL path is /file/ instead of file.html then your relative resources are loading from /file/ which is not a directory but rewritten html file. To fix this make your links absolute or use base tag. In the header of your webpage add this <base href="/"> so that your relative links can load from the correct location.

Redirecting all urls, including no path, to a file in subdirectory

I have checked a large amount of existing answers regarding .htaccess redirects. However none of them have helped me.
What I want to accomplish is redirecting all request urls to /api/init.php. However I've only gotten so far to where my index page www.example.com simply gives me a file listing because of the missing index.php file, while every url request with a path is working.
How can I accomplish this with .htaccess without ending up with a directory listing on my landing page?
This is as far as I got:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /api/init.php?path=$1 [NC,L,QSA]
Well your site root is a directory, so this rule you have excludes existing directories. What you could do is only exclude existing files, and allow existing directories to be handled by the PHP script. Like this:
RewriteEngine on
RewriteCond %{REQUEST_URI} !=/api/init.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /api/init.php?path=$1 [L,QSA]
I removed the NC flag as it's not needed. I added a condition to prevent an unnecessary file-system check.
You don't have to pass the path on in a URL parameter, as you could get it from $_SERVER['REQUEST_URI'] in PHP (not the same as REQUEST_URI in mod_rewrite, in PHP it always has the original URI). If you wanted to do that then your rule becomes nice and simple:
RewriteEngine on
RewriteCond %{REQUEST_URI} !=/api/init.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ /api/init.php [L]
Because the query string will just be passed on unaffected (so QSA is not needed).

CMSMS htaccess rewrite for ListIt2 module

i'm creating a website with CMS made simple version 1.11.11 and i use the listit2 module version 1.4.1 .
Now this module only can generate urls in this form:http://example.com/listit2/item-alias/page-id
Now, i don't care about the page id which is used to show the correct template,
but since this is a multilingual website i would like listit2 to apear behind my (virtual) language folder: http://example.com/lang/listit2/item-alias/page-id
so i added 2 rewrite lines in my htaccess file,
right before the general rewrite rules of CMSMS.
RewriteCond %{HTTP_HOST} ^lang/listit2 [NC]
RewriteRule ^lang/listit2(.*)$ listit2$1
# Rewrites urls in the form of /parent/child/
# but only rewrites if the requested URL is not a file or directory
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ index.php?page=$1 [QSA]
but that doesn't seem to work since it generates the summary overview instead of a detail page like the content from http://example.com/listit2/page-id
How, can i solve this?
This does the trick
RewriteEngine on
RewriteBase /
#Virtual folders for listit2
RewriteRule ^lang/listit2(.*)$ index.php?page=listit2$1
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ index.php?page=$1 [QSA]
It isn't a .htaccess issue. It is a URL generation issue within the ListIt2 module.
Within your summary template, instead of using the standard variable for the detail_url, you will need to put your own custom URL in the href.
For example something like this (this code isn't test, check documentation for the actual variables)
Read More...

Apache rewrite condition to fall back when css doesn't exist

I need a rule in Apache that redirects not-found CSS files to another location based on their names in another folder. Like this:
Request: localhost/css/nonexistent.css
Response: localhost/css/g/nonexistent.css
If the CSS exists, just serve it like normal:
Request: localhost/css/existent.css
Response: localhost/css/existent.css
My project is on CakePHP which comes with the following rules by default:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php/$1 [QSA,L]
I mention it because whatever the new rule is, it should not break Cake's rules.
Thanks for the help.
Edit: Forgot to mention that the css/g/ file is an alias for a script (inside the Cake MVC stack) that generates the new css file and echoes it. Answers so far seem to do the redirection fine, but then it doesn't find the css/g/file.css either because it really doesn't exist.
Here is a rewrite rule adapted from this SO question and the Apache mod_rewrite docs.
The gist is: If the request is for a path that starts with /css/,get the filesystem path of the requested file and check if it exists. If id doesn't, rewrite the URL for your deeper directory. This should be placed before the rules you posted in your question.
RewriteCond %{REQUEST_URI} ^/css/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/css/(.*) /css/g/$1
You can try first checking if the /css/g/ css file exists:
# Make sure it doesn't exist
RewriteCond %{REQUEST_FILENAME} !-f
# Make sure this is a request for a css file:
RewriteCond %{REQUEST_URI} ^/css/(.*)\.css$
# See if the /g/ version exists
RewriteCond %{DOCUMENT_ROOT}/css/g/%1.css -f
# rewrite if all conditions satisfied
RewriteRule ^css/(.*)$ /css/g/$1 [L]
The %1 in the 3rd condition backreferences the filename (sans .css extension) matched in the previous RewriteCond.
EDIT:
If the file css file is actually generated, then skip the checking of /g/ version and just pass it to the controller:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} ^/css/(.*)\.css$
RewriteRule ^css/(.*)$ index.php/css/g/$1 [L]