Problem with mod_rewrite rules in .htaccess file - apache

This is my .htaccess file but it is not working. Not any URL is redirected. Help me.
RewriteEngine on
RewriteRule ^home index.php
RewriteRule ^contactus index.php?file=c-contactus
RewriteRule ^course_registration index.php?file=c-course_registration
RewriteRule ^ncplhpage index.php?file=c-ncplhpage
RewriteRule ^scplhpage index.php?file=c-scplhpage
RewriteRule ^corporatetra index.php?file=c-corporatetra

You may need to set a RewriteBase.
However, I suspect the problem is the lack of a / before index.php in all cases, i.e.
RewriteEngine on
RewriteRule ^home /index.php
As a side point, have you considered combining your directives into a single directive like:
RewriteRule ^(home|contactus|course_registration|ncplhpage|scplhpage|corporatetra)$ /index.php?file=c-$1
? You could take this a step further and hand down the checking of the name into your index.php file itself, i.e.
RewriteRule ^([_a-z]+)$ /index.php?file=c-$1
Bear in mind that your index.php should be checking that the $_GET['file'] that is requested is valid. Just because you have public URLs like /contactus doesn't mean that someone still can't type in /index.php?file=c-contactus directly (try it!). That means they could therefore type in /index.php?file=c-../../../../etc/passwd for instance. So do ensure that your index.php does some sanity-checking as well. That will be good both for security but also mean that you can avoid hard-coding your URLs into your .htaccess file.

Related

RewriteRule 301 redirect for whole directory and sub-directories

