Apply htaccess rules for all cases except a few - .htaccess

I want every access to:
www.example.com/demo/action.html
to redirect to
www.example.com/demo/?section=action
Being action the variable that changes.
But, I do not want to apply that rule in a couple of cases, lets say:
www.example.com/demo/mypage1.html
www.example.com/demo/mypage2.html
For those cases I want them to load the real html pages mypage1.html and mypage2.html.
At the moment I have like 20 rules for all possible action variables. But as it doesn't seem to be ideal in terms of performance, I would rather have just the 2 special cases and a single rule for all the other cases.
This is what I have at the moment:
RewriteRule ^demo/removeUser.html$ demo/?section=removeUser [QSA]
RewriteRule ^demo/addUser.html$ demo/?section=addUser[QSA]
RewriteRule ^demo/addUser.html$ demo/?section=editUser[QSA]
RewriteRule ^demo/addUser.html$ demo/?section=comment[QSA]
... etc

You can keep exception at the top and then a generic rewrite rule:
RewriteEngine On
RewriteRule ^demo/(?:mypage1|mypage2)\.html$ - [L,NC]
RewriteRule ^demo/([\w-]+)\.html$ demo/?section=$1 [QSA,L,NC]
This assumes that demo/ directory has no .htaccess inside.
However if you are just looking at excluding all existing files from this rewrite then you just a single rule like this:
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^demo/([\w-]+)\.html$ demo/?section=$1 [QSA,L,NC]

Related

RewriteCond according to the first part of url not working

I'm trying to work on doing some rewrite but it's not working. Here is my code:
RewriteCond %{REQUEST_URI} !^(static/|server/|internal.php).*$
RewriteRule ^(.*)$ /internal.php?request=$1 [L]
I'm trying to redirect everything to /internal.php?request=blablabla, except the internal.php itself, and things in two folders called static and server, since these two folders have images and so on.
For example,
/hello/world => /internal.php?request=hello/world/
/static/a/b/c/a.jpg => /static/a/b/c/a.jpg not changed
But the code is not working, the RewriteCond seems not able to restrict rewrite of internal.php, and the two folders. Now what's happening is everything is going to rewrite to internal.php, and internal.php would be rewrite to internal.php again. And finally give me a 500 after infinite loops. Which I don't want any rewrite happen. What's wrong?
You are missing a leading / in the request URI expression, also you should escape the dot in internal.php so that it actually matches a dot instead of every char:
RewriteCond %{REQUEST_URI} !^/(static/|server/|internal\.php).*$
RewriteRule ^(.*)$ /internal.php?request=$1 [L]
Note that this will also rewrite /static and /server where the trailing slash is omitted, if you want to avoid that you could for example add another condition:
RewriteCond %{REQUEST_URI} !^/(static|server)$
RewriteCond %{REQUEST_URI} !^/(static/|server/|internal\.php).*$
Tough it should be possible to put this in a single expression, however I'm not that experienced with regular expressions, so I'm pretty sure that this not the most elegant way:
RewriteCond %{REQUEST_URI} !^/(((static|server)(/.*)?)|(internal\.php.*))$

htaccess issue including period/fullstop (.)

