Apache Mod Rewrite with Periods in URL - apache

Ok,
so I am using (or trying to use) two primary mod_rewrite rules, and they seem to be conflicting with one another
RewriteRule ^/?help$ index.php?page=help [L]
and
RewriteRule ^/?([a-zA-Z0-9._-]+)$ index.php?user=$1 [L]
If I get rid of the period ->. in the second rule, my help page is displayed, and I can display a user page as well, but when I add the period, my help page doesn't display, but instead (I think) gets processed as a user page.
Anyone have any pointers?

I looked at something another user ran into here - Apache / mod_rewrite / Periods messing with pattern , and modified his rule, and it is working -
RewriteRule ^/?help$ index.php?page=help [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/?([a-zA-Z0-9\[\]\.()+|_-]+)$ index.php?user=$1 [L]
Thankyou for the response.

First, if you are doing this in .htaccess mod_rewrite does not stop processing but instead does an internal redirect. See this answer for details.
You need to escape the period in your second rewrite rule. Period (or dot) will match any character if not escaped.
Fixed rule:
RewriteRule ^/([a-zA-Z0-9\._-]+)$ /index.php?user=$1 [L]
Edit 3:
Based on your comments and own answer, here's an updated solution. The way RewriteCond %{REQUEST_FILENAME} works in Apache depends on the context you are in. You can also omit the ? from the matching pattern.
RewriteRule ^/help$ /index.php?page=help [L]
# If you are inside <VirtualHost> context
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteRule ^/([a-zA-Z0-9\._-]+)$ /index.php?user=$1 [L]
# If you are inside <Directory> or .htaccesscontext
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/([a-zA-Z0-9\._-]+)$ /index.php?user=$1 [L]
Do bear in mind that this solution causes conflicts if there are users with the same name as any of the files or directories you have on your server.

Related

Adding exceptions to mod_rewrite

I got my basic redirects work with the mod_rewrite module. When requesting pages e.g. localhost/home it's correctly redirecting to localhost/index.php?page=home, but I have a problem with exceptions.
I created a folder api where I store files by category e.g. api/auth/register.php and api/customer/create.php. I tried to make rewrite rule that contains 2 params (in this example auth and customer) so basically it just drops the .php off from the url.
The rule that I made is following
RewriteRule ^api/(.*)/(.*)/?$ api/$1/$2.php [L]
After adding that line to my .htaccess, problems started to occur. For example my .css and .js files started to redirect. So maybe I need to make some exeption for the apis? Have you some other ideas to improve my rewrite rules?
.htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^api/(.*)/(.*)/?$ api/$1/$2.php [L] # problems started to occur after adding this line
RewriteRule (.*) index.php?page=$1 [L,QSA]
Thanks in advance.
RewriteCond will affect only the first following RewriteRule so you need the keep them next to your initial Rule, and move the added one above them (with its own conditions).
Also, your /api rule is not strict enough ((.*) will pick anything, including the slashes), which might not matter in you case, but still. I sugest you try with this:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^api/([^/]*)/([^/]*)/?$ api/$1/$2.php [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php?page=$1 [L,QSA]

htaccess to route all requests through index add add trailing slash

This probably seems like quite a simple question to most of you, but i'm having a real hard time getting my site to route all requests through the index file whilst also enforcing trailing slashes. I've searched high and low and not found an appropriate solution. My .htaccess so far is as follows:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [QSA,L]
RewriteCond %{REQUEST_URI} /+[^\.]+$
RewriteRule ^(.+[^/])$ %{REQUEST_URI}/ [R=301,L]
This is as far as i have managed to get and works apart from it adds the index.php into the url, for example if a user goes to;
www.example.com/about-us
I would like it to route through index and become;
www.example.com/about-us/
However my above htaccess file produces;
www.example.com/index.php/about-us/
Seems so close yet so far, anything i do to the htaccess file to try and remove the index.php just stops it from working entirely. I am aware my solution is far from perfect, it still allows access to directories and files however its the best i've been able to come up with (would ideally like to deny directory listing!)
Any help is greatly appreciated!
The ordering of rules is quite important in these cases. Switch the two rules order, and you should be getting the desired behaviour:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} /+[^.]+$
RewriteRule ^(.+[^/])$ %{REQUEST_URI}/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [QSA,L]

RewriteRule for several parameters

I'm currently working on a project powered by a home-made CMS and I'm experiencing some issues with URL rewriting.
Here's the thing: all the website is centralized around the index.php located in the main directory. Depending on what he gets thought the URL, the index.php displays the right page (the pages are included from a inc/pages/ folder)
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
RewriteRule ^([A-Za-z0-9-]+)/?$ index.php?page=$1 [NC]
For a single parameter, it works great. http://demo.com/subscribe/ or demo.com/subscribe does transmit a $_GET['page'] to the index.
For some pages, I do need a second parameter. So it's not required for each single pages. Per example, http://demo.com/edit/I-love-Stackoverflow should transmit a $_GET['snd_param')
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
RewriteRule ^([A-Za-z0-9-]+)/([A-Za-z0-9-]+)?$ index.php?page=$1&snd_param=$2 [NC]
I tried this but this isn't working well. First, if the second parameter is not mentioned (demo.com/edit) it's not working. The index doesn't receive the right $_GET['page']. Secondly, when the second parameter is mentionned, it "works" but apache believes this is a directory. My index page is then located in the fictive "I-love-Stackoverflow" folder and loading the CSS, images and javascript fails.
I hope I explained my issue pretty clearly ! Thanks in advance for helping me
You should treat the rules separately. All Conditions preceding rules only apply to a single rule, so basically the second RewriteRule is not executed at all.
You can use something like this:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)$ index.php?page=$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)$ index.php?page=$1&snd_param=$2 [L]
My index page is then located in the fictive "I-love-Stackoverflow"
folder and loading the CSS, images and javascript fails.
You are probably load your assets using relative paths, so the browser only knows for the unmodified url ( http://demo.com/edit/I-love-Stackoverflow ) in your case, and the wrong urls are created when browser load the assets. If you load resources with absolute paths instead of relative, you will be okay.

URLs redirecting to index.php when no protocol

Hoping someone with more htaccess experience can help us with this. We have Drupal 7 site that we have just moved from a dev to the live host (different hosting companies). However, now when someone puts a url with no protocol directly into the address bar (for example: examplesite.com/members), the page redirects to examplesite.com/index.php. I have been muddling around trying to fix this in the htaccess file, but have not been able to find the proper syntax for allowing urls with no protocol, while also forcing https://.
Our code:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^ index.php [L]
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
We have tried moving the RewriteRule ^ index.php [L] line to underneath all rules, or commenting it out. This fixed the initial problem, but breaks the drupal admin functionality on the backend (can't see the admin menu, can't save anything, etc)
Any insight would be helpful, let me know if more info is needed. Thank you in advance.
You need to move the entire block, conditions + rule to the bottom. Drupal routes everything through the index.php script and it requires the previous 3 conditions in order to do that properly. If you simply move the RewriteRule line, then the conditions are all gone.
RewriteEngine On
# this needs to come first
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
# then drupal stuff comes LAST
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^ index.php [L]

RewriteRule not working fine

I wrote the following rule in .htaccess
Options +FollowSymLinks
RewriteEngine on
RewriteRule ^(.*)/$ profile.php?business=$1
When i enter the URL like
http://www.abc.com/mujeeb/
page is correctly transfered to profiles page and page looks fine.
But i enter this in URL
http://www.abc.com/mujeeb
page doesn't show.
Can you please tell why? Or write the rule for this? i tried many times but not sucessful.
Mujeeb.
page doesn't show. because you specified that you RewriteRule is applied to the URL's ending with / at the end. Rewrite it as
RewriteRule ^(.*)/?$ profile.php?business=$1 [L]
And I hope that you have additional RewriteCond statements in order to prevent the infinite loop with redirects.
ps: basically you can prevent loop in two way
1) checks that requested url does not correspond to the existing file or directory. it is, probably, the best way to do (read comments to the second method)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/?$ profile.php?business=$1 [L]
2) checks that you are requesting not the file from RewriteRule. This method is not good, because for each request, even for existing files and directories, it calls profile.php script
RewriteCond %{REQUEST_URI} !profile\.php$
RewriteRule ^(.*)/?$ profile.php?business=$1 [L]
It is because you check for the trailing slash with ^(.*)/$. If you add a question mark, the trailing slash will be optional.
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.*)/?$ profile.php?business=$1
The RewriteCond is neccessary to make sure the Rule will only be applied once. Otherwise Apache will be caught in an infinite loop.
Try this:
Options +FollowSymLinks
RewriteEngine on
RewriteRule ^(.*)[/]?$ profile.php?business=$1
That makes the last slash optional.
Well you rule is checking for a trailing slash in URI and that's the reason /mujeeb/ works but /mujeeb does not. Change your code to:
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
# If the request is not for a valid file
#RewriteCond %{REQUEST_FILENAME} !-d
# If the request is not for a valid directory
#RewriteCond %{REQUEST_FILENAME} !-f
# your rule without trailing slash
RewriteRule ^(.*)$ profile.php?business=$1 [L,QSA]
Plenty of good answers already. My answer is a bit different.
This is what I usually do. If the requested URL doesn't end with a /, I make the browser redirect to a URL with the trailing /. This is consistent with the default behaviour of Apache (due to mod_dir). So, this is how I solve this problem.
RewriteEngine On
# Canonicalize http://example.com/mujeeb to http://example.com/mujeeb/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)([^/])$ /$1$2/ [R=307,L]
# Let profile.php process http://example.com/mujeeb/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ profile.php?business=$1