вторник, 14 июля 2015 г.

X-Robots-Tag: noindex, follow, noarchive

Как оказалось, использование HTTP-заголовка X-Robots-Tag: noindex, follow, noarchive абсолютно не мешают Гуглю пытаться скачивать URL. Наверное, дело в follow.

Я вообще-то сразу предлагал использовать nofollow. Но тут палка о двух концах: Гугль с осторожностью относится к сайтам, на которых очень много ссылок с nofollow. Логика такая - раз даже вебмастер понимает, что большая часть его внешних ссылок плохие, то, наверное, и сам сайт тоже плохой.

Вы спросите, а зачем вообще использовать X-Robots-Tag, а не meta-тэг? Потому что эта URL используется как exit link на рекламу, и возвращает 302. Т.е. страницы нет как таковой, некуда тэг влепить. 

В общем, не послушались меня. В результате после смены структуры сайта имеем десятки тысяч запросов к этой уже несуществующей URL каждый день. 

Возвращаем 410 Gone, и потихоньку количество ошибок уменьшается. Почему 410, а не 301 на главную страницу? Потому что ошибок слишком уж много, Гуглю может не понравится, если тупо всё перенаправлять.

понедельник, 6 июля 2015 г.

Проблема с catch-all и rewriteMaps

Задача: используя IIS URL Rewrite, перенаправить всё содержимое старого каталога (clients) в новое место (customers). Например, /clients/Gazprom/ в /customers/.

Это просто:

  <rule name="Сatch-all">
    <match url="^clients/" />
    <action type="Redirect" url="customers/" />
  </rule>

Поскольку в url я не использовал знак $ (конец строки), то отлавливаются все строки, начинающиеся на clients/.

А что, если у нас таких каталогов несколько (clients / partnerts / advertisers)? Пожалуйста: <match url="^(clients|partners|advertisers)/" />

А если их десяток? Причем нужно перенаправлять в разные места.
Тоже несложно - воспользуемся "картами":

<rewriteMaps>
<rewriteMap name="CatchAllRedirects">
  <add key="old1" value="new1" />
  <add key="old2" value="new2" />
  <add key="old3" value="new3" />
  <add key="old4" value="new4" />
</rewriteMap>
</rewriteMaps>

....

  <rule name="Catch-all">
    <match url="^([^/]+)/" />
    <conditions>
      <add input="{CatchAllRedirects:{R:1}}" pattern="(.+)"/>
    </conditions>
    <action type="Redirect" url="{C:1}/" />
  </rule>

Здесь мы перенаправляем /old1/*/ в /news1/ , /old2/*/ в /news1/ и т.д.


Пока что ничего особенного. Сложности возникают, если в старой URL может быть несколько уровней вложенности. Т.е. нужно перепроверить:

