.htaccess RewriteRule for multiple pages - regex

I've done RewriteRule for index page in my website.
Here is the code below:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^([a-zA-Z0-9+\-\(\)]+)/?$ /index.php?origin=$1
RewriteRule ^([a-zA-Z0-9+\-\(\)]+)/([a-zA-Z0-9+\-]+)/?$ /index.php?origin=$1&gender=$2
RewriteRule ^([a-zA-Z0-9+\-\(\)]+)/([a-zA-Z0-9+\-]+)/([a-zA-Z0-9+\-]+)/?$ /index.php?origin=$1&gender=$2&type=$3
RewriteRule ^([a-zA-Z0-9+\-\(\)]+)/([a-zA-Z0-9+\-]+)/([a-zA-Z0-9+\-]+)/([a-zA-Z0-9+\-]+)/?$ /index.php?origin=$1&gender=$2&type=$3&page=$4
</IfModule>
and the url is looks like
http://babynames.agurchand.com/scottish/male/pythagorean
It's a single page website, so everything is working fine so far.
Then i wanted to add one more page on my website and i have added too. file name is 'namemeaning.php'.
I've added the below code in addition of the htaccess pasted, at the bottom. But It doesn't seem to be working.
RewriteRule ^/namemeaning/([a-zA-Z0-9+\-\(\)]+)/?$ /namemeaning/namemeaning.php?name=$1
I've tried with the below url, but I'm still being referred to the index page only.
http://babynames.agurchand.com/namemeaning/abasi
Can anyone give me a solution for this please!

You're being forwarded to the index page because your regular expression for the index page fits your request. You're being sent to index.php?origin=namemeaning&gender=abasi
http://babynames.agurchand.com/namemeaning/abasi
'namemeaning' fits the rule ([a-zA-Z0-9+\-\(\)]+)
'abasi' fits the rule ([a-zA-Z0-9+\-]+)
A simple fix would be adding the line
RewriteRule ^/namemeaning/([a-zA-Z0-9+\-\(\)]+)/?$ /namemeaning/namemeaning.php?name=$1
above the line
RewriteRule ^([a-zA-Z0-9+\-\(\)]+)/?$ /index.php?origin=$1
You should remember to always place the most specific RewriteRule(s) above those that are more general.
For more information about regular expressions, I can advice you this website.

The rewruite rules are checked sequentially from top to bottom, and all rules matched are applied in that order. Double check that none of your rules match before the desired one.
Good Tool for that purpose is http://www.regextester.com/

Related

Rewrite Portion of URL Only

I am trying to rewrite a URL so that this-area-profile- will change to area-profile-, with everything after "profile-" matching what was in the original URL:
http://example.com/a-directory/this-area-profile-everything-after-profile-
http://example.com/a-directory/area-profile-everything-after-profile-
The below is my latest of numerous attempts, based on what I have read here and on other websites:
RewriteRule ^a-directory/area-profile-(.+)$ /a-directory/this-area-profile-$1 [R=301,L]
The other answers talk about changing or removing a directory, but I want to rename a portion of the URL.
I know my english is bad, but I understand the opposite from your explanation:
RewriteRule ^a-directory/this-area-profile-(.+)$ /a-directory/area-profile-$1 [R=301,L]

My apache rewrite only works for the first folder level

We have a website where we show clients creative work we have produced for them. We upload raw assets to a path like this:
x.com/clients/clientName/campaignName/size/
I have a PHP script which adds our branding, contact information and other information and pulls in the raw creative (usually a swf object). It is in this directory x.com/clients/index.php and it accepts a query string parameter ?path so it knows where to look for the creative.
I am trying to do an apache rewrite in .htaccess so that our designers can upload directly to the known folder structure but so that when you go to x.com/clients/clientName/campaignName/size/ it should rewrite to x.com/clients/index.php?path=clientName/campaignName/size/
I am currently using the following rewrite rule, which works for the first folder level e.g. x.com/clients/clientName/ does successfully rewrite, but any subsequent folders do not.
RewriteRule ^clients/([^/\.]+)/?$ /clients/index.php?path=$1 [L]
My RegEx's are terrible, so I'm stuck on what to do. Any help appreciated, thank you kindly.
Your regex is only matching urls like clients/xxxxxx/ because your pattern [^/\.]+ means one or many characters except "/" or "."
With your rule, it can't work for other subdirectories.
You can change your rule by this one
RewriteRule ^clients/(.+)$ /clients/index.php?path=$1 [L]
To avoid internal server error (code 500 which means an infinite loop in this case), you can do it this way
RewriteRule ^clients/index\.php$ - [L]
RewriteRule ^clients/(.+)$ /clients/index.php?path=$1 [L]
Is there a special reason you want to use regex? In my opinion you can just catch everything coming after /clients:
RewriteEngine on
RewriteCond %{REQUEST_URI} !^(.*/)?index\.php$ [NC]
RewriteRule ^clients/(.*)$ /clients/index.php?path=$1 [L]
The second line is to prevents redirect loops, because the index.php is also in the folder /clients and this would cause never ending redirects.

