MOD_REWRITE Правило для обеспечения обеспечения канонического кодирования процентов

StackOverflow https://stackoverflow.com/questions/3791548

Вопрос

У нас есть приложение PHP с динамической схемой URL, которая требует, чтобы персонажи были в процентах кодированы, даже «безразрешенные персонажи«Подобные скобкам или афострофам, которые на самом деле не требуются для кодировки. URL-адреса, которые приложение считается кодированным« неправильным »способом, канонизированы, а затем перенаправлены на« правильное »кодирование.

Но Google и другие пользовательские агенты будут по-разному каницировать процентные кодировки / декодирования, что означает, когда GoogleBot запрашивает страницу, которую она попросит «неправильный» URL, и когда он вернет перенаправление на «правильный» URL, GoogleBot откажется перенаправить и отказывается индексировать страницу.

Да, это ошибка на нашем конце. Спецификации HTTP требуют, чтобы серверы обрабатывали процентами и нецентризованными символами, закодированными без процента. Но исправление проблемы в коде приложения не просто прямого, поэтому я надеялся избежать изменения кода, используя правило перезаписи Apache, которое бы убедиться, что URL-адреса кодируются «правильно» из точки зрения приложения. , что означает, что апопстрофы, скобки и т. Д. - все проценты, и что пробелы кодируются как + и не %20.

Вот один из примеров, где я хочу переписать первый и в конечном итоге со второй формой:

  • www.splunkbase.com/apps/all/4.x/addoon/app:opceCHeLea+For+Check+Point+(Linux)
  • www.splunkbase.com/apps/all/4.x/addoon/app:opsec+Point+For+Check+Point+%28Linux%29.

Вот еще один:

  • www.splunkbase.com/apps/all/4.x/app:benford's+lawe+fraud+detection+дd-on.
  • www.splunkbase.com/apps/all/4.x/app:benford%27s+law+fraud+detection+ddoon.

Вот еще один:

  • www.splunkbase.com/apps/all/4.x/app:benford%27s%20Law%20Fraud%20Detection%20Addoon.
  • www.splunkbase.com/apps/all/4.x/app:benford%27s+law+fraud+detection+ddoon.

Если приложение видит только вторую форму этих URL, то она не будет отправлять никаких перенаправлений, и Google сможет индексировать страницу.

Я новичок с переписанными правилами, и это было ясно из моего читания Документация Mod-Rewrite Что MOD_REWRITE делает некоторую автоматическую кодировку / декодирование, которое может помочь или обидеть то, что я хочу сделать, хотя не уверен.

Любые советы по переписанию правил для обработки вышеупомянутых случаев? Я в порядке с правилом для каждого специального персонажа, поскольку их не так много, но одно правило (если возможно) будет идеальным.

Это было полезно?

Решение

Решение на самом деле может быть довольно простым, хотя он будет работать только в Apache 2.2, а затем из-за использования B флаг. Отказ Я не уверен, позаботится или нет правильно, позаботится о каждом корпусе (по общему признанию, я немного скептичен, это не приводит к большей работе, чем это), но я привел к веществу, чтобы он должен был исходным кодом.

Имейте в виду, что ценность REQUEST_URI Не обновляется трансформациями MOD_REWRITE, поэтому, если ваше приложение опирается на это значение, чтобы определить запрошенный URL, изменения, которые вы делаете, все равно не будут видны.

Хорошая новость заключается в том, что это можно сделать в .htaccess, поэтому у вас есть возможность выйти из основной конфигурации нетронутой, если она работает лучше для вас.

RewriteEngine On

# Make sure this is only done once to avoid escaping the escapes...
RewriteCond %{ENV:REDIRECT_STATUS} ^$
# Check if we have anything to bother escaping (likely unnecessary...)
RewriteCond $0 [^\w]+
# Rewrite the entire URL by escaping the backreference
RewriteRule ^.*$ $0 [B]

Итак, почему нужно использовать B Флаг вместо того, чтобы позволить Mod_rewrite автоматически избежать переписанного URL? Когда mod_rewrite автоматически избегает URL, он использует ap_escape_uri (что, по-видимому, было превращено в макрос для ap_os_escape_path По какой-то причине ...) функция, которая ускользает от ограниченного подмножества символов. То B Флаг, однако, использует функцию внутреннего модуля escape_uri, который смоделирован на PHP urlencode функция.

Реализация escape_uri В модуле предполагает, что буквенно-цифровые символы и подчеркивания оставлены как есть, пробелы преобразуются в +, и все остальное преобразуется в его сбежавшую эквивалент. Кажется, это поведение, которое вы хотите, поэтому предположительно он должен работать.

Если нет, у вас есть возможность настроить внешнюю программу RewriteMap Это может управлять своими входящими URL в правильный формат. Это требует манипулирования конфигурацией Apache, и сценарий Renegade может вызвать проблемы для сервера в целом, поэтому я не считаю его идеальным решением, если его можно избежать.

Другие советы

MOD_REWRITE - это не лучший инструмент для выполнения этой работы. Потому что с Mod_rewrite вы можете заменить только фиксированное количество вхождений одновременно. Но это возможно:

RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?\ ]*)%20([^?\ ]*)
RewriteRule ^ /%1+%2 [R=301,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?'\ ]*)'([^?'\ ]*)
RewriteRule ^ /%1\%27%2 [R=301,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?(\ ]*)\(([^?(\ ]*)
RewriteRule ^ /%1\%28%2 [R=301,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?)\ ]*)\)([^?)\ ]*)
RewriteRule ^ /%1\%29%2 [R=301,NE]

Это заменит один %20, ', (, или ) За один раз и отвечает с перенаправлением 301. Таким образом, если путь URL содержит 10 символов, которые необходимо заменять, ему нужно 10 перенаправлений для этого.

Поскольку это может быть не лучшее решение, можно делать все замены, кроме последнего внутреннего, используя N. флаг И только последняя замена снаружи с перенаправленным:

RewriteCond %{THE_REQUEST} ^[A-Z]+\ /(([^?%\ ]|%(2[1-9a-fA-F]|[013-9][0-9a-fA-F]))*)%20(([^?%\ ]|%(2[1-9a-fA-F]|[013-9][0-9a-fA-F]))*%20[^?\ ]*)
RewriteRule ^ /%1+%4 [R=301,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?\ ]*)%20([^?\ ]*)[?\ ]
RewriteRule ^ /%1+%2 [R=301,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?'\ ]*)'([^?'\ ]*'[^?\ ]*)
RewriteRule ^ /%1\%27%2 [N,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?'\ ]*)'([^?'\ ]*)[?\ ]
RewriteRule ^ /%1\%27%2 [R=301,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?(\ ]*)\(([^?(\ ]*\([^?\ ]*)
RewriteRule ^ /%1\%28%2 [N,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?(\ ]*)\(([^?(\ ]*)[?\ ]
RewriteRule ^ /%1\%28%2 [R=301,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?)\ ]*)\)([^?)\ ]*\)[^?\ ]*)
RewriteRule ^ /%1\%29%2 [N,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?)\ ]*)\)([^?)\ ]*)[?\ ]
RewriteRule ^ /%1\%29%2 [R=301,NE]

Но используя N. Флаг может быть опасен, поскольку он не увеличивает счетчик внутреннего рекурсиона, и, таким образом, может легко привести к бесконечному рекурсии.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top