I currently have this .htaccess rule the works fine:
RewriteRule ^instructor/([A-Za-z0-9-]+)$ instructor.php?username=$1 [NC,L]
However, when I attempt to add a period into the mix a lot of the rules on the site break so I am assuming the character isn't escaped correctly:
RewriteRule ^instructor/([A-Za-z0-9-\.]+)$ instructor.php?username=$1 [NC,L]
Anyone point me in the right direction please?
Update
It appears to be something to do with the directory structure.
Another selection of rules that apply to this site are the following:
## Registration
RewriteRule ^instructor/register/?$ instructor-form/index.php [L]
RewriteRule ^instructor/register/stage([1-5]+)$ instructor-form/stage$1.php [L]
These work fine (the directory here is instructor-form/
However, there is also a directory called instructor/ which these rules point to:
RewriteRule ^instructor/dashboard/?$ instructor/index.php [L]
RewriteRule ^instructor/account-details/?$ instructor/account-details.php [L]
RewriteRule ^instructor/change-password/?$ instructor/change-password.php [L]
These are the rules that are affected when adding the . into the first rule. The rules are all in order and work fine without the . in the [A-Za-z0-9-] char block. When added the physical instructor/ folder seems inaccessible.
You wrote so much text in your question but forgot to mention important details: what is actually broken? Because I do not have clear answer for that I will be speculating here based on the information you have provided so far.
RewriteRule ^instructor/([A-Za-z0-9-\.]+)$ instructor.php?username=$1 [NC,L]
The problem with this rule is that it will also rewrite already rewritten php files: instructor/index.php, instructor/account-details.php, instructor/change-password.php etc.
I think you are relaying on [L] flag too much .. or do not really know how mod_rewrite and [L] flag work. And that is why you are having this issue -- your rule with a dot in pattern rewrites already rewritten URLs.
Useful link: RewriteRule Last [L] flag not working?
You need to add some condition (global rule or condition specific to this rule only) to prevent rewriting already rewritten URLs or existing files.
1. Global rule -- place it somewhere on the top before other rules. Keep in mind that this may not work as intended depending on your website structure and rewrite logic (e.g. when you need to actually rewrite requests to already existing files or folders):
# do not do anything for already existing files
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .+ - [L]
2. Condition specific to that rule only:
a) do not rewrite if requested URI is physical file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^instructor/([A-Za-z0-9-\.]+)$ instructor.php?username=$1 [NC,L]
OR
b) do not rewrite .php files
RewriteCond %{REQUEST_URI} !.+\.php$
RewriteRule ^instructor/([A-Za-z0-9-\.]+)$ instructor.php?username=$1 [NC,L]

How do you add a second possible variable to a clean url?

I have created a htaccess rewrite code for URLs so when a user goes to myurl.com/testing/ it shows them index.php?page=testing however I would like to have a second or maybe third page so it could look like myurl.com/testing/2832/9283 and would show users index.php?page=testing&var1=2832&var2=9283.
This is the code I currently have:
RewriteRule ^([^\/]+)/([^\/]*)/$ index.php?page=$1&var1=$2
RewriteRule ^([^\/]+)/([^\/]*)$ index.php?page=$1&var1=$2
This works but I want to make the variables optional. If I do not have a second variable (i.e. just myurl.com/testing/) then it says it cant find the file.
# 3-level deep parameters
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)(/([^/]+))?(/([^/]+))?(/)?$ /index.php?page=$1&var1=$3&var2=$5 [QSA,L]
This rule will not touch already existing files and folders.
This rule will rewrite:
/help/tracking/123456/ => /index.php?page=help&var1=tracking&var2=123456
/help/tracking => /index.php?page=help&var1=tracking&var2=
/help => /index.php?page=help&var1=&var2=
You were having page=index.php because your rule rewrites already rewritten URLs (A lot of people forgetting, that when rewrite happens, it goes to next iteration and starting to test all rules again). This rule has conditions (extra checks) to ignore already existing files and folders.
Why not just set multiple RewriteRules for each case?
RewriteRule ^([^/]+)/?$ index.php?page=$1
RewriteRule ^([^/]+)/([^/]+)/?$ index.php?page=$1&var1=$2
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/?$ index.php?page=$1&var1=$2&var2=$3

Rewrite htaccess old oscommerce links

I am trying to rewrite all the old oscommerce links to a new website. But I am having trouble with part of the URL I need to rewrite.
The link looks like this:
http://www.domain.com/product_info.php?cPath=3_72&products_id=129&osCsid=6j3iabkldjcmgi3s1344lk1285
This rewrite works for the above link:
RewriteCond %{REQUEST_URI} ^/product_info\.php$
RewriteCond %{QUERY_STRING} ^cPath=3_72&products_id=129&osCsid=([A-Za-z0-9-_]+)$
RewriteRule ^(.*)$ http://www.domain.com/apple/air.html? [R=301,L]
But will not work for:
http://www.domain.com/product_info.php?cPath=3_72&products_id=129
My problem is that I want the rewrite to work no matter if the &osCsid=6j3iabkldjcmgi3s1344lk1285 part is included or not.
I think you can achieve this by not specifying the closing delimiter ($)
Give this a try:
RewriteCond %{REQUEST_URI} ^/product_info\.php$
RewriteCond %{QUERY_STRING} ^cPath=3_72&products_id=129
RewriteRule ^(.*)$ http://www.domain.com/apple/air.html? [R=301,L]
By not putting the $ at the end of the regex string you are basically saying: match any string that starts with ..., no matter what comes after
Hope this helps :)
This should do the job just fine:
RewriteCond %{QUERY_STRING} ^cPath=3_72&products_id=129
RewriteRule ^product_info\.php$ http://www.domain.com/apple/air.html? [R=301,L]
There is no need for separate condition RewriteCond %{REQUEST_URI} ^/product_info\.php$ -- this part can be (actually, SHOULD BE, for better performance) moved to RewriteRule.
This is enough ^cPath=3_72&products_id=129 -- it tells "When query strings STARTS with ...". No need to include optional/non-important parameters osCsid=([A-Za-z0-9-_]+).
This rule is to be placed in .htaccess file in website root folder. If placed elsewhere some small tweaking may be required.

