Reputation: 7597
If have the following possible urls:
http://stackoverflow.com/categories/
http://stackoverflow.com/categories/category-type
http://stackoverflow.com/categories/category-type/category
http://stackoverflow.com/categories/category-type/category/sub-category
which I want to rewrite to
http://stackoverflow.com/categories/
http://stackoverflow.com/categories/?category-type=category-type
http://stackoverflow.com/categories/?category-type=category-type&category=category
http://stackoverflow.com/categories/?category-type=category-type&category=category&sub-category=sub-category
And here are my rewrite rules:
RewriteRule ^categories/([^/]*)/([^/]*)/([^/]+)(/)?$ /categories/?category-type=$1&category=$2&sub-category=$3 [NC,L]
RewriteRule ^categories/([^/]*)/([^/]+)(/)?$ /categories/?category-category=$1&category-=$2 [NC,L]
RewriteRule ^categories/([^?][^/]*)(/)?$ /categories/?category-type=$1 [NC,L]
The last rule is causing a 500 Internal Server Error
. What is causing this?
Upvotes: 9
Views: 2346
Reputation: 151
I’m not sure if my method will help because your original .htaccess rules actually worked for me when I tested them, which may suggest that it may be a configuration issue. For clarity, this code you posted worked for me:
RewriteRule ^categories/([^/]*)/([^/]*)/([^/]+)(/)?$ /categories/?category-type=$1&category=$2&sub-category=$3 [NC,L]
RewriteRule ^categories/([^/]*)/([^/]+)(/)?$ /categories/?category-category=$1&category-=$2 [NC,L]
RewriteRule ^categories/([^?][^/]*)(/)?$ /categories/?category-type=$1 [NC,L]
This worked with no modifications (except for setting “RewriteEngine On”). I would suggest posting the associated Apache configuration, or at least minimally what version of Apache you’re using, an excerpt of the Apache log file, and the whole .htaccess.
The following is what I personally suggest, remove “R=301” as needed (I only used it to physically see the address change):
RewriteEngine On
RewriteBase /
# Is the request is for a file, directory, or symlink?
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
# If the request is for a file, directory, or symlink then skip the next 3 rules.
RewriteRule .? - [S=3,L]
RewriteRule ^categories/([^/]*)/([^/]*)/([^/]*)(/)?$ /categories/?category-type=$1&category=$2&sub-category=$3 [NC,R=301,L]
RewriteRule ^categories/([^/]*)/([^/]*)(/)?$ /categories/?category-type=$1&category=$2 [NC,R=301,L]
RewriteRule ^categories/([^?][^/]*)(/)?$ /categories/?category-type=$1 [NC,R=301,L]
If this does not work, have you attempted to use “END” instead of “L” flag for the rules?
RewriteRule ^categories/([^/]*)/([^/]*)/([^/]*)(/)?$ /categories/?category-type=$1&category=$2&sub-category=$3 [NC,R=301,END]
RewriteRule ^categories/([^/]*)/([^/]*)(/)?$ /categories/?category-type=$1&category=$2 [NC,R=301,END]
RewriteRule ^categories/([^?][^/]*)(/)?$ /categories/?category-type=$1 [NC,R=301,END]
Does disabling "FollowSymlinks" do anything?
Options –FollowSymlinks
In addition to all of this, it would be helpful if you responded to a number of the other possible answers. Floris pointed out one error I saw in the second rule; “category-category”, instead of “category-type”. In addition to this, there is a possible error at the end of the same part rule, as I’m assuming you intend “category=$2” and not “category-=$2”. (Both fixes I made in my suggestion)
Anubhava accurately mentioned that error logs would be extremely helpful.
Multiple people have implicitly modified (Anubhava) or explicitly suggested (Jon Lin) that you should force at least one character to be in each URI part. The only reason I did not modify this myself is because it worked out of the box for me, and I’m just going to assume when you designed it you had a logical reason to use "*" instead of "+" (despite responding to Jon Lin); that said there is an inconsistency of use in your expressions, sometimes you used "+" and other times you used "*" in places I expected consistency. I modified any "+" to "*" in my suggestion for consistency, even though I personally agree it would make more sense for them all to be consistently be "+".
Carlos raises a good point too; are you using this as an abstraction and should you re-think how your rules should be designed outright?
References:
http://httpd.apache.org/docs/current/rewrite/flags.html http://httpd.apache.org/docs/2.2/mod/core.html#options
Upvotes: 1
Reputation: 7888
Your last rewrite falls into a loop which it can't get out! what you need is change your rules in a way to avoid such a situation, like putting a condition:
RewriteRule ^categories/([^/]*)/([^/]*)/([^/]+)(/)?$ /categories/?category-type=$1&category=$2&sub-category=$3 [NC,L]
RewriteRule ^categories/([^/]*)/([^/]+)(/)?$ /categories/?category-type=$1&category-=$2 [NC,L]
RewriteCond %{QUERY_STRING} !category-type
RewriteRule ^categories/([^\/]+)/?$ /categories/?category-type=$1 [NC,L]
in this way, it won't rewrite URL if there is category-type
in query string!
Upvotes: 1
Reputation: 10947
We could be here forever triying to fix it, but as soon as you create some new url type, you will go cazy again. I use to have complex httacess in my old websites, but since a couple years ago, i dont put much logic in the httacces, an delegate all to a php router.
This is a much more flexible solution, you can create more complicated rules, it is easier to change everything, and also works perfectly if you change the server, install the app in another server or in another folder or add new routes.
This is the htacess of Zend Framework 2, that is more or less like the one i'm using:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]
All the rules means that if the request is not an actual file or directory, just send it to index.php
There, in index php you parse the actual url and fill your $_GET variables.
Upvotes: 1
Reputation: 46375
There is clearly a typo in your second rule:
RewriteRule ^categories/([^/]*)/([^/]+)(/)?$ /categories/?category-category=$1&category-=$2 [NC,L]
It should presumably be
RewriteRule ^categories/([^/]*)/([^/]+)(/)?$ /categories/?category-type=$1&category-=$2 [NC,L]
error is here ^^^^
I am wondering whether you end up with a malformed request - in other words, it's not that your expression is wrong, but that your resulting request is not accepted by the server. What happens if you turn off the rewriting and type your actual requests directly into the browser?
Upvotes: 0
Reputation: 785246
Your regex in last rules appears to be faulty. Try these rules in your DOCUMENT_ROOT/.htaccess
file:
RewriteEngine On
RewriteRule ^categories/([^/]+)/([^/]+)/([^/]+)/?$ /categories/?category-type=$1&category=$2&sub-category=$3 [NC,QSA,L]
RewriteRule ^categories/([^/]+)/([^/]+)/?$ /categories/?category-type=$1&category=$2 [NC,QSA,L]
RewriteRule ^categories/([^/]+)/?$ /categories/?category-type=$1 [NC,QSA,L]
Upvotes: 1
Reputation: 143906
The last rule is causing a 500 Internal Server Error. What is causing this?
It's a loop. Your rule's target, /categories/
matches the pattern ^categories/([^?][^/]*)(/)?$
, since all that stuff after the /
is optional. Try making the *
a +
to force at least 1 character there:
RewriteRule ^categories/([^?][^/]+)(/)?$ /categories/?category-type=$1 [NC,L]
Upvotes: 4