Not able to track htaccess issue, How to implement IF ELSE in htaccess - apache

I have a problem with htaccess to execute a rule and if rule matches then do not check for another rule. which i am trying to figure out from last few hours. Below is the sample code
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} ^/projectname/$
#RewriteCond %{REQUEST_URI} !projectname/(storage)$
RewriteRule ^(.*)$ /projectname/abc/dist/$1 [L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} projectname/(storage)$
RewriteRule ^(.*)$ /projectname/storage/$1 [L]
Rewritecond %{REQUEST_URI} projectname/(.*)$
#RewriteCond %{REQUEST_URI} !projectname/(storage)$ [NC]
RewriteCond %{REQUEST_URI} !\.(html?|png|woff|ttf|eot|svg|woff2|jpg|gif|xml|rss|png|css|js|json)$ [NC]
RewriteRule ^(.*)$ /projectname/#/$1 [NE,R=301,L]
RewriteRule ^(.*)$ /projectname/abc/dist/$1 [L]
I want to load everything from projectname/abc/dist folder but not for the case when i have storage inside url then i want to load the data from storage folder only.
So as per rules defined here everything works fine but when i have storage inside url/src for image it still checks /projectname/abc/dist/storage/xxxx.png instead of checking /projectname/storage/xxxx.png as defined in htaccess rule.
I have tried using [S=5] skip with storage rule in htaccess does not works from reference http://httpd.apache.org/docs/2.4/rewrite/flags.html.
Also as per my understanding [L] is the last so it should stop the htaccess after storage rule but it does not.
I have tried implementing IF ELSE in htaccess but the examples i tried for IF ELSE does not help even.
reference https://blogs.apache.org/httpd/entry/new_in_httpd_2_4
reference http://httpd.apache.org/docs/2.4/rewrite/flags.html (check Skip IF ELSE stanza)
Any Idea would be useful.

You want to load from 'projectname/abc/dist'-folder EXCEPT when there is 'storage' anywhere in the requested URI?! If I got that right, that might help:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} !storage
RewriteRule ^(.*)$ /projectname/abc/dist/$1 [END,P]
I added [P] for 'proxy' assuming that you don't want to show the customer he is rewritten by your server. If you don't mind seeing them, just leave that out.

First of all, L|last doesn't mean stop all processing.
If you are using RewriteRule in either .htaccess files or in sections, it is important to have some understanding of how the rules are processed. The simplified form of this is that once the rules have been processed, the rewritten request is handed back to the URL parsing engine to do what it may with it.
See also Ruleset Processing for how this works.
To load from /project/abc/dist, except when there's storage in the URL, you must first check for storage
RewriteCond %{REQUEST_URI} /storage/
RewriteRule /([^/]*$ /project/storage/$1 [L]
And then
RewriteRule ^(.*)$ /project/abc/dist/$1 [L]
Finally, to prevent a rewrite loop, prefix the rules with
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]
Everything together
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]
RewriteCond %{REQUEST_URI} /storage/
RewriteRule /([^/]*$ /project/storage/$1 [L]
RewriteRule ^(.*)$ /project/abc/dist/$1 [L]

Related

How to add/ignore a subfolder in htaccess file?

I have build an app at http://url/sdf19/
I have a .htaccess placed in /sdf19/ containing RewriteRule for clean urls.
But I have built a PDF generating tool, which is in a subfolder /inc/tools.
I need to link to it direct to run before headers.
Despite a few hours of searching, trying snippets, generators, etc. I cannot get any request to http://url/sdf19/inc/tools to be allowed, without the existing RewriteRule set taking over
Here is my starting file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-z]+)\/?$ index.php?page=$1 [NC]
RewriteRule ^([a-z]+)\/([0-9]+)\/?$ index.php?page=$1&id=$2 [NC]
RewriteRule ^([a-z]+)\/([a-z]+)\/?$ index.php?page=$1&action=$2 [NC]
RewriteRule ^([a-z]+)\/([a-z]+)\/([0-9]+)\/?$ index.php?page=$1&action=$2&id=$3 [NC]
I've tried to add this on line 4;
RewriteCond %{REQUEST_URI} !^ inc/tools/ [NC]
This gave RewriteCond: bad argument line error
I've tried to add this to line 2;
RewriteCond %{REQUEST_URI} ^/inc/tools/(.*)$
RewriteRule ^.*$ - [L]
Desired result is that I can allow direct access to http://url/sdf19/inc/tools > everything I have tried so far i get redirected to base http://url/sdf19/
Maybe, we could step by step solve this problem. First step, we might just want to make something work with as less as boundaries that'd be possible.
Let's design a low boundary expression, maybe something similar to:
(.+)(\/inc\/tools)
From here, we can just add \/inc\/tools to the RewriteCond, just for testing. Later, we can modify that.
RegEx
If this wasn't a desired expression, you can modify/change your expressions in regex101.com.
RegEx Circuit
You can also visualize your expressions in jex.im:
RewriteRule Test
You can test your RewriteRules in htaccess.madewithlove.be.
I'm not so sure about the rest of RewriteRules, but I'm assuming they are working fine and not conflicting with the new one. Maybe, this or something similar would work:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} \/inc\/tools [NC]
RewriteRule ^(.*)$ $1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-z]+)\/?$ index.php?page=$1 [NC]
RewriteRule ^([a-z]+)\/([0-9]+)\/?$ index.php?page=$1&id=$2 [NC]
RewriteRule ^([a-z]+)\/([a-z]+)\/?$ index.php?page=$1&action=$2 [NC]
RewriteRule ^([a-z]+)\/([a-z]+)\/([0-9]+)\/?$ index.php?page=$1&action=$2&id=$3 [NC]
</IfModule>