.htacces RewriteRule not working

Hi people#stackoverflow,
Maybe I have a fundamental misconception about the working of RewriteRule. Or maybe not. Nevertheless, I'm trying to figure this out now for two days, without any progress.
This is the currrent situation:
I have a Joomla website with SEF and mod_rewrite turned on.
This results in the URL:
mysite.com/index.php?option=com_remository&Itemid=7
being rewritten to:
mysite.com/sub-directory/sub-directory/0000-Business-files/
These are the lines that are currently used in my .htaccess (all standard Joomla)
Options +FollowSymLinks
RewriteEngine On
RewriteRule ^([^\-]*)\-(.*)$ $1 $2 [N]
RewriteCond %{QUERY_STRING} mosConfig_[a-zA-Z_]{1,21}(=|\%3D) [OR]
RewriteCond %{QUERY_STRING} base64_encode.*\(.*\) [OR]
RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2})
RewriteRule ^(.*)$ index.php [F,L]
# RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{REQUEST_URI} (/|\.php|\.html|\.htm|\.feed|\.pdf|\.raw|/[^.]*)$ [NC]
RewriteRule (.*) index.php
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
This is what I want to achieve:
When a visitor uses this URL
mysite.com/sub directory/sub directory/0000 Business files/
it should lead him to the right page.
Although I know it's not the best idea to use spaces in a URL, I'm confronted with the fact that these 'spacious' URL's are used in a PDF, that's already been issued.
I thought I could use mod_rewrite to rewrite these URL's. But all I get is 'page not found'
I've added this rule on top of the .htaccess file:
RewriteRule ^([^\-]*)\-(.*)$ $1 $2 [N]
But this is not working. What am I doing wrong? Or, also possible, am I missing the point on when and how to use mod_rewrite?
rgds, Eric
First off, the default behavior of apache is usually to allow direct URLs that map to the underlying file system (relative to the document root), and you should use RewriteRule when you want to work around that. Looking at your question, it seems like you want to browse the filesystem and so you should not use a RewriteRule.
If mysite.com/sub+diretory/sub+directory/0000+Business+files/ doesn't work (without your rule), I'm wondering: do you have that directory structure on your server? I.e. does it look like this?
[document root]/index.php
[document root]/sub directory/sub directory/0000 Business files/
If not, I'm not sure I understand what you're trying to achieve, and what you mean by the visitor being "lead to the right page". Could you provide an example URL that the user provides, and the corresponding URL (or file system path) that you want the user to be served.
Regarding your rewrite rule, I'm not even sure that it is allowed, and I'm surprised you don't get a 500 Internal Server Error. RewriteRule takes two arguments (matching pattern and substitution) and optionally some flags, but because of the space between $1 and $2 you're supplying three arguments (+ flags).
EDIT: I got the pattern wrong, but it still doesn't make much sense. It matches against any URL that has at least one dash in it, and then picks out the parts before and after the first dash. So, for a URL like "this-is-a-url-path/to-a-file/on-the-server", $1 would be "this" and $2 would be "is-a-url-path/to-a-file/on-the-server". Again, if I had some example URLs and their corresponding rewrites, I could help you find the right pattern.
On a side note, spaces aren't allowed in URLs, but the browser and server probably does some work behind the scenes, allowing your PDFs to be picked up correctly.

Resources