问题
I've been stuck the last few days trying to convert the following Apache/Mod_Rewrite rewrite rule to NGINX format. Anyone know where I am going wrong?
MOD_REWRITE:
RewriteCond %{QUERY_STRING} topic=([0-9]+)
RewriteRule /forum/index\.php /forum/vbseo301.php?action=thread&oldid=%1 [L]
NGINX:
location /forum/index.php {
if ($args ~ "topic=([0-9]+)"){
rewrite ^/forum/index\.php?topic=(.+)$ /forum/vbseo301.php?action=thread&oldid=$1 last;
}
}
回答1:
This does not answer the question -- please read the comment with more information I am leaving this answer to host other variants of rewriting viable for other situations.
You can do it easier:
# At "server" level, NOT in "location"
rewrite ^/forum/index.php
/forum/vbseo301.php?action=thread&oldid=$arg_topic?
last;
The ? suffix tells Nginx to not append original arguments to the new URL.
Sidenote
By the way, if you are doing static mapping of one set of IDs to another, there is a more effective solution:
http {
map $arg_topic $new_topic_id {
default 1;
2 3;
4 65;
}
server {
# some directives (server_name, listen, etc.) omitted
rewrite ^/forum/index.php /forum/new.php?topic=$new_topic_id? last;
# locations omitted
}
}
map
takes the first parameter (topic
from query string in this case) and does a lookup through the table. It then assigns the result to the second parameter (new_topic_id
). Two benefits:
- The lookup is very effective, as Nginx creates a hash table.
- The lookup occurs only when you are going to use
new_topic_id
(lazy evaluation)
回答2:
From the details you provided I agree the only way is to use if
(despite the fact if
is not recommended generally). Try this:
location /forum/index.php {
if ($arg_topic != "") {
rewrite ^ /forum/vbseo301.php?action=thread&oldid=$arg_topic? break;
}
}
I shall leave my previous answer as it might be of help for someone else.
Simpler example to make sure this works
I've put a simpler example to show this works. Here it is the Nginx configuration fragment:
location /index.html {
if ($arg_topic != '') {
rewrite ^ /vv.html?t=$arg_topic? break;
}
ssi on;
root /home/alaz;
}
location /vv.html {
ssi on;
root /home/alaz;
}
index.html
contents:
<b>index</b>
<br/>
topic: <!--#echo var="arg_topic" -->
vv.html
contents:
<b>vv</b>
<br/>
topic: <!--#echo var="arg_topic" -->
<br/>
t: <!--#echo var="arg_t" -->
Now reload Nginx and point your browser to http://hostname/index.html at the first and http://hostname/index.html?topic=11 after that.
回答3:
Seems lots of people are still viewing this question. Hope my answer helps!
location /forum/index.php {
if ($args ~ "topic=([0-9]+)"){
rewrite ^/forum/index\.php$ /forum/vbseo301.php?action=thread&oldid=$arg_topic? last;
}
}
Tested and it works. A couple of critical but subtle fixes in the rewrite line:
- I removed the query string part "?topic=(.+)" from the old url because nginx rewrite rule doesn't match query strings at all(also called args in nginx). It only tries to match PATH. reference link
- The argument topic=xxxx is automatically stored in nginx in this variable: $arg_topic. So I can simply put "oldid=$arg_topic" in the new url. reference link
- I put a question mark "?" at the end of the new url so that nginx won't try to attach the query string from the old url. By default, nginx will attach the entire query string from the old url.
来源:https://stackoverflow.com/questions/2442374/converting-mod-rewrite-rules-which-use-query-string-to-nginx-rewrite-format