apache redirect to naked (non-www) domain messes up pages handler

all the urls in my website actually go through a PHP page that handles them by the page GET parameter (i.e. domain.com/sub/test is actually domain.com/page_handler.php?page=sub/test).
files or directories that exist don't go through the handler.
I've been trying to 301 redirect all www.domain.com requests to domain.com for improving SEO etc.
the problem is that this doesn't seem to work, no matter what rule I use and where I put it. this is the .htacess file:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
#THIS IS THE DISCUSSED RULE:
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
RewriteRule (.*[^\/])$ page_handler.php?page=$1 [QSA,NC,L]
RewriteRule ^/?$ page_handler.php?page= [L,QSA]
DirectoryIndex page_handler.php?page=
When I put the rule in the current line, it works ok with pages that are supposed to go through the handler BUT it makes existing resources go through it as well (e.g. domain.com/page_handler.php?page=js/script.js) which is not good.
When I put it after the other rules it redirects www.domain.com/something to domain.com/?page=something.
So, the question is: how to redirect urls that begin with "www." to the naked (non-www) domains without affecting the other rules?
Thank you!
The problem with your code is that you are applying the first two conditions only to the non-www rule. Conditions can only be tested for the rule that immediately follows them.
So, you'll need to move those down, and clean up a bit:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /page_handler.php?page=$1 [QSA,NC,L]
If this causes issues for you, then you may want to change the way your page is detected, by using the REQUEST_URI instead of a $_GET['page']. If you want to do this (which is actually a better method), the last rule can be changed to the following:
RewriteRule ^ /page_handler.php [QSA,NC,L]

Multiple RewriteRule to one RewriteCond