/old1/*/
/old1/*/*/
/old1/*/*/*/
/old2/old3/*/
/old2/old3/*/*/*/

Казалось бы, просто меняем ([^/]+) (хоть один символ, но не слэш) на (.+) (хоть один символ, любой):


  <rule name="Catch-all">
    <match url="^(.+)/" />
    <conditions>
      <add input="{CatchAllRedirects:{R:1}}" pattern="(.+)"/>
    </conditions>
    <action type="Redirect" url="{C:1}/" />
  </rule>


И добавляем в карту вложенные каталоги:

<rewriteMap name="CatchAllRedirects">
  <add key="old1" value="new1" />
  <add key="old2/old3" value="new2" />
   ....
</rewriteMap>

И не работает.

Потому что {R:1} (результат регулярного выражения, который используется как ключ для поиска) всегда один и только один. Правило не станет перебирать все возможные варианты (с одним слэшем, двумя, тремя) и пытаться найти соответвующий ключ в карте. Проблема в том, что при использовании карты обработка правила происходит в два шага: сначала регулярное выражение в <match>, и только потом поиск значения в карте.

Если же всё старые каталоги запихнуть в регулярное выражение и не использовать карту, то проблемы нет. Или можно сделать отдельные правила для разных уровней вложенности старого каталога. Но, конечно, если таких уровней десяток, то это непрактично...

Летучие мыши

С 2008 года в Англии упростили процедуру для loft conversion (перестройка чердака в жилую площадь): для большинства небольших проектов теперь не требуется разрешение.

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

четверг, 2 июля 2015 г.

Батарея за фунт

После ремонта выставил на eBay старую батарею. Начальную цену поставил один фунт, да так больше никто и не предложил. Ну, делать нечего - раз продалась, так продалась.

Договорился с покупателем о встрече. Он никак не приезжает. А мне тратить выходной на него вроде как не с руки ради одного фунта. Телефона я не знаю. Написал ему: "Я уезжаю, оставил калитку незапертой, батарея сразу за ней, сам заберешь".

Вернулся - батареи нет. Но через некоторое время он пишет: "Ой, извини, у меня мама заболела, я не смог приехать". Хм... а кто же забрал батарею? Случайный прохожий? Но это, можно сказать, кража. Я ведь не вынес батарею на улицу, она стояла на моей территории; калитка сплошная, с улицы почти не видно; улица тихая...

Ну, а с другой стороны, бывают всякие странные совпадения... К счастью, у меня была вторая точно такая же батарея. Опять договорились встретиться, и опять он не пришел. Ну, я уже больше сам писать ему не стал. Подождал ещё для верности да и отвез в металлолом.

А этот мудак взял и оставил про меня негативный отзыв! Причем договариваться о новой встрече он и не пытался.

среда, 1 июля 2015 г.

Говорить ли Гуглю про перенос сайта

Как известно, при смене домена (например, example.com.ua на example.ua) обычно рекомендуется не только настроить 301 redirects, но и сообщить Гуглю через Webmasters Tools.

Но есть случай, когда это делать не стоит: если вы одновременно со сменой домена меняете и структуру URL. Допустим, раньше у вас были миллионы страниц с адресами вроде example.com.ua/offers/London/. А теперь каждая из них переносится в example.ua/best-offers-in-London/. В этом случае нам нужна грубая сила - Гугль должен переиндесировать каждую из миллиона страниц. Если же сообщить ему про смену домена, он может схалтурить и решить, что просто меняется домен, а все пути остаются старыми.

По этой же причине в такой ситуации не стоит добавлять в robots.txt директиву Host:example.ua (впрочем, она вроде влияет только на Яндекс).

Секция httpErrors в сочетании с IIS URL Rewrite

Столкнулся с ситуацией, которая, похоже, не описана в документации: такое впечатление, что модуль URL Rewrite не всегда срабатывает...

Итак, первое обстоятельство: в web.config есть секция:

    <httpErrors errorMode="Custom" existingResponse="Replace" defaultPath="/Errors/ServerError">
      <clear/>
      <error responseMode="ExecuteURL" statusCode="403" path="/Errors/NotSupported"/>          
      <error responseMode="ExecuteURL" statusCode="404" path="/Errors/PageNotFound"/>
      <error responseMode="ExecuteURL" statusCode="410" path="/Errors/Gone"/>
      <error responseMode="ExecuteURL" statusCode="500" path="/Errors/ServerError"/>
      <error responseMode="ExecuteURL" statusCode="503" path="/Errors/ServiceUnavailable"/>
    </httpErrors>

В MVC-приложении есть ErrorsController с соответвующими actions (ServerError, NotSupported и т.д.) Таким образом, в случае ошибок мы показывает красивые странички с неким динамическим контентом. Вот как оно работает: когда пользователь запрашивает несуществующий адрес http://example.ua:80/some-invalid-URL/ , IIS незаметно подменяет этот адрес на http://example.ua/Errors/PageNotFound?404;http://example.ua:80/some-invalid-URL/ и возвращает клиенту полученный HTML. Код ошибки и проблемный адрес передаются в query string, поэтому MVC приложение может их как-нибудь использовать.


Второе обстоятельство: я использую модуль URL Rewrite. В нем есть довольно сложная логика, которая добавляет к запросу нестандартный заголовок HTTP, который я потом использую в приложении. Этот заголовок для меня очень важен - он проверяется при каждом запросе. Казалось, непробиваемая система - ведь запрос даже не дойдет до приложения, пока не пройдет URL Rewrite. По идее, может сломаться, только если отключить URL Rewrite или неправильно его сконфигурировать?


Но оказывается, что в очень редких случаях это не работает: когда URL ошибочная, и при этом в ней есть точка, или она заканчивается на пробел. Насколько я понимаю, в этой ситуации IIS пересылает запрос в приложение (в ErrorsController) напрямую, минуя URL Rewrite. Возможно, по соображениям безопасности. А может, баг (версия IIS - 8.0.9200.16384).

Ratings by outbrain