If have the following possible urls:
如果有以下可能的url:
http://*.com/categories/
http://*.com/categories/category-type
http://*.com/categories/category-type/category
http://*.com/categories/category-type/category/sub-category
which I want to rewrite to
我想把它改写成
http://*.com/categories/
http://*.com/categories/?category-type=category-type
http://*.com/categories/?category-type=category-type&category=category
http://*.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?
最后一条规则导致500个内部服务器错误。是什么原因导致了晒伤的?
6 个解决方案
#1
1
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.
我们可以一直在这里尝试修复它,但是一旦你创建了新的url类型,你就会再次回到cazy。我以前的网站上有复杂的httacess,但是自从几年前以来,我没有在httacces中放入太多的逻辑,httacces是php路由器的一个委托。
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:
这是Zend Framework 2的htacess,与我正在使用的这个差不多:
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
所有规则都意味着,如果请求不是实际的文件或目录,只需将其发送到index.php
There, in index php you parse the actual url and fill your $_GET variables.
在索引php中,解析实际的url并填充$_GET变量。
#2
4
The last rule is causing a 500 Internal Server Error. What is causing this?
最后一条规则导致500个内部服务器错误。是什么原因导致了晒伤的?
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:
这是一个循环。您的规则的目标,/类别/匹配模式^类别/((^ ?)[^ /]*)(/)?$,因为/之后的所有东西都是可选的。试着让* a +至少在那里强制一个字符:
RewriteRule ^categories/([^?][^/]+)(/)?$ /categories/?category-type=$1 [NC,L]
#3
1
Your regex in last rules appears to be faulty. Try these rules in your DOCUMENT_ROOT/.htaccess
file:
您的regex在最后的规则中似乎是错误的。在DOCUMENT_ROOT/中尝试这些规则。htaccess:
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]
#4
1
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!
这样,如果查询字符串中有类别类型,它就不会重写URL !
#5
0
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?
我想知道您是否最终得到了一个畸形的请求——换句话说,不是您的表达式是错误的,而是您的结果请求没有被服务器接受。如果关闭重写并将实际请求直接输入浏览器,会发生什么情况?
#6
0
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:
我不确定我的方法是否会有帮助,因为您的原始的.htaccess规则在我测试它们时实际上对我有效,这可能意味着它可能是一个配置问题。为了清晰起见,你发布的代码对我起了作用:
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.
此操作无需修改(除了设置“RewriteEngine On”)。我建议发布相关的Apache配置,或者至少是您正在使用的Apache版本,Apache日志文件的摘录,以及整个.htaccess。
The following is what I personally suggest, remove “R=301” as needed (I only used it to physically see the address change):
以下是我个人的建议,根据需要删除“R=301”(我只是用它来查看地址变化):
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?
如果这不起作用,您是否尝试使用“END”而不是“L”标志来执行规则?
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?
禁用“FollowSymlinks”有什么作用吗?
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)
除此之外,如果你能回答一些其他可能的答案,那将会很有帮助。Floris指出了我在第二条规则中看到的一个错误;“category-category”,而不是“类别”。除此之外,在相同的部分规则的末尾有一个可能的错误,因为我假定您打算“category=$2”而不是“category-=$2”。(我在我的建议中提出的两个修正)
Anubhava accurately mentioned that error logs would be extremely helpful.
Anubhava准确地提到错误日志将非常有用。
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 "+".
许多人已经隐式地修改(Anubhava)或显式地建议(Jon Lin),您应该在每个URI部分中强制至少一个字符。我自己没有修改它的唯一原因是因为它非常适合我,我假设当你设计它的时候你有一个合理的理由使用“*”而不是“+”(尽管有Jon Lin的回应);也就是说,在你的表达式中有一个不一致的用法,有时你用“+”,有时你用“*”在我期望的地方。我在我的建议中修改了任何“+”到“*”,以保持一致性,尽管我个人认为,一致地使用“+”更有意义。
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
http://httpd.apache.org/docs/current/rewrite/flags.html http://httpd.apache.org/docs/2.2/mod/core.html选项
#1
1
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.
我们可以一直在这里尝试修复它,但是一旦你创建了新的url类型,你就会再次回到cazy。我以前的网站上有复杂的httacess,但是自从几年前以来,我没有在httacces中放入太多的逻辑,httacces是php路由器的一个委托。
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:
这是Zend Framework 2的htacess,与我正在使用的这个差不多:
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
所有规则都意味着,如果请求不是实际的文件或目录,只需将其发送到index.php
There, in index php you parse the actual url and fill your $_GET variables.
在索引php中,解析实际的url并填充$_GET变量。
#2
4
The last rule is causing a 500 Internal Server Error. What is causing this?
最后一条规则导致500个内部服务器错误。是什么原因导致了晒伤的?
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:
这是一个循环。您的规则的目标,/类别/匹配模式^类别/((^ ?)[^ /]*)(/)?$,因为/之后的所有东西都是可选的。试着让* a +至少在那里强制一个字符:
RewriteRule ^categories/([^?][^/]+)(/)?$ /categories/?category-type=$1 [NC,L]
#3
1
Your regex in last rules appears to be faulty. Try these rules in your DOCUMENT_ROOT/.htaccess
file:
您的regex在最后的规则中似乎是错误的。在DOCUMENT_ROOT/中尝试这些规则。htaccess:
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]
#4
1
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!
这样,如果查询字符串中有类别类型,它就不会重写URL !
#5
0
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?
我想知道您是否最终得到了一个畸形的请求——换句话说,不是您的表达式是错误的,而是您的结果请求没有被服务器接受。如果关闭重写并将实际请求直接输入浏览器,会发生什么情况?
#6
0
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:
我不确定我的方法是否会有帮助,因为您的原始的.htaccess规则在我测试它们时实际上对我有效,这可能意味着它可能是一个配置问题。为了清晰起见,你发布的代码对我起了作用:
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.
此操作无需修改(除了设置“RewriteEngine On”)。我建议发布相关的Apache配置,或者至少是您正在使用的Apache版本,Apache日志文件的摘录,以及整个.htaccess。
The following is what I personally suggest, remove “R=301” as needed (I only used it to physically see the address change):
以下是我个人的建议,根据需要删除“R=301”(我只是用它来查看地址变化):
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?
如果这不起作用,您是否尝试使用“END”而不是“L”标志来执行规则?
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?
禁用“FollowSymlinks”有什么作用吗?
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)
除此之外,如果你能回答一些其他可能的答案,那将会很有帮助。Floris指出了我在第二条规则中看到的一个错误;“category-category”,而不是“类别”。除此之外,在相同的部分规则的末尾有一个可能的错误,因为我假定您打算“category=$2”而不是“category-=$2”。(我在我的建议中提出的两个修正)
Anubhava accurately mentioned that error logs would be extremely helpful.
Anubhava准确地提到错误日志将非常有用。
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 "+".
许多人已经隐式地修改(Anubhava)或显式地建议(Jon Lin),您应该在每个URI部分中强制至少一个字符。我自己没有修改它的唯一原因是因为它非常适合我,我假设当你设计它的时候你有一个合理的理由使用“*”而不是“+”(尽管有Jon Lin的回应);也就是说,在你的表达式中有一个不一致的用法,有时你用“+”,有时你用“*”在我期望的地方。我在我的建议中修改了任何“+”到“*”,以保持一致性,尽管我个人认为,一致地使用“+”更有意义。
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
http://httpd.apache.org/docs/current/rewrite/flags.html http://httpd.apache.org/docs/2.2/mod/core.html选项