Pull to refresh

PHP: Уменьшаем исходящий трафик (или изобретаем очередной велосипед)

Lumber room
В связи с разработкой мобильной версии сайта столкнулся с проблемой — передается много данных, как следствие на мобильном телефоне тратится много денег, было решено написать несколько функций предназначенных для уменьшения передаваемых данных

Во первых было уменьшен размер отдаваемого HTML, с помощью простого класса:
class OutBufferFilter {
function OutBufferFilter() {
if( @ob_start( array(&$this, 'filter') ) ) {
register_shutdown_function( array(&$this, 'shutdown') );
}
}
function filter( $chunk, $mode ) {
return(
str_replace( '> <', '><',
ereg_replace( "[ \t\r\n]{2,}", ' ',
$chunk
)
)
);
}
function shutdown() {
while( @ob_end_flush() );
}
}
* This source code was highlighted with Source Code Highlighter.

Понятное дело, что метод filter не идеален, но на том HTML-коде который есть у меня он работает (в дизайне не используется теги типа pre)
Потом была добавлена компрессия gzip-ом:
class OutBufferFilterGZ extends OutBufferFilter {
var $use_gzhandler = false;

function OutBufferFilterGZ() {
$this->use_gzhandler = function_exists('ob_gzhandler');
parent::OutBufferFilter();
}
function filter( $chunk, $mode ) {
return(
$this->use_gzhandler?
ob_gzhandler( parent::filter( $chunk ), $mode ):
parent::filter( $chunk, $mode )
);
}
}
* This source code was highlighted with Source Code Highlighter.

Потом класс был расширен на предмет того что-бы кешировать полученные страницы в memcached-е, и если в качестве frontend-а используется nginx, то контент отдавался без участия php, а напрямую из memecache
class OutBufferCached extends OutBufferFilterGZ {
var $memcache = false;
var $content = '';
var $timeout = 10;

function key() {
global $_SERVER;

return( ( isset( $_SERVER )
and isset( $_SERVER[«REQUEST_METHOD»] )
and $_SERVER[«REQUEST_METHOD»] == 'GET'
)?
( 'pda:html:'
. (isset( $_SERVER[«SCRIPT_NAME»] )? $_SERVER[«SCRIPT_NAME»]: '')
. (isset( $_SERVER[«PATH_INFO»] )? $_SERVER[«PATH_INFO»]: '' )
. '?'
. (isset( $_SERVER[«REQUEST_URI»] )? $_SERVER[«REQUEST_URI»]: '' )
):
''
);
}
function OutBufferCached( $memcache = false ) {
$key = $this->key();

if( !empty($key) and $memcache and @$memcache->getVersion() !== false ) {
$this->memcache = $memcache;
$this->content = $this->memcache->get( $key );

if( $this->content !== false ) {
$this->shutdown( false );
exit();
}
else {
$this->content = '';
}
}
parent::OutBufferFilterGZ();
}
function filter( $chunk, $mode ) {
$this->content .= parent::filter( $chunk, $mode );

return(null);
}
function shutdown( $store = true ) {
parent::shutdown();
$this->output();
if( $store ) {
$key = $this->key();

if( $this->memcache and !empty($key) and $this->timeout ) {
$this->memcache->set(
$key,
$this->content,
MEMCACHE_COMPRESSED,
$this->timeout
);
}
}
$this->content = '';
}
function output() {
echo $this->content;
flush();
}
function timeout( $t = 10 ) {
$this->timeout = $t;
}
function nocache() {
$this->timeout( 0 );
}
}
* This source code was highlighted with Source Code Highlighter.

Все тестировалось по PHP4 и PHP5 — пока проблем не возникло.
Собственно хотелось-бы узнать насколько интересен изобретенный мною велосипед ?
Update: Сделал подсветку кода (правда на source.virtser.net/default.aspx нету PHP, а другие, где есть PHP не годятся для habrahabr.ru :-)
Update 2: Сттистика по поддержке компрессии в мобильных устройствах: waplog.net/ru/html/stat/1/gzip
Tags:phpgzipfiltermemcachednginxpdaapache
Hubs: Lumber room
Total votes 1: ↑5.5 and ↓-4.5+10
Views492

Popular right now