2013-07-22 10 views
10

Gdy mam wiele połączonych Łańcuch Rewrite, tylko grupy przechwytujące ostatniego RewriteCond mogą być przywoływane z %0 - %9.Odwołanie grup przechwytywania wielokrotnego RewriteCond w RewriteRule

W poniższym problemie parametry w ciągu zapytania adresu URL mogą być w dowolnej kolejności. Analizować je w fantazyjne url byłyby potrzebne, aby dopasować każdy parametr w ciągu zapytania indywidualnie:

RewriteCond %{QUERY_STRING} param1=([^&]+) 
RewriteCond %{QUERY_STRING} param2=([^&]+) 
RewriteCond %{QUERY_STRING} param3=([^&]+) 
RewriteRule ^foo$ bar/%1/%2/%3/ [R] 

Jak podkreśliłem ... to nie działa. Aby rozwiązać ten problem, mogę odwołać się do grupy przechwytywania poprzedniej RewriteCond w następnym RewriteCond i „propagować” każdy parametr do rzeczywistej RewriteRule:

RewriteCond %{QUERY_STRING} param1=([^&]+) 
RewriteCond %1&%{QUERY_STRING} ^([^&]*)&.*param2=([^&]+) 
RewriteCond %1&%2&%{QUERY_STRING} ^([^&]*)&([^&]*)&.*param3=([^&]+) 
RewriteRule ^foo$ bar/%1/%2/%3/ [R] 

To powinno działać, ale dla każdego dodatkowego parametru to get Messier. Innym rozwiązaniem może być parsowanie jednego parametru i przekierowanie klienta po każdym parametrze (co spowoduje długi łańcuch przekierowań, których chciałbym uniknąć).

Czy istnieje przejrzysty sposób uzyskiwania dostępu do grupy przechwytywania wszystkich RewriteCond jest w RewriteRule (np jest to możliwe, aby je wymienić lub przypisać je do zmiennej, więc mogę odwołać je gdzieś indziej?)

+2

+1 za wielkie pytanie. Stawiłem też czoła temu problemowi i chciałbym znać odpowiedź: – anubhava

+0

Dokumenty mod_rewrite mówią, że backreferences RewriteCond zachowują ** ostatnio dopasowany RewriteCond ** w bieżącym zestawie warunków, więc tak, twoja druga odpowiedź może być tylko odpowiedź na tej trasie. Biorąc pod uwagę jego złożoność, czy zastanawiałeś się nad ustawieniem skryptu w 'foo', który analizuje GET) lub POST) i przekierowuje do odpowiedniego' paska'? – miah

Odpowiedz

10

można spróbować konstruowania docelowy adres URL wewnątrz warunkach przepisywania:

RewriteCond ##%{QUERY_STRING}  (.*)##(|.*&)param1=([^&]+) 
RewriteCond %1/%3##%{QUERY_STRING} (.*)##(|.*&)param2=([^&]+) 
RewriteCond %1/%3##%{QUERY_STRING} (.*)##(|.*&)param3=([^&]+) 
RewriteCond %1/%3##%{QUERY_STRING} (.*)##(|.*&)param4=([^&]+) 
RewriteCond %1/%3##%{QUERY_STRING} (.*)##(|.*&)param5=([^&]+) 
RewriteCond %1/%3##%{QUERY_STRING} (.*)##(|.*&)param6=([^&]+) 

RewriteRule ^foo$ /bar%1/%3? [L,R] 

Kiedy próbuję żądanie:

/foo?param1=a&param2=b&param6=3&param3=4&param5=5&param4=6

dostaję przekierowany do:

/bar/a/b/4/6/5/3

dodawania jakichkolwiek dodatkowych wymaganych parametrów ciągów zapytanie nie będzie to wyglądać bardziej brudny niż jest obecnie.

+0

Do czego służy '## '? –

+0

@RahilWazir jest używany tylko jako ogranicznik do dopasowania, wiemy, że nie możemy mieć '#' w uri, więc jest bezpieczny w użyciu –

+0

Więc to było konieczne? Chodzi mi o to, że bez ograniczników nie zadziała (nadal nie rozumiem)? –

1

Po przeprowadzeniu kolejnych eksperymentów możliwe byłoby przeanalizowanie wszystkich parametrów jako zmiennych środowiskowych i użycie ich w ten sposób. Wątpię, czy jest to bardzo wydajne i myślę, że jakikolwiek przypadek użycia, który wymagałby takiej konstrukcji, lepiej byłoby użyć routera strony php. Dla wymyślnego url'a rozwiązanie Jona Lin będzie prawdopodobnie działało lepiej. To jednak w pewnym sensie naśladuje to, co miałem na myśli.

będę jednak umieścić kod tutaj do demonstracji:

#Parse all query key-value pairs to an environment variable with the q- prefix 
RewriteCond %{QUERY_STRING} ^([^=]*)=([^&]*)(&(.*)|$)$ 
RewriteRule ^(.*)$ $1?%4 [E=q-%1:%2,N] 

#If 'param1' existed in the query string... 
RewriteCond %{ENV:q-param1} !^$ 
RewriteRule ^foo$ bar/%{ENV:q-param1} [END] 

lub nawet ...

#Keep the original query string 
RewriteCond %{ENV:qstring} ^$ 
RewriteCond %{QUERY_STRING} ^(.*)$ 
RewriteRule .* - [E=qstring:#%1] 

#parse the query parameters to environment variables 
RewriteCond %{ENV:qstring} ^#([^=]*)=([^&]*)(&(.*)|$)$ 
RewriteRule ^(.*)$ - [E=q-%1:%2,E=qstring:#%4,N] 

#See that the original query string is still intact 
RewriteCond %{ENV:q-param1} !^$ 
RewriteRule ^foo$ bar/%{ENV:q-param1} [QSA] 
Powiązane problemy