.htaccess | Rewrites with pages

So I'm adjusting the URLs on a site I'm working on and I'm having some trouble with a couple of variables being passed in the URL.
mylighting.com/bath-fixture-c-13.html?osCsid=u2qj8o9rvjn0p5pa7p8npuhs54
RewriteRule ^bath-fixture bath-fixture-c-13.html?id=$1
So this Rewrite works perfect as the page that comes up is mylighting.com/bath-fixture
Now unfortunately on that page there are several other items to view and I'm having some trouble with the page variable. I think I have the code correct but every time I try to go to the correct page it doesn't seem to work.
http://mylighting.com/bath-fixture-c-13.html?page=2&id=u0hnumfus6gjhjc45av36663m3
RewriteRule ^bath-fixture/([a-zA-Z0-9]+)$ bath-fixture-c-13.html?page=$1&id=$2
So I thought I had this correct but apparently not. I would like the output to be
mylighting.com/bath-fixture/2 for the second page.
Unfortunately with that code in the .htaccess, every time I input that URL it takes me to the first page of the category and not the second like it should.
It appears that you have misunderstood the format of the RewriteRule. The first one is working by accident.
RewriteCond %{QUERY_STRING} page=([0-9]+)
RewriteRule ^bath-fixture-c-13.html bath-fixture/%1 [R=301,QSA,L]
RewriteRule ^bath-fixture-c-13.html bath-fixture/ [R=301,QSA,L]
The first argument to RewriteRule is the regex to match against the requested URL. The second argument is the URL to send as a Redirect to the user, so they end up at your desired URL instead. Because you want to parse the QUERY_STRING I believe you need to use a RewriteCond. If you are doing this for SEO purposes do not forget to add the [R=301].
http://httpd.apache.org/docs/current/mod/mod_rewrite.html
If you are trying to go the other direction then you need the following.
RewriteRule ^bath-fixture/$ bath-fixture-c-13.html [QSA,L]
RewriteRule ^bath-fixture/([0-9]+) bath-fixture-c-13.html?page=$1 [QSA,L]
If you can clarify your desired inputs and outputs you will get correct answers much more quickly.

How can I improve my .htaccess mod_rewrite stuff?

I've created the following .htaccess file after hours of work,
Everything seems to be working properly, however I'm new to mod_rewrite, and I think my code is amateurish, so I'm looking for things to improve.
For example I thought if I use [L] at the end of a rule, the rest of rewrites will be ignored, but looking at the rewrite logs I see that they are not, there are multiple unwanted pattern matchings that certainly will slow everything down.
Also I have a book that says [C] will chain rewrite conditions, but my apache throws
http://pastebin.com/62JyBXdS
The [L] flag does indeed prevent further rules from processing, however the rewritten url could be passed back through all of your rules a second time hence the multiple entries in your log - see the manual page http://httpd.apache.org/docs/2.2/rewrite/flags.html#flag_l
Alot of your rewrite rules do the same thing with just different data and could be compacted down to a single regex, I've done a few but you could do the entire list.
RewriteRule ^/([dprcmlfb]|members|lnli|freelisting)/(.*)$ /$1\.php/$2 [L]
if you also add a RewriteCond of somethine like
RewriteCond %{REQUEST_URI} !^/[^/]+\.php
to prevent the rule firing for a php file request
You could add the MultiViews option instead of rules like the rule below:
RewriteRule ^/d/(.*)$ /d\.php/$1 [L]
MultiViews would correctly interpret /d/stuff as a request to d.php if no other rule interferes.

Is there a better way to do this regex?

