SharePoint Alfresco PHP MySQL
О сайте Контакты
суббота, 31 марта 2012 г.

Установка счетчиков посещаемости на любые страницы средствами Apache HTTPD

Некоторые веб-приложения не имеют единого шаблона вывода, куда можно было бы просто вставить код счетчика (Google Analytics или Яндекс Метрика). В таких приложениях HTML-страницы генерируются различными способами и по различным шаблонам. Чтобы вставить в такие системы код счетчика, можно использовать возможности Apache HTTPD.

Логика работы такова:

1) Перехватывается сгенерированный HTML-трафик

2) В перехваченном тексте ищется место, в которое необходимо вставить счетчик. В общем случае, это «</body>», так как счетчики обычно вставляются перед этим тэгом (можно искать «</header>»)

3) Найденные вхождения заменяются на код со счетчиком

4) Трафик отдается клиенту

Перехватить трафик средствами apache можно, используя его в качестве прокси. Заменять текст можно утилитой sed (она есть также и для windows). Помимо этого, надо удостовериться, что замена идет в простом тексте, а не сжатом, так как сервер может сжимать трафик внутренними средствами. До замены нужно распаковать трафик. Далее, произведя замену, нужно снова сжать его.

Можно использовать следующие настройки apache:

Listen *:80
Listen 127.0.0.1:20001

<VirtualHost 127.0.0.1:20001>
  # интеграция с приложением
  ProxyPreserveHost On
  ProxyPass / ajp://127.0.0.1:8009/ min=5 ttl=120 keepalive=On ping=1
  ProxyPassReverse / ajp://127.0.0.1:8009/
  
  # фильтр для замены текста
  ExtFilterDefine metrika mode=output \
    cmd="C:/apache_scripts/metrika_filter.cmd" \
    intype=text/html
  
  # распаковка трафика и применение замены
  AddOutputFilterByType INFLATE;metrika text/html
</VirtualHost>

<VirtualHost *:80>
  # прокси для сжатия получившегося трафика
  ProxyPreserveHost On
  ProxyPass / http://127.0.0.1:20001/ min=5 ttl=120 keepalive=On ping=1
  ProxyPassReverse / http://127.0.0.1:20001/
  
  # сжатие html-трафика
  AddOutputFilterByType DEFLATE text/html
</VirtualHost>

Таким образом, создаются два виртуальных хоста, один ловит поток другого. Теоретически, можно было бы применить фильтры в нужном порядке, однако практически это сделать не удается. По умолчанию вначале выполняется распаковка, потом сжатие, потом замена. Естественно, нужен другой порядок. Применение модуля mod_filter с его механизмом filter chaining здесь не помогает, так как он не взаимодействует с фильтрами, установленными с помощью ExtFilterDefine (возможно, это связано с багами в реализации модулей для apache 2.2).

Код файла metrika_filter.cmd:

@echo off
set _command="s/<\/body>/<!-- Yandex.Metrika counter --><script type='text\/javascript'>(function (d, w, c) { (w[c] = w[c] || []).push(function() { try { w.yaCounterXXXXXX = new Ya.Metrika({id:XXXXXX, enableAll: true, ut:'noindex'}); } catch(e) {} }); var n = d.getElementsByTagName('script')[0], s = d.createElement('script'), f = function () { n.parentNode.insertBefore(s, n); }; s.type = 'text\/javascript'; s.async = true; s.src = (d.location.protocol == 'https:' ? 'https:' : 'http:') + '\/\/mc.yandex.ru\/metrika\/watch.js'; if (w.opera == '[object Opera]') { d.addEventListener('DOMContentLoaded', f); } else { f(); } })(document, window, 'yandex_metrika_callbacks');<\/script><noscript><div><img src='\/\/mc.yandex.ru\/watch\/XXXXXX?ut=noindex' style='position:absolute; left:-9999px;' alt='' \/><\/div><\/noscript><!-- \/Yandex.Metrika counter --><\/body>/gi"
sed %_command%

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

Sergey Lysenko, суббота, 31 марта 2012 г.

Комментарии: