.htaccess with multiple rewrite rules, based on path - apache

I have the following .htaccess, which is not working as expected:
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^example.bg$
RewriteRule (.*) http://www.example.bg/$1 [R=301,L]
RewriteCond %{REQUEST_URI} !^/sessiontest\.php$
RewriteCond %{REQUEST_URI} ^/login.* [OR]
RewriteCond %{REQUEST_URI} ^/admin.*$
RewriteRule ^(.*)$ travelpartner.php [L,NC]
RewriteCond %{REQUEST_URI} !^/sessiontest\.php$
RewriteCond %{REQUEST_URI} !^/login.*$
RewriteCond %{REQUEST_URI} !^/admin.*$
RewriteRule ^(.*)$ perla/$1 [L,NC]
What I need is the following:
If the URI is missing the "www" from example.bg, then add it and redirect to www.example.bg
If the URI does not end in "sessiontest.php" and starts with "www.example.bg/login" or starts with www.example.bg/admin, then forward all requets to travelpartner.php
For all other cases, we should forward all requests to a subfolder, called "perla"
However, right now what happens is that we always see the contents of the perla subfolder, even if I open exemple.bg/login
What am I missing here?

With your current rules I get the infinite redirect loop:
Once the rule No.2 is matched, and the request /login is rewritten to /travelpartner.php, the rewritten request is handed back to the URL parsing engine and the ruleset is run again from the start.
This time, it will match the last segment and be rewritten to /perla/travelpartner.php,and sent back again, and be rewritten to /perla/perla/travelpartner.php, etc...
The fix is to, in the last segment, prevent rewriting if the request starts with /perla or is /travelpartner.php:
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^example.bg$
RewriteRule (.*) http://www.example.bg/$1 [R=301,L]
RewriteCond %{REQUEST_URI} !^/sessiontest\.php$
RewriteCond %{REQUEST_URI} ^/login [OR]
RewriteCond %{REQUEST_URI} ^/admin
RewriteRule ^ travelpartner.php [L,NC]
RewriteCond %{REQUEST_URI} !^/sessiontest\.php$
RewriteCond %{REQUEST_URI} !^/login
RewriteCond %{REQUEST_URI} !^/admin
RewriteCond %{REQUEST_URI} !^/perla/
RewriteCond %{REQUEST_URI} !^/travelpartner\.php$
RewriteRule ^(.*)$ perla/$1 [L,NC]

You can use the following rules
RewriteEngine on
RewriteCond %{HTTP_HOST} ^example.bg$
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [L,R]
RewriteRule ^(login|admin) /travelpartner.php [L]
RewriteRule !(perla/|travelpartner\.php) /perla [L]

Related

Apache - .HTACCESS applies previous conditions to current rewrite url

My .htaccess applies RewriteCond's from previous RewriteRule's to the current RewriteRule.
For example example.com/acme gets redirected to http://www.example.com/index.php?url=acme.
Why would this configuration ever redirect to index.php? The index.php's RewriteRule isn't even a R=301. And the RewriteCond's that makes exceptions when the request_uri contains the string acme shouldn't even be applying themselves to this RewriteRule since they have their own RewriteRule.
RewriteEngine On
RewriteCond %{REQUEST_URI} !\.(txt) [OR]
RewriteCond %{REQUEST_URI} robots\.txt
RewriteCond %{REQUEST_URI} !acme
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{REQUEST_URI} !\.(txt) [OR]
RewriteCond %{REQUEST_URI} robots\.txt
RewriteCond %{HTTPS} !=off
RewriteRule ^ http://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
It seems lke it executed 2 rewrite rules at the same time. Adding the [END] flag fixed the issue.

HTACCESS - Allow access to folders