I finally figured out a good/easy way to make clean URLs with regex on my site in this format below, however it will require a very large .htaccess file, I know from the post on here that it is supposed to not be to bad on performance to use mod_rewrite but I have never really seen it used where the way I am, with a seperate entry for almost every page of my site.
Below is an example of an entry, there is 2 entries for 1 page, the first entry re-writes
http://www.example.com/users/online/friends/
to
http://www.example.com/index.php?p=users.online.friends
It works great but if the user is not on the first page then there is another thing added to the URL for paging and I had to write another entry to rewrite when this happens, is this the correct way or should these be combined somehow?
RewriteRule ^users/online/friends/*$ ./index.php?p=users.online.friends&s=8
RewriteRule ^users/online/friends/(\d+)/*$ ./index.php?p=users.online.friends&s=8&page=$1
The second one would do this
http://www.example.com/users/online/friends/22/
to
http://www.example.com/index.php?p=users.online.friends&page=22
It depends what you think is more readable, but here's how you could do it with a single rule:
RewriteRule ^users/online/friends(/(\d+))?/*$ ./index.php?p=users.online.friends&s=8&page=$2
(Edited to be more faithful to treatment of trailing slash in original question. Was: RewriteRule ^users/online/friends/((\d+)/*)?$ ./index.php?p=users.online.friends&s=8&page=$2)
Here I've just put "(...)?" around the final part of the url to make it an optional match, and changed the backreference to $2.
Of course, this actually rewrites http://www.domain.com/users/online/friends/ as:
http://www.domain.com/index.php?p=users.online.friends&page=
So your PHP code would have to check whether the page parameter is non-empty.
Yes, that's fine. I guess they could be combined into a single rule but there's not really any need.
You might consider leaving page as part of the URL so instead of:
http://www.domain.com/users/online/friends/22/
just have:
http://www.domain.com/users/online/friends?page=22
and then have one rule something like:
RewriteRule ^users/online/friends/?$ ./index.php?p=users.online.friends&s=8 [L,QSA]
to append the query string
Edit: There are a couple of ways of reducing the number of rewrite rules you have.
Firstly, use wildcards in the search terms, like:
RewriteRule ^users/(\w+)/(\w+)$ /index.php?p=users.$1.$2 [L,QSA]
will reduce quite a number of rules.
Secondly, if you're passing everything through /index.php just consider delegating all requests there:
RewriteRule ^(users/*)$ /index.php/$1 [L,QSA]
That rule uses a third technique: instead of passing the path information via a query string parameter, pass it via the extra path info. That can be accessed via $_SERVER['PATH_INFO'].
That being said, lots of rules isn't necessarily bad. At least it's explicit about all your actions. The thing you have to watch out for is creating a maintenance nightmare however.
# Initial step
RewriteCond %{QUERY_STRING} !(?:^|&)p=
RewriteRule ^([^/]+)/(.+) /$2?p=$1 [QSA]
# Subsequent steps
RewriteCond %{QUERY_STRING} ((?:[^&]*&)*?)p=([^&]*)(.*)
RewriteRule ^([^/]+)/(.+) /$2?%1p=%2.$1%3
# Last step with page number
RewriteRule ^(\d+)/?$ /index.php?page=$1 [QSA,L]
# Last step without page number
RewriteCond %{QUERY_STRING} (?:((?:[^&]*&)*?)p=([^&]*))?(.*)
RewriteRule ^([^/]+)/?$ /index.php?%1p=%2.$1%3 [L]
This would rewrite the URL in several steps:
http://www.domain.com/users/online/friends/22/
http://www.domain.com/online/friends/22/?p=users
http://www.domain.com/friends/22/?p=users.online
http://www.domain.com/22/?p=users.online.friends
http://www.domain.com/index.php?p=users.online.friends&page=22
An easier method would be the following, but would require you to change your scripts:
RewriteRule ^(.*?)(?:/(\d+))?/?$ /index.php?p=$1&page=$2 [QSA,L]
It would do everything in one step, with a little difference:
http://www.domain.com/users/online/friends/22/
http://www.domain.com/index.php?p=users/online/friends&page=22
Adding the s=8 query argument would require more work:
Creating a text-file with the menu numbers for each page.
Adding a RewriteMap directive.
Changing the second-last rule to use the same RewriteCond as the last rule has.
Adding &s=%{menumap:%2|0} to the last two rules.