Недавно мне нужно было написать плагин для браузера Google Chrome. Суть была в анализе активной страницы и получении всевозможной SEO-информации. Под катом я опишу неприятную ситуацию, вызванную кроссдоменным ajax-запросом, а так же листинг кода для получения количества страниц в кеше яндекса для указанного домена.

Одним из пунктов востребованной SEO-информации было количество страниц в кеше яндекса. Плагин писался по-быстрому и после небольшого гугления я понял, что яндекс не предоставляет никакого API по этому поводу. Что же, приходится вручную подбирать адрес страницы, которой можно передать в качестве запроса домен нужного сайта и распарсить количество страниц. Чтобы понять, о чем я говорю посмотрите на скрин ниже:

Yandex search

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

var y_Idx = 'http://yandex.ru/yandsearch?text=&site=http://%URL%&ras=1&site_manually=true';

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

function setYaIndex(url)
{
    // Заменяем в адресе константное выражение на активный домен
    var page = y_Idx.replace('%URL%', url);
 
    $.get(page, function(response) {
       var res = response.match(/(Нашёлся|Нашлось|Нашлась)(.*?)ответ/);
       if (res == null) res = '000';
 
      var mp = 1;
      if (res[2].indexOf('тыс') > 0) mp = 1000;
      if (res[2].indexOf('млн') > 0) mp = 1000000;
 
      // Результат
      return parseFloat(res[2]) * mp;
    });
}

Парсинг он такой :). Но суть не в этом, с какой же ошибкой я столкнулся?

Cross domain ajax

Для начала объясню суть кроссдоменного аякса. Объект XMLHttpRequest блокирует любые обращения к “левым” доменам в целях безопасности. Есть несколько путей обойти эти ограничения:

  • Использовать прокси-скрипт (в том случае, если обе стороны: отправляющая и принимающая запрос написаны вами);
  • Использование Flash;
  • Использование тега script и его атрибута src.

Подробней о реализациях всего этого можете прочитать на этом сайте.

Политика безопасности в Google Chrome

Разработчики браузера Google Chrome сделали отличный API для расширений. Если вы уже писали их когда-либо, то знаете о существовании manifest.json файла, в котором можно указать некоторые параметры плагина. Среди них есть управление безопасностью, а точнее: адреса/домены, к которым скрипт непосредственно может обращаться. Таким образом мы можем обойти запрет на запрос к “левым” доменам, но с ограниченным списком этих самых доменов. Конечно, ничто не мешает прописать в качестве маски: “http://*/”, но это некрасиво и небезопасно.

Вернемся к плагину, который я создавал. Я прописал в manifest.json вот такой код:

  "permissions": [
    "tabs",
    "http://yandex.ru/*",
    "https://yandex.ru/*"
  ]

В итоге $.get не возвращал результата. Отследив Firebug'ом я понял, что там идет редирект с изменением адреса страницы. Там же я увидел, что меняется домен и к нему добавляются аргументы: lr, ncnrd. Как я понимаю, так яндекс отслеживает пользователей. К сожалению, у меня не сохранились скрины с выводом FireBug'a, где было видно сам факт редиректа и возвращаемую информацию, но было видно, что после первого редиректа (а до этого все шло отлично) вдруг обрывается какая-либо связь.

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

Причина ошибки

А разгадка проста. Если читатель внимательный, он ещё мог заметить это на первом скрине. Я живу в Украине, поэтому яндекс автоматически обнаруживает мой регион и перенаправляет на украинский домен яндекса. В итоге, первый запрос шел к ru-домену, а редирект пересылал второй запрос на ua-домен.

Как вы могли бы догадаться, чтобы решить проблему нужно изменить маску в manifest.json на http://yandex.*/*. Будьте внимательны!