Reguła przepisywania z QUERY_STRING nie działa

Oct 22 2020

Na serwerze Apache muszę przepisać mojadomena.com/something/?p=value na mydomain.com/something/?page=value

Próbowałem:

RewriteEngine On
RewriteCond %{QUERY_STRING} p=(.*)
RewriteRule ^(.*)/p=$ $1?page=%{QUERY_STRING} [L,QSA]

ale nie pracuj, czy możesz mi pomóc?

Odpowiedzi

1 MrWhite Oct 22 2020 at 14:13
RewriteCond %{QUERY_STRING} p=(.*)
RewriteRule ^(.*)/p=$ $1?page=%{QUERY_STRING} [L,QSA]

Występuje tu wiele „błędów”:

  • RewriteRule Wzorzec , tj. ^(.*)/p=$, nigdy nie będzie pasować, ponieważ p=nie występuje jako część ścieżki adresu URL (jest częścią ciągu zapytania). Na RewriteRule wzór mecze przeciwko jedynej ścieżka_url, która szczególnie wyklucza ciąg kwerendy. Tak więc powyższe nic nie zrobi dla podanego przykładowego adresu URL.

  • Używasz QUERY_STRINGzmiennej serwera zamiast wymaganego parametru adresu URL valuew ciągu zastępczym . Ale QUERY_STRINGto oczywiście cała „string query”, tak by skończyć budowy nieprawidłowy ciąg kwerendy w postaci: page=p=<value>.

  • Użycie tej QSAflagi powoduje, że oryginalny ciąg zapytania w żądaniu jest scalany z ciągiem zapytania używanym w ciągu zastępczym . Tak więc spowoduje &p=<value>to dołączenie, co nie jest tym, czego wymagałeś. Chcesz zastąpić istniejący ciąg zapytania.

  • RewriteRule ^(.*)/p=$ $1?page=- Wykluczasz końcowy ukośnik z grupy przechwytywania we RewriteRule wzorcu , więc skutecznie usunie to końcowy ukośnik z przepisanego adresu URL. To jest inne niż twój przykład.

  • Wygląda na to, że wymaga wewnętrznego przepisania (bez zewnętrznego przekierowania ) i zmieniasz „tylko” nazwę pojedynczego parametru adresu URL. Jest to coś, co zwykle można rozwiązać w swojej aplikacji, zamiast przepisywania adresu URL w Apache. (?)

Zamiast tego spróbuj wykonać następujące czynności:

RewriteEngine On

# Internally "rewrite" the request
RewriteCond %{QUERY_STRING} ^p=([^&]*)$
RewriteRule (.*/)$ $1?page=%1 [L]

To pasuje do każdej ścieżki URL, która kończy się ukośnikiem (jak na przykładzie). %1Wsteczne odnosi się do grupy przechwycone w ostatnim dopasowane CondPattern , tj. wartość pparametru adresu URL. Zakłada się, że p=<value>jest to jedyny parametr adresu URL w żądaniu.


AKTUALIZACJA: wydaje się nie działać ... jeśli zadzwonię, localhost/list/?p=2po prostu dostajęlocalhost/list/?p=2

Tak, widoczny adres URL się nie zmienia, ponieważ jest to wewnętrzne „przepisanie” (o co prosisz w swoim pytaniu). Adres URL jest wewnętrznie przepisywany na list/?page=2. (Jest też punkt, który list/?page=2nie jest ściśle poprawnym punktem końcowym - wymaga dalszego przepisania, być może przez mod_dir, aby utworzyć prawidłowe żądanie. Np. list/index.php?page=2?)

Jeśli chcesz, aby adres URL wyraźnie się zmienił, może w końcu potrzebujesz zewnętrznego „przekierowania”? W tym celu musisz dołączyć prefiks ukośnika do ciągu RewriteRule podstawiania i dodać flagę R( redirect). Na przykład:

# Externally "redirect" the request
RewriteCond %{QUERY_STRING} ^p=([^&]*)$ RewriteRule (.*/)$ /$1?page=%1 [R=302,L]

jeśli zmodyfikuję regułę, aby uzyskać localhost/list/?p=2&?p=2jak poniżej:

RewriteEngine On
RewriteCond %{QUERY_STRING} ^p=([^&]*)$
RewriteRule (.*/)$ $1&?page=%1 [L]

Otrzymuję komunikat „Żądany adres URL /list/&nie został znaleziony na tym serwerze”. tak jak '?' przerwać przepisywanie

Jeśli zażądasz localhost/list/?p=2&?p=2(ale dlaczego?), Powyższe dyrektywy w ogóle nic nie zrobią, ponieważ warunek nie będzie zgodny.

Dlaczego dodałeś a &w ciągu RewriteRule zastępczym ? (To nie ma sensu?) To faktycznie skutkowałoby ścieżką adresu URL do formularza /list/&, gdyby reguła została przetworzona. Ale jak wspomniano, nie zostanie przetworzony dla podanego adresu URL?