exclude files from rewrite rule in .htaccess - apache

I'm modifying an existing website that uses a fairly complex .htaccess file to implement a custom MVC type framework so all urls are redirected to index.php?[some parameters] or a 404 page. I'd like to add ajax support to a limited area of the site using XAJAX, and to implement that I need to place two files in the root which are ignored by the rewrite rules. How do I do that?

How about identity rewriting rule with “last” flag on the top of your rules?
For example, to exclude “/a-file-outside-of-rewriting.html” from current set of rules, the following configuration might help:
# http://~/outside-of-rewriting.html will be rewritten to itself (i.e., unmodified).
# then no more rules will be applied (because it has “last” flag.)
RewriteRule ^/a-file-outside-of-rewriting.html$ $0 [L]
RewriteRule ^/any/other/rules(/.*) $1
RewriteRule ^/already/exist(/.*) $1
# ...

Related

Execute PHP script without Redirect

I have below Rewrite rule in .htaccess:
# /m/yyy rule
RewriteRule ^m/([\w-]+)/?$ accounts/$1/index.php [L,NC]
# /m/yyy/abc rule
RewriteRule ^m/([\w-]+)/([\w-]+)$ accounts/$1/$2.php [L,NC]
# /m/yyy/abc/ rule
RewriteRule ^m/([\w-]+)/([\w-]+)/$ accounts/$1/$2/index.php [L,NC]
I want to execute the PHP script view.php if the URL is https://example.com/m/mya/view.php, I expect accounts/mya/view.php to be executed.
Please advise how I can do.
I assume your existing rules are being used for other purposes, since none of them will match the stated URL.
To internally rewrite the request /m/mya/view.php to /accounts/mya/view.php (as stated) then you would add the following before (or after) your existing rules:
RewriteRule ^m/(mya/view\.php)$ accounts/$1 [L]
To make this more generic and rewrite the request /m/<file> to /accounts/<file>, but only if /accounts/<file> exists then you can do something like the following instead before (or after) your existing rules:
RewriteCond %{DOCUMENT_ROOT}/accounts/$1 -f
RewriteRule ^m/([\w/-]+\.\w{2,5})$ accounts/$1 [L]
UPDATE: The regex part \.\w{2,5} matches, what looks-like, a file extension. ie. a dot followed by between 2 and 5 word characters. If you are only matching .php files then you can change this to \.php to hardcode the .php extension. Use a regex testing tool such as regex101.com to test this and get a detailed explanation of the regex (this is not unique to Apache - Apache uses the same regex engine as PHP and other languages, ie. PCRE).
The preceding RewriteCond (condition) directive then checks that this file exists at the intended destination before actually rewriting the request. Without this, the request is rewritten unconditionally, regardless of whether the target file exists or not. eg. /m/abc/xyz/does-not-exist.php would be internally rewritten to /accounts/abc/xyz/does-not-exist.php which then triggers a 404 later (potentially exposing the accounts subdirectory - depending on how you are handling your 404s).
The order of these rules in relation to your existing rules as posted does not matter since the regex (RewriteRule patterns) do not conflict when making a request for a file (that contains a dot before the file extension).

Redirect to a specific page from any dir or subdir in htaccess

