2

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

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

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

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

  • www.splunkbase.com/apps/All/4.x/Add-On/app:OPSEC + LEA + для + Check + точка + (Linux)
  • www.splunkbase.com/apps/All/4.x/Add-On/app:OPSEC+LEA+for+Check+Point+%28Linux%29

Вот еще:

  • www.splunkbase.com/apps/All/4.x/app:Benford's+Law+Fraud+Detection+Add-on
  • www.splunkbase.com/apps/All/4.x/app:Benford%27s + закон + мошенничество + обнаружение + Add-на

Вот еще:

  • www.splunkbase.com/apps/All/4.x/app:Benford%27s%20Law%20Fraud%20Detection % 20Add-на
  • www.splunkbase.com/apps/All/4.x/app:Benford%27s+Law+Fraud+Detection+Add-on

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

Я новичок с правилами перезаписи, и из моего описания mod-rewrite documentation было ясно, что mod_rewrite выполняет некоторую автоматическую кодировку/декодирование, которая может помочь или повредить то, что я хочу сделать, хотя и не уверен.

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

+1

У вас есть полный доступ к конфигурации Apache или вы ограничены решением, которое подходит для htaccess? –

+0

у нас есть полный доступ к конфигурации apache, хотя я подозреваю, что наша операционная команда предпочла бы минимально-инвазивное решение. –

ответ

1

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

Имейте в виду, что значение 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, хотя сценарий ренегата может вызвать проблемы для сервера в целом, поэтому я не считаю его идеальным решением, если его можно избежать.

+0

Это похоже на ответ, который я искал. Ницца! –

1

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 flag и только последнюю замену внешне с переадресацией:

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 флаг может быть опасным, так как он не увеличивает счетчик внутренней рекурсии и, следовательно, может легко привести к бесконечной рекурсии.

+0

Хммм. На уровне сложности выше, вероятно, проще попросить команду dev переписать код переадресации. :-) Другой ответ выглядит проще, поэтому я соглашусь. Но мне нравится ваша общая идея повторять правила - возможно, это не решение, которое я хотел бы здесь, но может быть полезным в других обстоятельствах. Благодаря! +1 –

+0

@ Юстин Грант: Да, наверное. – Gumbo

 Смежные вопросы

  • Нет связанных вопросов^_^