added support for gzip compression

new config option: compression_encoding (integer)
 1  - use deflate if available (or raw deflate for Internet Explorer) or don't compress
 2  - use gzip if available or don't compress
 10 - prefer deflate -- use deflate (or raw deflate for IE) if both deflate and gzip are available
 20 - prefer gzip    -- use gzip if both deflate and gzip are available
 default: 20

		   


git-svn-id: svn://ttmath.org/publicrep/winix/trunk@727 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
2011-04-02 00:10:16 +00:00
parent 1b60935d08
commit aadf12c7b3
9 changed files with 316 additions and 86 deletions

View File

@@ -2,7 +2,7 @@
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2010, Tomasz Sowa
* Copyright (c) 2010-2011, Tomasz Sowa
* All rights reserved.
*
*/
@@ -385,7 +385,7 @@ void App::ReadRequest()
ReadGetPostVars();
cookie_parser.Parse(cur.request->env_http_cookie, cur.request->cookie_tab);
accept_encoding_parser.Parse(cur.request->env_http_accept_encoding);
accept_encoding_parser.ParseAndLog(cur.request->env_http_accept_encoding);
CheckIE();
CheckKonqueror();
@@ -540,7 +540,7 @@ void App::PrepareSessionCookie()
void App::SendHeaders(bool compressing, Header header)
void App::SendHeaders(bool compressing, int compress_encoding, Header header)
{
PrepareSessionCookie();
@@ -590,8 +590,13 @@ void App::SendHeaders(bool compressing, Header header)
}
}
if( compressing )
FCGX_PutS("Content-Encoding: deflate\r\n", fcgi_request.out);
if( compressing )
{
if( compress_encoding == 0 || compress_encoding == 1 )
FCGX_PutS("Content-Encoding: deflate\r\n", fcgi_request.out);
else
FCGX_PutS("Content-Encoding: gzip\r\n", fcgi_request.out);
}
FCGX_PutS(cur.request->headers.CStr(), fcgi_request.out);
FCGX_PutS("\r\n", fcgi_request.out);
@@ -610,14 +615,12 @@ void App::SetHtmlFilterConf()
}
// !! kopiowanie tych stringow bedzie zmienione
// gdy bedziemy korzystac w przyszlosci z wlasnego stringstream
void App::FilterCompressSend(bool compressing, const std::wstring & source_ref)
void App::FilterCompressSend(bool compressing, int compress_encoding, const std::wstring & source_ref)
{
const std::wstring * source = &source_ref;
bool raw = cur.request->is_item && cur.request->item.content_type == Item::ct_raw && cur.request->status == WINIX_ERR_OK &&
cur.request->function && (cur.request->function == &functions.fun_cat || cur.request->function == &functions.fun_run);
cur.request->function && (cur.request->function == &functions.fun_cat || cur.request->function == &functions.fun_run);
if( config.html_filter && !raw )
{
@@ -633,32 +636,76 @@ void App::FilterCompressSend(bool compressing, const std::wstring & source_ref)
source = &html_with_debug;
}
// !! zrobic z tym porzadek
std::string temp;
Ezc::WideToUTF8(*source, temp);
if( config.utf8 )
Ezc::WideToUTF8(*source, source_a);
else
AssignString(*source, source_a);
if( compressing )
compress.CompressAndPut(temp.c_str(), temp.length(), fcgi_request.out);
compress.CompressAndPut(source_a.c_str(), source_a.length(), fcgi_request.out, compress_encoding);
else
FCGX_PutS(temp.c_str(), fcgi_request.out);
FCGX_PutS(source_a.c_str(), fcgi_request.out);
}
bool App::IsCompressionAllowed(const std::wstring & source)
int App::SelectDeflateVersion()
{
return( config.compression &&
cur.request->role == Request::responder &&
cur.request->redirect_to.empty() &&
cur.request->x_sendfile.empty() &&
!cur.request->browser_msie &&
!cur.request->browser_konqueror &&
accept_encoding_parser.AcceptDeflate() &&
source.size() >= (size_t)config.compression_page_min_size );
if( cur.request->browser_msie )
return 0; // raw deflate
else
return 1; // deflate
}
void App::SelectCompression(size_t source_len, bool & compression_allowed, int & compression_encoding)
{
compression_allowed = false;
compression_encoding = 0;
if( config.compression &&
cur.request->role == Request::responder &&
cur.request->redirect_to.empty() &&
cur.request->x_sendfile.empty() &&
!cur.request->browser_konqueror && /* !! sprawdzic czy Konqueror bedzie obslugiwal raw deflate */
source_len >= config.compression_page_min_size )
{
if( config.compression_encoding == 1 || config.compression_encoding == 10 )
{
if( accept_encoding_parser.AcceptDeflate() )
{
compression_allowed = true;
compression_encoding = SelectDeflateVersion();
}
else
if( config.compression_encoding == 10 && accept_encoding_parser.AcceptGzip() )
{
compression_allowed = true;
compression_encoding = 2; // gzip
}
}
if( config.compression_encoding == 2 || config.compression_encoding == 20 )
{
if( accept_encoding_parser.AcceptGzip() )
{
compression_allowed = true;
compression_encoding = 2; // gzip
}
else
if( config.compression_encoding == 20 && accept_encoding_parser.AcceptDeflate() )
{
compression_allowed = true;
compression_encoding = SelectDeflateVersion();
}
}
}
}
bool App::CanSendContent(Header header)
{
if( !cur.request->redirect_to.empty() || !cur.request->x_sendfile.empty() )
@@ -698,9 +745,12 @@ void App::AddDebugInfo(std::wstring & out)
void App::SendAnswer()
{
const std::wstring & source = cur.request->page.Str();
Header header = h_200;
bool compressing = IsCompressionAllowed(source);
Error status = cur.request->status;
Header header = h_200;
Error status = cur.request->status;
bool compressing;
int compress_encoding;
SelectCompression(source.length(), compressing, compress_encoding);
if( status == WINIX_ERR_NO_ITEM || status == WINIX_ERR_NO_FUNCTION || status == WINIX_ERR_UNKNOWN_PARAM )
header = h_404;
@@ -708,12 +758,12 @@ Error status = cur.request->status;
if( status == WINIX_ERR_PERMISSION_DENIED || status == WINIX_ERR_CANT_CHANGE_USER || status == WINIX_ERR_CANT_CHANGE_GROUP )
header = h_403;
SendHeaders(compressing, header);
SendHeaders(compressing, compress_encoding, header);
if( CanSendContent(header) )
{
// filtering (html), compressing (deflate) and sending back to the web browser
FilterCompressSend(compressing, source);
// filtering (html), compressing and sending back to the web browser
FilterCompressSend(compressing, compress_encoding, source);
}
}