On the side I have about 400,000 subdomains. in view of the above, some calls also operate subdomain level, e.g..
subdomain1.example.com/some_action/
Such actions that should be performed only from the domain have 27.
Htaccess file I created a rule:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www.)?example.com
RewriteRule ^some_action1/?$ index.php?some_action1 [L]
If i add this line
RewriteRule ^some_action2/?$ index.php?some_action2 [L]
not work in the same way as for some_action3, etc.
I have added for each action separately
RewriteCond %{HTTP_HOST} ^(www.)?example.com
Can you somehow skip to harmonize?
Each RewriteCond condition only applies to the immediately following RewriteRule. That means if you have a bunch of rules, you have to duplicate the conditions. If you really don't want to do that for some reason, you could use a negate at the very beginning of all your rules. This may or may not be a good solution since it could affect how you make future changes to the rules:
RewriteEngine On
RewriteCond %{HTTP_HOST} !^(www.)?example.com
RewriteRule ^ - [L]
RewriteRule ^some_action1/?$ index.php?some_action1 [L]
RewriteRule ^some_action2/?$ index.php?some_action2 [L]
RewriteRule ^some_action3/?$ index.php?some_action3 [L]
etc...
So the first rule checks for the negative of the host being example.com, and skips everything. Then you can add all your rules without having to worry about that condition.
However, if your "some_action" is always going to be part of the GET parameters, you can maybe just use a single rule:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www.)?example.com
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/?$ index.php?$1 [L]

htaccess from https to http

I have these vales in my htacces file it all works fine except when i try to go back to http from https i have tried swapping the rules around with no success, any help would be awsome
I have tried all the sujestion with still no suucess so maybe i need to show you guys the entire thing.
Still not going back to http from https, here is the whole thing
Have i got the rules in the wrong order? im lost
<ifModule mod_rewrite.c>
RewriteEngine on
# For Sales:
RewriteRule ^shop/sales/?$ sales.php
# For the primary categories:
RewriteRule ^shop/([A-Z-Aa-z\+]+)/?$ shop.php?type=$1
# For specific products:
RewriteRule ^browse/([A-Za-z\+]+)/([A-Za-z\+\-]+)/([0-9]+)$ browse.php?type=$1&category=$2&id=$3
#For https pages:
#RewriteCond %{HTTPS} on
#RewriteRule ^(.*)$ http://%{HTTP_HOST}%{REQUEST_URI} [R=301,L=301]
#RewriteCond %{HTTPS} off
#RewriteRule ^(checkout\.php|final\.php|admin/(.*))$ https://{HTTP_HOST}/$1[R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?$1 [L,QSA]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s(.*)/index\.php [NC]
RewriteRule ^ /%1 [R=301,L]
</ifModule>
I am not able to test the rules, but I think you need to change the following:
In the first rule your flag is attached to the 2nd argument. This should create an internal error. Your second rule would rewrite all url's to their http equivalent, making an infinite loop. You need to make sure it doesn't match url's that you want to be in https. You can do this with %{REQUEST_URI} and a negation (!). As far as I am aware, L=301 is an invalid flag too. You probably meant to make it R=301.
RewriteCond %{HTTPS} off
RewriteRule ^(checkout\.php|final\.php|admin/(.*))$ https://{HTTP_HOST}/$1 [R,L]
RewriteCond %{HTTPS} on
RewriteCond %{REQUEST_URI} !/(checkout\.php|final\.php|admin/(.*))$
RewriteRule ^http://%{HTTP_HOST}%{REQUEST_URI} [R,L]
Last but not least an word of advice. Don't test your .htaccess with permanent redirects until everything works as expected. The browser will cache permanent redirects, not picking up further tries to make your .htaccess work as you want.

Check URL and stop processing using htaccess

I want to check URL using htaccess. Developer might want run special file - specialfile.php. I use htaccess:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} /specialfile\.php$
RewriteRule .* [L] #don't change adress
RewriteRule ^$ public/index.html [NC,L]
RewriteRule (.*) public/$1 [NC,L]
My idea was: if rewriteCond %{REQUEST_URI} !/specialfile.php$ true than htaccess should use RewriteRule .* [L] - that should mean that specialfile.php will be run and this all. But it doesn't work because it runs next rule: RewriteRule (.*) public/$1 [NC,L].
I think you are using the RewriteCond not correctly. The conditions only affect the next RewriteRule that follows.
Check out the example on the Apache Homepage. Since your 2nd RewriteRule is evalutated, I think your conditions are not correct. To get a litte bit more information about the rewriting, you should increase the log level. This is also documented here.
Your 2nd rule ^$ matches only an empty request btw. That's why it probably does not work as you expect it to.