I really need your help with this one...
I'm simply trying to redirect EVERYTHING in a directory to another. It looks simple when I read about it, but in real life, it's not working... Here is my entire .htaccess file right now:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
# Redirect all to HTTPS
RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://example.org/$1 [R]
# End redirect
#301 REDIRECTS
Options +FollowSymLinks
RewriteRule ^mydir/(.*)$ /mydir-and-more/$1 [R=301,NC,L]
Fisrt, there is Wordpress stuff in didn't mess with.
Then, the code i copy/pasted from some site to redirect http to https. It works well. Note that i removed the "L" argument from the list to make sure my next rules will work.
After comes the part I'm strugling with.
So, it really is like that. My new directory starts with the same word then my old directory.
I copied this line from there: https://coolestguidesontheplanet.com/redirecting-a-web-folder-directory-to-another-in-htaccess/
On the Apache web site (https://httpd.apache.org/docs/current/mod/mod_rewrite.html) it says that i should use a / between ^ and mydir. Tried it, didn't work.
I tried moving Options +FollowSymLinks at the top of the file. Nothing.
When i use something like this:
RedirectMatch 301 ^/mydir/ https://example.org/mydir-and-more/
This works. But only moves the exact /mydir/ address. It doesn't move the whole directory. Also, if I type in https://example.org/mydir without the last /, it won't work. If i add the / in the Redirect match, it doesn't work anymore because its the same word!
So, here I am, totally confused! Please, any expert advise on this one? Thanks!!
You need to move you rules before the wordpress defined ones.
In fact if you try to access you site the rewrite rules elaboration stops at
RewriteRule . /index.php [L]
That instruction means "manage all paths that are not already beign managed by upper rule and stop elaboration ([L] stands for last)".
You can safely place your rules above the wordpress ones, better in a ifmodule
<IfModule mod_rewrite.c>
RewriteRule ^/mydir/(.*)$ /mydir-and-more/$1 [R=301,NC,L]
</IfModule>
# BEGIN WordPress
Funniest thing is, I solved my problem by fooling around! I didn't really need the RewriteRule, all I needed to write instead of the RewriteRule was exactly this :
Redirect 301 /mydir https://example.org/mydir-and-more
I don't even need the Options +FollowSymLinks.

I can't figure out why this RewriteCond isn't working

So I'm having trouble figuring out why my RewriteRules won't trigger. These rules are in an .htaccess file at the root directory of a subdomain of my website. I've turned on detailed logging for mod_rewrite in the VirtualHost but that isn't really helping me solve what's wrong, though the first three rules seem to be working simply by coincidence since their files exist at the requested location.
The goal of this set of rules is:
sub.domain.tld/ -> passthrough/serve actual file
sub.domain.tld/?q=test -> passthrough/serve actual file with query args intact
sub.domain.tld/.well-known/* -> passthrough/serve actual file (for letsencrypt)
sub.doamin.tld/* -> process.php?project=*
sub.domain.tld/*?q=test -> process.php?project=*&q=test while handling unlimited number of query args
And the current .htaccess is:
RewriteEngine on
#serve actual file if viewing main page or doing https renewal
RewriteCond %{REQUEST_URI} ^\?.+|\/$ [OR]
RewriteCond %{REQUEST_URI} ^\.well-known.*
RewriteRule (.*) - [L,QSA]
#redirect everything else to the processing script
RewriteCond %{REQUEST_URI} ^(\w+)
RewriteRule \/(\w+) process.php?project=$1 [NC,L,QSA]
Thank you for your help!
OK, This was actually a complex one and because most of the time, %{REQUEST_URI} tests are done using the RewriteRule itself, I got a bit confused and I'm sorry about that.
It turns out:
%{REQUEST_URI} contains the leading slash
the matching part of the RewriteRule doesn't
Also, keep in mind %{REQUEST_URI} doesn't contain the query string, as stated in the Apache manual:
REQUEST_URI
The path component of the requested URI, such as "/index.html". This notably excludes the query string which is available as its own variable named QUERY_STRING.
So, a rule like RewriteCond %{REQUEST_URI} ^\?.+ is pretty much useless as you'll never have a question mark in %{REQUEST_URI}
Also, and this probably is the most confusing part, when requesting /, %{REQUEST_URI} will contain the actual index file that has been served. So, if your DirectoryIndex is set to index.php index.html (in that order) and you have an index.html file in the root folder, {REQUEST_URI} will be index.html. If you have an index.php file, it will be index.php, but never /.
That being said, we can simply your rules to:
RewriteEngine on
RewriteCond %{REQUEST_URI} !^/(\.well-known|index\.php$)
RewriteRule (.+) process.php?project=%{REQUEST_URI} [QSA]
Note that I added the $ inside the brackets to only match the end of string character after index\.php but not after \.well-known, so anything after \.well-known will also match.
You will need to replace index\.php with index\.html if you have an html index.
Finally, you don't need 2 rules for that. It's always better to have only one and exclude some URLs from it.
PS: you'll also notice you don't need to escape / as this is not considered as a regexp delimiter.
You just need this single rule in your .htaccess:
RewriteEngine on
# skip files, directories and anything inside .well-known/ directory
RewriteRule ^(?!index\.|process\.php|\.well-known)(.+)$ process.php?project=$1 [L,QSA,NC]

Shorten url with .htaccess

I do not know .htaccess so much. What i want to do is to shorten my url. I have searched on Google and found many solutions. Still none of them is working.For exmaple my url is "example.com/video?id=12345/filename". I want an url like "example.com/video/12345/filename". I have tried thisRewriteEngine on
RewriteRule ^video video?id=$1 [QSA]But it is not working. Please help.
Here is my .htaccess code
Options +FollowSymLinks -MultiViews -indexes
RewriteEngine On
RewriteBase /
# remove .php; use THE_REQUEST to prevent infinite loops
RewriteCond %{THE_REQUEST} ^GET\ (.*)\.php\ HTTP
RewriteRule (.*)\.php$ $1 [L,R=301]
RewriteRule ^video/([0-9]+)/.+$ video?id=$1 [L,QSA]
RewriteRule ^video/([0-9]+)/.+$ video?id=$1 [L,QSA]
ErrorDocument 404 /index.php
I guess this is what you are looking for:
RewriteEngine on
RewriteRule ^video/([0-9]+)/(.+)$ video?id=$1/$2 [L,QSA]
I would however suggest that you simply drop the filename, you don't need it to deliver the file. Since you have some numerical ID you certainly have some form of database that stores the physical location of the referenced file. In that case the above would have to be changed to:
RewriteEngine on
RewriteRule ^video/([0-9]+)/ video?id=$1 [L,QSA]
And another, general hint: if possible you should always prefer to place such rules into the real host configuration of your http server. You should only fall back to .htaccess style files if that really is not possible for you, for example because you do not have access to the http server configuration. Reason is that .htaccess style files are notoriously error prone, a security risk, hard to debug and really slow the server down.

htaccess adding WWW and changing filename in subdirectory

I know similar questions have come up, though often without a working answer. I'm hoping to have better luck!
I have an .htaccess file in my root directory adding "www" to everything:
RewriteEngine on
RewriteCond %{SERVER_NAME} ^mysite.org
RewriteRule ^(.*)$ http://www.mysite.org/$1 [R=permanent,L]
This generally works fine. I have a subfolder (/myquiz/) in which the old index.html file has been replaced with index.php. I know there are external links to /myquiz/index.html, so I want to make sure those redirect. Leaving index.html in place and trying to redirect from that led to some odd behavior, but adding an .htaccess in that directory works for that:
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html?$ /myquiz/index\.php [NC,R]
Trying to load index.html redirects to index.php as hoped for, and the WWW gets added if needed. But requesting mysite.org/myquiz/index.php directly does not add the WWW.
I tried adding "RewriteEngine inherit", but that resulted in calls getting redirected to my root folder instead. A great trick if I want to make a subfolder inaccessible, but not helping here. I also tried just adding the code from my root .htaccess into the beginning of my subfolder's .htaccess, but that worked no better.
Any ideas?
You shouldn't need to add another htaccess file in the myquiz folder. This should work in the htaccess file in the root of the site. Remove the htaccess file in myquiz and try this.
RewriteEngine On
RewriteCond %{HTTP_HOST} ^mysite\.org
RewriteRule ^(.*)$ http://www.mysite.org/$1 [R=301,L]
RewriteRule ^myquiz/index\.html$ /myquiz/index.php [R=301,L]
Also I wouldn't use %{SERVER_NAME} unless your are sure the name is set properly in the config file. Then it can be more reliable than HTTP_HOST, otherwise I would instead use %{HTTP_HOST}.
I think inherit would work if you add an L flag to the rule that you have in your myquiz folder:
RewriteRule ^index\.html?$ /myquiz/index\.php [NC,R,L]
So that it redirects first, then the inherited rule (the www) gets applied after.
You could also just put both rules in the same file:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^mysite.org$ [NC]
RewriteRule ^(.*)$ http://www.mysite.org/$1 [R=permanent,L]
RewriteRule ^myquiz/index\.html$ http://www.mysite.org/myquiz/index.php [R=permanent,L]

Apache .htaccess RewriteRule

Here's my situation. I have a web root and several subdirectories, let's say:
/var/www
/var/www/site1
/var/www/site2
Due to certain limitations, I need the ability to keep one single domain and have separate folders like this. This will work fine for me, but many JS and CSS references in both sites point to things like:
"/js/file.js"
"/css/file.css"
Because these files are referenced absolutely, they are looking for the 'js' and 'css' directories in /var/www, which of course does not exist. Is there a way to use RewriteRules to redirect requests for absolutely referenced files to point to the correct subdirectory? I have tried doing things like:
RewriteEngine on
RewriteRule ^/$ /site1
or
RewriteEngine on
RewriteRule ^/js/(.*)$ /site1/js/$1
RewriteRule ^/css/(.*)$ /site1/css/$1
But neither of these work, even redirecting to only one directory, not to mention handling both site1 and site2. Is what I'm trying possible?
EDIT: SOLUTION
I ended up adapting Jon's advice to fit my situation. I have the ability to programatically make changes to my .htaccess file whenever a new subdirectory is added or removed. For each "site" that I want, I have the following section in my .htaccess:
RewriteCond %{REQUEST_URI} !^/$
RewriteCond %{REQUEST_URI} !^/index.php$
RewriteCond %{HTTP_COOKIE} sitename=site1
RewriteCond %{REQUEST_URI} !^/site1/
RewriteRule ^(.*)$ /site1/$1 [L]
Index.php is a file that lists all my sites, deletes the "sitename" cookie, and sets a cookie of "sitename=site#" when a particular one is selected. My RewriteConds check,
If the request is not for /
If the request is not for /index.php
If the request contains the cookie "sitename=site1"
If the request does not start with "/site1/"
If all of these conditions are met, then the request is rewritten to prepend "/site1/" before the request. I tried having a single set of Conds/Rules that would match (\w+) instead of "site1" in the third Condition, and then refer to %1 in the fourth Condition and in the Rule, but this did not work. I gave up and settled for this.
If the RewriteRules are in your .htaccess file, you need to remove the leading slashes in your match (apache strips them before sending it to mod_rewrite). Does this work?
RewriteEngine on
RewriteRule ^js/(.*)$ /site1/js/$1
RewriteRule ^css/(.*)$ /site1/css/$1
EDIT: To address the comment:
Yes, that works, but when I do RewriteRule ^(.*)$ /site1/$1, it causes Apache to issue internal server errors. But to me, it seems like that should just be a generic equivalent of the individual rules!
What's happening with that rule is when /something/ gets rewritten to /site/something/, and apache internally redirects, it gets rewritten again, to /site/site/something/, then again, then again, etc.
You'd need to add a condition to that, something like:
RewriteCond %{REQUEST_URI} !^/site/
RewirteRule ^(.*)$ /site/$1 [L]
You need to set up symlinks, which the rewrite rules will use so your absolute links at the server level can follow the symbolic links to the central site hosting account.