This is my current htaccess.
Site
|.htaccess
|--/folder-1
|--/folder-2
Now my root htaccess is as follows:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^site.com$ [NC,OR]
RewriteCond %{HTTP_HOST} ^site.com$
RewriteRule ^/?$ /public/ [L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !^/public/
RewriteRule ^(.*) /public/$1 [L]
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
I want users to access all files and folders inside folder 1 and folder 2. How that can be done?
Several changes: do your domain redirect first (note the subtle changes);
RewriteEngine on
RewriteBase /
RewriteCond %{HTTP_HOST} ^www\.(.+) [NC]
RewriteRule .* http://%1/$0 [R=301,L]
RewriteCond %{HTTP_HOST} ^site\.com$ [NC]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(?!(?:folder-1|folder-2)(?:$|/)|public/(?:index\.php)?$).* public/$0 [L]
This incorporates the folders you're excluding from rewriting into the main rule, so should be more efficient. It looks ugly since it starts with a negative look-ahead assertion (?! and the rest of the groups begin with (?: so they are non-capturing.
Do you really need a single domain? If so, it should be checked on all requests. If not, drop the first RewriteCond of the second RewriteRule.
if your default document is not index.php, change it in the negative look-ahead assertion of the second RewriteRule.

.htaccess rewrite path: New query string removes the paths first trailing slash

I have this code to rewrite a path, and then redirect to subdomain's folder:
RewriteEngine On
RewriteBase /
RewriteRule ^category/?$ category.php
RewriteRule ^category/[a-z0-9\-]+\_([A-Z0-9\_]+)/?$ articles.php?id=$1&section=category
RewriteCond %{HTTP_HOST} ^test.(.*)example.com/?$ [NC]
RewriteCond %{REQUEST_URI} !^/\!test/ [NC]
RewriteRule (.*) /!test/$1 [L,NC]
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^(.*)$ http://www.example.com/$1 [NE,L,R=301]
The big problem is that typing this in the browser address field and press Enter:
http://test.example.com/category/article-about-something_35436
Ends up in that it changes by itself to:
http://test.example.comcategory/article-about-something_35436
And the browser of course tells you that "Server is not found".
Troubleshooting
I have figured out that this works fine:
http://test.example.com/category
And removing the query string ?id=$1&section=category from the second rewrite rule works. You don't end up on the article of course but on articles.php.
So, anyone know the problem?
Rearrange your rules and keep redirect rules with R flag before other internal rewrite rules:
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [NE,L,R=301]
RewriteRule ^category/?$ category.php [L,NC]
RewriteRule ^category/[a-z0-9-]+_([A-Z0-9_]+)/?$ articles.php?id=$1&section=category [L,QSA]
RewriteCond %{HTTP_HOST} ^test\.(.*)example\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/\!test/ [NC]
RewriteRule (.*) /!test/$1 [L,NC]

Apache .hatccess rewrites not working for legacy URLS

I'm trying to rewrite some legacy Joomla URLs on a site that's now using ExpressionEngine as its CMS but they're not working.
The ExpressionEngine URL rewrites, i.e. removing index.php from the URL work fine though.
This is what I've got:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} !=on
# This is the one that's not working
RewriteRule /index.php?option=com_chronocontact&Itemid=54 /contact/ [R=301,L]
# Force www
RewriteCond %{HTTP_HOST} !^www\..+$ [NC]
RewriteCond %{HTTP_HOST} (.+)$ [NC]
RewriteRule ^(.*)$ http://www.%1/$1 [R=301,L]
# Redirect index.php Requests
RewriteCond %{THE_REQUEST} ^[^/]*/index\.php [NC]
RewriteCond %{THE_REQUEST} ^GET
RewriteRule ^index\.php(.+) $1 [R=301,L]
# Standard ExpressionEngine Rewrite
RewriteCond %{REQUEST_URI} ^/
RewriteCond %{QUERY_STRING} ^(gclid=.*)
RewriteRule ^(.+) /index.php?/ [L,PT]
RewriteCond $1 !\.(css|js|gif|jpe?g|png) [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond $1 !^(assets|css|images|tinymce|js|min|cms|themes|index\.php|admin\.php|favicon\.ico|index\.php|path\.php|php\.ini) [NC]
RewriteRule ^(.+) /index.php?/ [L]
</IfModule>
Can anyone spot what I'm doing wrong?
The first thing is the stray RewriteCond %{HTTPS} !=on that you have at the top. It looks like it belongs to the rule under it, as in:
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} !^www\..+$ [NC]
RewriteCond %{HTTP_HOST} (.+)$ [NC]
RewriteRule ^(.*)$ http://www.%1/$1 [R=301,L]
As far as the rule that you have commented that doesn't work, the ? is a reserved character for regular expressions, and your pattern actually says that the second p in /index.php is "optional". Additionally, you can't match against the query string in a rewrite rule, you need to use a rewrite condition and match against the %{QUERY_STRING} variable:
RewriteCond %{QUERY_STRING} ^option=com_chronocontact&Itemid=54$
RewriteRule ^(index.php)?$ /contact/? [R=301,L]
is probably more along the lines of what you're looking for.

redirecting file request for subdomain and main site with certain arguments?

I am running wildcard subdomains. the aim of the site is to run a virtual subdomain. what the functionality should be is that when the files
from the main site are called they will be rewritten for the clean URLs. But when i am calling the same files form the subdomain
like xyz.doamin.com/my-file.php then this should be rewritten like it is calling that file with an argument of subdoamin like
domain.com/my-file.php?var=xyz. Currently what i have done for the file call is this
Options +FollowSymLinks
RewriteEngine on
## Redirecting all non-www domains to www.domain.com
RewriteCond %{HTTP_HOST} ^domain.com [NC]
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301,NC,L]
RewriteCond %{HTTP_HOST} !^www\.domain\.com$ [NC]
RewriteCond %{HTTP_HOST} ^(.*)\.domain\.com$ [NC]
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^(.*)$ http://www.domain.com%{REQUEST_URI}?var=%1 [L]
RewriteCond %{HTTP_HOST} !^www\.domain\.com$ [NC]
RewriteCond %{HTTP_HOST} ^(.*)\.domain\.com$ [NC]
RewriteCond %{QUERY_STRING} !^$
RewriteRule ^(.*)$ http://www.domain.com%{REQUEST_URI}?%{QUERY_STRING}&var=%1 [L]
RewriteCond %{HTTP_HOST} !^www\.domain\.com$ [NC]
RewriteCond %{HTTP_HOST} ^(.*)\.domain\.com$ [NC]
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^(.*)$ http://www.domain.com/index.php?subdomain=%1 [L]
RewriteCond %{HTTP_HOST} !^www\.domain\.com$ [NC]
RewriteCond %{HTTP_HOST} ^(.*)\.domain\.com$ [NC]
RewriteCond %{QUERY_STRING} !^$
RewriteRule ^(.*)$ http://www.domain.com%{REQUEST_URI}?%{QUERY_STRING}&subdomain=%1 [L]
This is throwing a 500 internal error for the file call.
Rule set 4 will overlap with rule set 1 and 2. I suspect this is causing the issue.
So I think all 3 need an extra RewriteCond check on REQUEST_URI.
Really you shouldn't need rule set 4. Just including index.php as a default should do the trick. Unless of course you don't want URL's like http://www.domain.com/?var=xyz, in this case you need rule 4, but you need to split it into 2 - one with a QUERY_STRING and one without, just like rule 1 and 2
Also, isn't %1 from the regex in the rewriteRule itself and not the preceeding rewriteConds? If so then your regex is wrong, because it'll be setting the var= to the entire original URL.
Looking in the error log is a good idea as it will give you the reason for the 500 error.
Edit: Ok, try something like this (not tested)
## Redirecting all non-www domains to www.domain.com
RewriteCond %{HTTP_HOST} ^domain.com [NC]
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301,L,QSA]
## Redirecting / requests to index.php
# Note: Use the QSA flag for handling with or without query string
RewriteCond %{REQUEST_URI} ^/$
RewriteCond %{HTTP_HOST} !^www\.domain\.com$ [NC]
RewriteCond %{HTTP_HOST} ^(.*)\.domain\.com$ [NC]
RewriteRule ^(.*)$ http://www.domain.com/index.php?var=%1 [L,QSA]
## Redirecting /something requests to index.php
# Note: Use the QSA flag for handling with or without query string
RewriteCond %{REQUEST_URI} ^/.+$
RewriteCond %{HTTP_HOST} !^www\.domain\.com$ [NC]
RewriteCond %{HTTP_HOST} ^(.*)\.domain\.com$ [NC]
RewriteRule ^(.*)$ http://www.domain.com%{REQUEST_URI}?var=%1 [L,QSA]