@ -339,7 +339,7 @@ void App::ProcessRequest()
log < < log2 < < config . log_delimiter < < logend ;
ProcessRequestThrow ( ) ;
SaveSessionsIfNeeded ( ) ; // !! przerzucic to na watek sesji
SaveSessionsIfNeeded ( ) ; // !! IMPROVE ME move to the session's thread
system . load_avg . StopRequest ( ) ;
}
@ -356,25 +356,48 @@ void App::ProcessRequest()
log < < log1 < < " App: there was an unknown exception " < < logend ;
}
ClearAfterRequest ( ) ;
}
void App : : ClearAfterRequest ( )
{
try
{
plugin . Call ( WINIX_END_REQUEST ) ;
}
catch ( . . . )
{
log < < log1 < < " App: an exception when clearing after a request (exception from a plugin) " < < logend ;
log < < log1 < < " App: an exception from a plugin when clearing after a request" < < logend ;
}
// simple operations which should not throw an exception
templates . RequestEnd ( ) ;
cur . request - > Clear ( ) ;
cur . session - > ClearOnEndRequest ( ) ;
cur . session = session_manager . GetTmpSession ( ) ;
log < < logendrequest ;
try
{
// simple operations which should not throw an exception
json_out_stream . Clear ( ) ;
templates . ClearAfterRequest ( ) ;
cur . request - > Clear ( ) ;
cur . session - > ClearAfterRequest ( ) ;
cur . session = session_manager . GetTmpSession ( ) ;
output_8bit . clear ( ) ;
compressed_output . clear ( ) ;
html_filtered . clear ( ) ;
aheader_name . clear ( ) ;
aheader_value . clear ( ) ;
// send_data_buf doesn't have to be cleared and it is better to not clear it (optimizing)
log < < logendrequest ;
}
catch ( . . . )
{
log < < log1 < < " App: an exception when clearing after a request " < < logend ;
}
}
void App : : Start ( )
{
while ( ! synchro . was_stop_signal & & FCGX_Accept_r ( & fcgi_request ) = = 0 )
@ -475,12 +498,6 @@ bool sent = false;
{
templates . Generate ( ) ;
}
if ( cur . request - > return_json )
{
CreateJSONAnswer ( ) ;
}
}
@ -915,7 +932,7 @@ void App::PrepareHeadersCompression(int compress_encoding)
}
void App : : PrepareHeadersNormal ( Header header )
void App : : PrepareHeadersNormal ( Header header , size_t output_size )
{
switch ( header )
{
@ -932,6 +949,9 @@ void App::PrepareHeadersNormal(Header header)
cur . request - > out_headers . Add ( L " Status " , L " 200 OK " ) ;
PrepareHeaderContentType ( ) ;
}
if ( output_size ! = static_cast < size_t > ( - 1 ) )
cur . request - > out_headers . Add ( L " Content-Length " , output_size ) ;
}
@ -986,7 +1006,7 @@ void App::SendCookies()
}
void App : : PrepareHeaders ( bool compressing , int compress_encoding , Header header )
void App : : PrepareHeaders ( bool compressing , int compress_encoding , Header header , size_t output_size )
{
PrepareSessionCookie ( ) ;
@ -1009,7 +1029,7 @@ void App::PrepareHeaders(bool compressing, int compress_encoding, Header header)
}
else
{
PrepareHeadersNormal ( header );
PrepareHeadersNormal ( header , output_size );
}
if ( compressing )
@ -1018,41 +1038,42 @@ void App::PrepareHeaders(bool compressing, int compress_encoding, Header header)
void App : : FilterCompressSend ( bool compressing , int compress_encoding , const std : : wstring & source_ref )
void App : : FilterContent ( )
{
const std : : wstring * source = & source_ref ;
Request & req = * cur . request ;
bool raw = req . is_item & & req . item . content_type = = Item : : ct_raw & &
req . status = = WINIX_ERR_OK & & req . function & &
( req . function = = & functions . fun_cat | | req . function = = & functions . fun_run ) ;
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 ) ;
size_t start = req . out_streams . size ( ) ; // default nothing should be filtered
size_t end = req . out_streams . size ( ) ;
if ( config . html_filter & & cur . request - > use_html_filter & & ! raw & & ! cur . request - > return_json )
{
TemplatesFunctions : : html_filter . Filter ( * source , clean_html ) ;
source = & clean_html ;
}
else
if ( config . html_filter & & ! req . send_bin_stream & & ! raw )
{
html_with_debug = * source ;
source = & html_with_debug ;
if ( req . return_json )
{
if ( ! req . return_info_only )
{
start = 1 ;
}
}
else
{
start = 0 ;
end = 1 ;
}
}
if ( config . utf8 )
PT : : WideToUTF8 ( * source , source_a ) ;
else
AssignString ( * source , source_a ) ;
// !! IMPROVE ME add to log the binary stream as well
if ( config . log_server_answer )
log < < log1 < < " App: the server's answer is: \n " < < source_a < < " \n App: end of the server's answer " < < logend ;
if ( compressing )
compress . CompressAndPut ( source_a . c_str ( ) , source_a . length ( ) , fcgi_request . out , compress_encoding ) ;
else
FCGX_PutS ( source_a . c_str ( ) , fcgi_request . out ) ;
if ( cur . request - > return_json )
json_out_stream . Clear ( ) ;
for ( size_t i = start ; i < end ; + + i )
{
if ( req . use_html_filter [ i ] )
{
// !! IMPROVE ME may some kind of html_filtered.reserve() here? (optimization)
TemplatesFunctions : : html_filter . Filter ( req . out_streams [ i ] . Str ( ) , html_filtered ) ;
req . out_streams [ i ] . Str ( std : : move ( html_filtered ) ) ;
}
}
}
@ -1067,6 +1088,7 @@ int App::SelectDeflateVersion()
}
void App : : SelectCompression ( size_t source_len , bool & compression_allowed , int & compression_encoding )
{
compression_allowed = false ;
@ -1114,7 +1136,7 @@ void App::SelectCompression(size_t source_len, bool & compression_allowed, int &
bool App : : CanSendContent ( Header header )
bool App : : CanSendContent ( )
{
if ( ! cur . request - > redirect_to . empty ( ) | | ! cur . request - > x_sendfile . empty ( ) )
// if there is a redirect or a file to send then we do not send a content
@ -1132,22 +1154,10 @@ return true;
void App : : SendTextAnswer ( )
App : : Header App : : GetHTTPStatusCode ( )
{
const std : : wstring * source ;
Header header = h_200 ;
Error status = cur . request - > status ;
bool compressing ;
int compress_encoding ;
if ( cur . request - > return_json )
source = & json_out_stream . Str ( ) ;
else
source = & cur . request - > out_streams [ 0 ] . Str ( ) ;
SelectCompression ( source - > length ( ) , compressing , compress_encoding ) ;
Error status = cur . request - > status ;
Header header = h_200 ;
if ( status = = WINIX_ERR_NO_ITEM | | status = = WINIX_ERR_NO_FUNCTION | | status = = WINIX_ERR_UNKNOWN_PARAM )
{
@ -1167,15 +1177,67 @@ int compress_encoding;
header = h_200 ;
}
PrepareHeaders ( compressing , compress_encoding , header ) ;
return header ;
}
void App : : SendTextAnswer ( )
{
const std : : wstring * source ;
bool compressing = false ;
int compress_encoding = 0 ;
size_t output_size = 0 ;
Header header = GetHTTPStatusCode ( ) ;
if ( CanSendContent ( ) )
{
FilterContent ( ) ;
if ( cur . request - > return_json )
{
CreateJSONAnswer ( ) ;
source = & json_out_stream . Str ( ) ; // json_out_stream was prepared by CreateJSONAnswer()
}
else
{
source = & cur . request - > out_streams [ 0 ] . Str ( ) ;
}
SelectCompression ( source - > length ( ) , compressing , compress_encoding ) ;
if ( config . utf8 )
PT : : WideToUTF8 ( * source , output_8bit ) ;
else
AssignString ( * source , output_8bit ) ;
// !! IMPROVE ME add to log the binary stream as well
if ( config . log_server_answer )
log < < log1 < < " App: the server's answer is: \n " < < output_8bit < < " \n App: end of the server's answer " < < logend ;
if ( compressing )
{
compress . Compressing ( output_8bit . c_str ( ) , output_8bit . length ( ) , compressed_output , compress_encoding ) ;
output_size = compressed_output . size ( ) ;
}
else
{
output_size = output_8bit . size ( ) ;
}
}
PrepareHeaders ( compressing , compress_encoding , header , output_size ) ;
SendHeaders ( ) ;
SendCookies ( ) ;
FCGX_PutS ( " \r \n " , fcgi_request . out ) ;
if ( CanSendContent ( header ) )
if ( CanSendContent ( ) )
{
// filtering (html), compressing and sending back to the web browser
FilterCompressSend ( compressing , compress_encoding , * source ) ;
if ( compressing )
SendData ( compressed_output , fcgi_request . out ) ;
else
FCGX_PutStr ( output_8bit . c_str ( ) , output_8bit . size ( ) , fcgi_request . out ) ;
}
}
@ -1187,7 +1249,7 @@ void App::SendData(const BinaryPage & page, FCGX_Stream * out)
if ( send_data_buf . size ( ) ! = buf_size )
send_data_buf . resize ( buf_size ) ;
BinaryPage : : const_iterator i = page . begin ( ) ;
BinaryPage : : const_iterator i = page . begin ( ) ;
BinaryPage : : const_iterator end = page . end ( ) ;
while ( i ! = end )
@ -1219,18 +1281,19 @@ int compress_encoding;
if ( status = = WINIX_ERR_PERMISSION_DENIED | | status = = WINIX_ERR_CANT_CHANGE_USER | | status = = WINIX_ERR_CANT_CHANGE_GROUP )
header = h_403 ;
// !! IMPROVE ME add header: content-size
PrepareHeaders ( compressing , compress_encoding , header ) ;
// !! IMPROVE ME add header: content-length (size from Item struct)
// warning: if someone changed a file on the disk (in the real os)
// then winix would send an incorrect content-lenght header,
// we are waiting for the fsck winix function to be implemented
PrepareHeaders ( compressing , compress_encoding , header , static_cast < size_t > ( - 1 ) ) ;
if ( CanSendContent ( header ) )
if ( CanSendContent ( ) )
{
if ( compressing )
{
out_bin_stream_compressed . clear ( ) ; // !! IMPROVE ME add to the end of a request
compress . Compressing ( source , out_bin_stream_compressed , compress_encoding ) ;
SendData ( out_bin_stream_compressed , fcgi_request . out ) ;
out_bin_stream_compressed . clear ( ) ;
compress . Compressing ( source , compressed_output , compress_encoding ) ;
SendData ( compressed_output , fcgi_request . out ) ;
}
else
{