2013-05-20 20 views
3

我想建立一個ISAPI_Rewrite 3 "RewriteRule「處理以下永久重定向:刪除特定的查詢字符串鍵/值對(但讓別人完好無損)

╔════════════════════════════════╦════════════════════════════╗ 
║    Input    ║   Redirect   ║ 
╠════════════════════════════════╬════════════════════════════╣ 
║ /path/?a=foo&b=bar    ║ /path/foo/bar/    ║ 
║ /path/?b=baz&a=qux    ║ /path/qux/baz/    ║ 
║ /path/?c=1&a=foo&d=2&b=bar&e=3 ║ /path/foo/bar/?c=1&d=2&e=3 ║ 
╚════════════════════════════════╩════════════════════════════╝ 

例如,

RewriteCond ${QUERY_STRING} (?:^|&)a=([\w]+)(?:&|$) 
RewriteCond ${QUERY_STRING} (?:^|&)b=([\w]+)(?:&|$) 
RewriteRule ^/path/$ /path/%1/%2/? [R=301] 

將工作,除了它將剝離所有的查詢字符串對(失敗的第三個例子)。我似乎無法找出一個優雅的解決方案,從URL中只剝離已知的鍵/值對。 ...

RewriteCond ${QUERY_STRING} ^(.*)&?a=([\w]+)(.*)&?b=([\w]+)(.*)$ 
RewriteRule ^/path/$ /path/%2/%4/?%1%3%5 [R=301] 

是不完全正確的(但你應該得到什麼樣的例子試圖做),並得到真正的凌亂匆忙。

任何想法?

澄清:我的第三個例子,對於/path/?c=1&a=foo&d=2&b=bar&e=3請求應該重定向到/path/foo/bar/?c=1&d=2&e=3和NOT /path/foo/bar/1/2/3/。 I 可能不知道要使用請求哪些查詢字符串對,並且可能需要其中一些查詢字符串留在用於客戶端處理的查詢字符串中。一些示例未知的查詢字符串鍵是;

  • gclid」 - 使用谷歌Analytics(分析)客戶端腳本中的AdWords數據,以配合
  • utm_source」 - 用來明確地告訴GA的流量來源/類型
+1

作爲珍聞,檢查參數可以簡化很少,因爲'(?:^ |&)a =([^&] +)',在那裏你的非捕獲開始或&符號仍然引導開始(避免xa = 123) &符號(將在下一個&符號處停止,如果沒有,則運行到結尾)。 – goodeye

+0

我認爲單獨的規則是要走的路,但其中有很多。我可以稍後做一個具體的答案,但是這個想法是:ab,ba,abe,cab,cadb,cabe,cadbe。可選捕獲的問題是最終會遇到一個難以處理的「額外」&符號,因此特定的排列更容易(只是其中很多)。問題:是否總是有'a'和'b'參數(按任意順序),還是可能有一個或另一個? – goodeye

+0

我想我有一個解決方案。在Global.asax的Application_BeginRequest()中(在.htaccess規則之前運行),我會檢查各種動態頁面的查詢字符串變量的順序是否正確,然後讓.htaccess使用一個規則進行處理。 –

回答

0

這是一個有趣一!我的經驗表明,有一個簡單的條件比一個繁瑣的規則更好。它通常更有效和高效。

我的建議:

# a-b pair 
RewriteCond %{QUERY_STRING} a=([^&]+) 
RewriteCond %{QUERY_STRING} b=([^&]+) 
RewriteRule ^/path/$ /path/%1/%2/? [NC,R=301,L] 

# a-b-c pair 
RewriteCond %{QUERY_STRING} a=([^&]+) 
RewriteCond %{QUERY_STRING} b=([^&]+) 
RewriteCond %{QUERY_STRING} c=([^&]+) 
RewriteRule ^/path/$ /path/%1/%2/%3/? [NC,R=301,L] 

這可能不是你想要的優雅,但它仍然應該做的伎倆。 我也可以想出一些辦法

+0

拆分成單獨的規則是完全沒有問題的。但是,我從來沒有試圖在您的a-b-c對示例中重定向到/ path /%1 /%2 /%3 /。如果你包含「c」,我想直接改爲/ path /%1 /%2 /?c = value。問題是,「c」的值需要在查詢字符串中爲客戶端解析...可以是任意數量的鍵,如:「gclid」(谷歌用於將Adwords信息傳遞給客戶端分析腳本)或「utm_medium」(谷歌分析客戶端腳本也用於處理媒體) –

+0

我會更新我的問題來澄清。 –

+0

好像你的代碼不起作用。 %1將表示第一個示例中的b變量的值,以及第二個示例中的c變量的值。 –

2

我在兩個階段做了這個。首先是一組提取一個參數的規則,其他參數保持不變。然後我將其擴展爲兩個參數。規則本身並不那麼糟糕。這只是棘手的計算出來。

單參數

這使用該示例的a參數。有4個條件:

  • A-其他
  • 其他-A
  • 其他-A-其他

因爲問號與符號的,這是最簡單的做單獨的規則。原來,最後兩個很容易合併爲一個規則。(注意:我使用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。這確保這些僅在ab存在時才運行。如果只有一個或另一個存在,則它跳過所有這些。 (如果你的意思是也只處理一個,這可以調整。)

# 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] 


這可能是代碼更容易....

相關問題