我在兩個階段做了這個。首先是一組提取一個參數的規則,其他參數保持不變。然後我將其擴展爲兩個參數。規則本身並不那麼糟糕。這只是棘手的計算出來。
單參數
這使用該示例的a
參數。有4個條件:
因爲問號與符號的,這是最簡單的做單獨的規則。原來,最後兩個很容易合併爲一個規則。(注意:我使用Helicon Ape重寫,它通常與Apache兼容,我有一個問題,RewriteRule問號需要在參數之前轉義,例如,\?%2
。我不知道這是真的嗎?一般。)
# a
# ?a=foo
# Starts with a=, non-ampersand to the end.
# Suppress querystring with trailing question mark.
RewriteCond ${QUERY_STRING} ^a=([^&]+)$
RewriteRule ^/path/$ /path/%1/? [NC,R=301,L]
# a-other
# ?a=foo&b=bar, ?a=foo&b=bar&c=1
# Starts with a=, non-ampersand, ampersand, remaining required.
# Escape question mark so it doesn't include entire original querystring.
RewriteCond ${QUERY_STRING} ^a=([^&]+)&(.+)
RewriteRule ^/path/$ /path/%1/\?%2 [NC,R=301,L]
# other-a or other-a-other
# ?b=baz&a=qux, ?b=baz&c=1&a=qux
# ?c=1&a=foo&d=2&b=bar&e=3, ?z=4&c=1&a=foo&d=2&b=bar&e=3
# Starts with anything, ampersand, a=, non-ampersand, remaining optional.
# The remaining optional lets it follow with nothing, or with ampersand and more parameters.
# Escape question mark so it doesn't include entire original querystring.
RewriteCond ${QUERY_STRING} ^(.+)&a=([^&]+)(.*)$
RewriteRule ^/path/$ /path/$2/\?%1%3 [NC,R=301,L]
兩個參數
爲了把這些結合在一起爲這兩個參數是有點棘手,但這個想法是重寫a
,則f全部重寫b
並重定向。要一起管理這兩個部分,請將path
重寫爲temppath
,然後temppath2
,然後在完成時將其重寫回path
。這確保這些僅在a
和b
存在時才運行。如果只有一個或另一個存在,則它跳過所有這些。 (如果你的意思是也只處理一個,這可以調整。)
# Test cases:
# 1) /path/?a=foo&b=bar to /path/foo/bar
# 2) /path/?a=foo&b=bar&c=1 to /path/foo/bar?c=1
# 3) /path/?a=foo&b=bar&c=1&d=2 to /path/foo/bar?c=1&d=2
# 4) /path/?b=baz&a=qux to /path/qux/baz
# 5) /path/?b=baz&c=1&a=qux to /path/qux/baz/?c=1
# 6) /path/?c=1&b=baz&a=qux to /path/qux/baz/?c=1
# 7) /path/?c=1&d=2&b=baz&a=qux to path/qux/baz/?c=1&d=2
# 8) /path/?c=1&a=foo&d=2&b=bar&e=3 to /path/foo/bar/?c=1&d=2&e=3
# 9) /path/?z=4&c=1&a=foo&d=2&b=bar&e=3 to /path/foo/bar/?z=4&c=1&d=2&e=3
# Check for a and b (or b and a), rewrite to temp path and continue.
RewriteCond ${QUERY_STRING} (?:^|&)(?:a|b)=.+&(?:b|a)=.+$
RewriteRule ^/path/$ /temppath/ [NC]
# a
# ?a=foo
# This case isn't needed, since we test for a and b above.
# a-other
# 1) /temppath/?a=foo&b=bar to /temppath2/foo/?b=bar
# 2) /temppath/?a=foo&b=bar&c=1 to /temppath2/foo/?b=bar&c=1
# 3) /temppath/?a=foo&b=bar&c=1&d=2 to /temppath2/foo/?b=bar&c=1&d=2
# Starts with a=, non-ampersand, ampersand, remaining required.
RewriteCond ${QUERY_STRING} ^a=([^&]+)&(.+)$
RewriteRule ^/temppath/$ /temppath2/%1/\?%2 [NC]
# other-a or other-a-other
# 4) /temppath/?b=baz&a=qux to /temppath2/qux/?b=baz
# 5) /temppath/?b=baz&c=1&a=qux to /temppath2/qux/?b=baz&c=1
# 6) /temppath/?c=1&b=baz&a=qux to /temppath2/qux/?c=1&b=baz
# 7) /temppath/?c=1&d=2&b=baz&a=qux to /temppath2/qux/?c=1&d=2&b=baz
# 8) /temppath/?c=1&a=foo&d=2&b=bar&e=3 to /temppath2/foo/?c=1&d=2&b=bar&e=3
# 9) /temppath/?z=4&c=1&a=foo&d=2&b=bar&e=3 to /temppath2/foo/?z=4&c=1&d=2&b=bar&e=3
# Starts with anything, ampersand, a=, non-ampersand, remaining optional.
# The remaining optional lets it follow with nothing, or with ampersand and more parameters.
# Escape question mark so it doesn't include entire original querystring.
RewriteCond ${QUERY_STRING} ^(.+)&a=([^&]+)(.*)$
RewriteRule ^/temppath/$ /temppath2/%2/\?%1%3 [NC]
# b
# 1) /temppath2/foo/?b=bar to /path/foo/bar
# 4) /temppath2/qux/?b=baz to /path/qux/baz
# Starts with b=, non-ampersand to the end.
# Capture and use path after temppath2, since it has the a folder from above.
RewriteCond ${QUERY_STRING} ^b=([^&]+)$
RewriteRule ^/temppath2/(.*)/$ /path/$1/%1/? [NC,R=301,L]
# b-other
# 2) /temppath2/foo/?b=bar&c=1 to /path/foo/bar?c=1
# 3) /temppath2/foo/?b=bar&c=1&d=2 to /path/foo/bar?c=1&d=2
# 5) /temppath2/qux/?b=baz&c=1 to /path/qux/baz/?c=1
# Starts with b=, non-ampersand, ampersand, remaining required.
# Capture and use path after temppath2, since it has the a folder from above.
# Escape question mark so it doesn't include entire original querystring.
RewriteCond ${QUERY_STRING} ^b=([^&]+)&(.+)$
RewriteRule ^/temppath2/(.*)/$ /path/$1/%1/\?%2 [NC,R=301,L]
# other-b or other-b-other
# 6) /temppath2/qux/?c=1&b=baz to /path/qux/baz/?c=1
# 7) /temppath2/qux/?c=1&d=2&b=baz to /path/qux/baz/?c=1&d=2
# 8) /temppath2/foo/?c=1&d=2&b=bar&e=3 to /path/foo/bar/?c=1&d=2&e=3
# 9) /temppath2/foo/?z=4&c=1&d=2&b=bar&e=3 to /path/foo/bar/?z=4&c=1&d=2&e=3
# Starts with anything, ampersand, b=, non-ampersand, remaining optional.
# The remaining optional lets it follow with nothing, or with ampersand and more parameters.
# Capture and use path after temppath2, since it has the a folder from above.
# Escape question mark so it doesn't include entire original querystring.
RewriteCond ${QUERY_STRING} ^(.+)&b=([^&]+)(.*)$
RewriteRule ^/temppath2/(.*)/$ /path/$1/%2/\?%1%3 [NC,R=301,L]
這可能是代碼更容易....
作爲珍聞,檢查參數可以簡化很少,因爲'(?:^ |&)a =([^&] +)',在那裏你的非捕獲開始或&符號仍然引導開始(避免xa = 123) &符號(將在下一個&符號處停止,如果沒有,則運行到結尾)。 – goodeye
我認爲單獨的規則是要走的路,但其中有很多。我可以稍後做一個具體的答案,但是這個想法是:ab,ba,abe,cab,cadb,cabe,cadbe。可選捕獲的問題是最終會遇到一個難以處理的「額外」&符號,因此特定的排列更容易(只是其中很多)。問題:是否總是有'a'和'b'參數(按任意順序),還是可能有一個或另一個? – goodeye
我想我有一個解決方案。在Global.asax的Application_BeginRequest()中(在.htaccess規則之前運行),我會檢查各種動態頁面的查詢字符串變量的順序是否正確,然後讓.htaccess使用一個規則進行處理。 –