Is it possible to use an universal rule to redirect to a specific page from whatever directory or subdirectory using .htaccess?
To be more precise, if I want to have an URL like example.com/login that redirects to example.com/login.php?action=login, I use the following line in my .htaccess file:
RewriteRule ^login$ /login.php?action=login [L]
But is it possible to to have a rule that lets me redirect from example.com/any_directory/login to example.com/login.php?action=login? So from anywhere down the example.com subdirectories to ``example.com/login.php?action=login`. And if yes, how can I do this
Certainly that is possible. Easiest is to use a rewrite condition since that operates on the absolute request path even inside a dynamic configuration file. Rewrite rules operate on a relative path i such location which makes matching complicated...
Take a look at this simple example:
RewriteEngine on
RewriteCond %{REQUEST_URI} /login$
RewriteRule ^ /login.php?action=login [L]
If you do the rewriting in the http servers host configuration instead you can simplify that. Reason is that it is always absolute paths the rules work on in that location:
RewriteEngine on
RewriteRule /login$ /login.php?action=login [L]
The main approach in both variants is to rely on the slash preceding the login key word. It always is present in an absolute request path and clearly left-delimits the key word. And not to insist on matching at the line start.
And a general hint: you should always prefer to place such rules inside the http servers host configuration instead of using dynamic configuration files (".htaccess"). Those files are notoriously error prone, hard to debug and they really slow down the server. They are only provided as a last option for situations where you do not have control over the host configuration (read: really cheap hosting service providers) or if you have an application that relies on writing its own rewrite rules (which is an obvious security nightmare).
You need to adjust your regex pattern .Simply remove the ^ ,so that it can match anychars before login/ in uri ie : /foobar/login .
RewriteRule /login/?$ /login.php?action=login [L]

Apache 301 redirect with get parameters

I am trying to do a 301 redirect with lightspeed webserver htaccess with no luck.
I need to do a url to url redirect without any related parameters.
for example:
from: http://www.example.com/?cat=123
to: http://www.example.com/some_url
I have tried:
RewriteRule http://www.example.com/?cat=123 http://www.example.com/some_url/ [R=301,L,NC]
Any help will be appreciated.
Thanks for adding your code to your question. Once more we see how important that is:
your issue is that a RewriteRule does not operate on URLs, but on paths. So you need something like that instead:
RewriteEngine on
RewriteRule ^/?$ /some_url/ [R=301,L,NC,QSD]
From your question it is not clear if you want to ignore any GET parameters or if you only want to redirect if certain parameters are set. So here is a variant that will only get applied if some parameter is actually set in the request:
RewriteEngine on
RewriteCond %{QUERY_STRING} (?:^|&)cat=123(?:&|$)
RewriteRule ^/?$ /some_url/ [R=301,L,NC,QSD]
Another thing that does not really get clear is if you want all URLs below http://www.example.com/ (so below the path /) to be rewritten, or only that exact URL. If you want to keep any potential further path component of a request and still rewrite (for example http://www.example.com/foo => http://www.example.com/some_url/foo), then you need to add a capture in your regular expression and reuse the captured path components:
RewriteEngine on
RewriteRule ^/?(.*)$ /some_url/$1 [R=301,L,NC,QSD]
For either of this to work you need to have the interpretation of .htaccess style files enabled by means of the AllowOverride command. See the official documentation of the rewriting module for details. And you have to take care that that -htaccess style file is actually readable by the http server process and that it is located right inside the http hosts DOCUMENT_ROOT folder in the local file system.
And a general hint: you should always prefer to place such rules inside the http servers host configuration instead of using .htaccess style files. Those files are notoriously error prone, hard to debug and they really slow down the server. They are only provided as a last option for situations where you do not have control over the host configuration (read: really cheap hosting service providers) or if you have an application that relies on writing its own rewrite rules (which is an obvious security nightmare).

Apache rewrite third directory depth to first directory depth

I have resources for two websites located here...
localhost/index.php /* rewrite handler */
localhost/images/
localhost/scripts/
Then I have the two sites...
localhost/site1/
localhost/site2/
I want to rewrite...
localhost/site1/images/
localhost/site2/images/
localhost/site1/scripts/
localhost/site2/scripts/
...to...
localhost/images/site1/
localhost/images/site2/
localhost/scripts/site1/
localhost/scripts/site2/
Is there a way to make "site1" and "site2" a dynamic variable (so that I don't have to manually add an exception or rule if I add more sites in the future) that will rewrite in this manner?
This rule REWRITES the directory, I want to be able to access the files AS WELL, not just the index...
RewriteRule .*\/scripts\/$ scripts\/$1 [L]
For once the Apache documentation was useful!
http://httpd.apache.org/docs/2.3/rewrite/flags.html#flag_qsa
RewriteEngine on
RewriteRule .*\/scripts(.+) scripts$1 [QSA]

mod_rewrite to alias one file suffix type to another

I hope I can explain this clearly enough, but if not let me know and I'll try to clarify.
I'm currently developing a site using ColdFusion and have a mod_rewrite rule in place to make it look like the site is using PHP. Any requests for index.php get processed by index.cfm (the rule maps *.php to *.cfm).
This works great - so far, so good. The problem is that I want to return a 404 status code if index.cfm (or any ColdFusion page) is requested directly.
If I try to block access to *.cfm files using mod_rewrite it also returns a 404 for requests to *.php.
I figure I might have to change my Apache config rather than use .htaccess
You can use the S flag to skip the 404 rule, like this:
RewriteEngine on
# Do not separate these two rules so long as the first has S=1
RewriteRule (.*)\.php$ $1.cfm [S=1]
RewriteRule \.cfm$ - [R=404]
If you are also using the Alias option then you should also add the PT flag. See the mod_rewrite documentation for details.
Post the rules you already have as a starting point so people don't have to recreate it to help you.
I would suggest testing [L] on the rule that maps .php to .cfm files as the first thing to try.
You have to use two distinct groups of rewrite rules, one for .php, the other for .chm and make them mutually exclusives with RewriteCond %{REQUEST_FILENAME}. And make use of the flag [L] as suggested by jj33.
You can keep your rules in .htaccess.