removed: ezn patterns for rawcontent and ajaxcontent:

index_rawcontent.html, index_ajaxcontent.html
         now we have out_streams in Request and some special
         keyword in ezc templates for sending content to the 
         specified streams
changed: the way how winix answers to the client's browsers:
         info from Request class:
	                                   winix answer send to the client's browser
	                                                       |
	                                                       |
	                                          depending on send_bin_stream
	                               -------------------------------------------------
	                               |                                               |
	                          text answer                                     binary answer
	                               |                                               |
	                   depending on return_json                          sending out_bin_stream
	             ------------------------------------
	             |                                  |
	       normal request                     ajax request
	             |                                  |
	   sending out_streams[0]           depending on return_info_only
	                              ------------------------------------------------------
	                              |                                                    |
	                 generating JSON object from:                   generating JSON object only from info
	                 out_streams and info, e.g.:                    e.g.:
	                 {                                              { info object serialized here }
	                  "stream_1": "some html content",
	                  "stream_2": "some other html content",
	                  "info": { info object serialized here }
	                 }
	                 note that out_streams[0] is not sent
	                 in JSON answers
	
	




git-svn-id: svn://ttmath.org/publicrep/winix/trunk@937 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
2013-11-14 20:59:23 +00:00
parent d801f53154
commit 3af3ac3f6f
15 changed files with 303 additions and 115 deletions

View File

@@ -316,7 +316,8 @@ void App::ProcessRequestThrow()
}
plugin.Call(WINIX_SESSION_CHANGED);
functions.Parse(); // parsing directories,files,functions and parameters
functions.Parse(); // parsing directories,files,functions and parameters
cur.mount = system.mounts.CalcCurMount();
if( cur.mount->type != system.mounts.MountTypeStatic() )
@@ -400,13 +401,51 @@ void App::SaveSessionsIfNeeded()
void App::CreateJSONAnswer()
{
Request & req = *cur.request;
json_out_stream.Clear();
if( !req.return_info_only )
{
json_out_stream << L"{\n";
for(size_t i=1 ; i<req.out_streams.size() ; ++i)
{
json_out_stream << L"\"stream_" << i << L"\": \"";
JSONescape(json_out_stream, req.out_streams[i].Str());
json_out_stream << L"\",\n";
}
json_out_stream << L"\"info\": ";
}
if( req.info_serializer )
{
req.info_serializer->Serialize(req.info, json_out_stream, true);
}
else
{
json_out_stream << L"{}";
log << log1 << "App: Request::info_serializer not defined" << logend;
}
log << log3 << "App: sending JSON answer";
if( !req.return_info_only )
json_out_stream << L"}\n";
else
log << " (Request::info only)";
log << logend;
}
// !! zmienic na lepsza nazwe
void App::MakePage()
{
bool sent = false;
if( cur.request->page_generated || !cur.request->redirect_to.empty() || !cur.request->x_sendfile.empty() )
return;
@@ -419,7 +458,7 @@ bool sent = false;
{
if( cur.request->function == &functions.fun_cat )
{
cur.request->page << cur.request->item.content;
cur.request->out_streams[0] << cur.request->item.content; // !! CHECK ME is it ok?
sent = true;
}
else
@@ -436,12 +475,9 @@ bool sent = false;
}
if( cur.request->ajax_serializer )
if( cur.request->return_json )
{
log << log3 << "App: sending JSON" << logend;
std::wstring & ajax_content = cur.request->ajax.Add(L"content", L"");
ajax_content = cur.request->page.Str();
cur.request->ajax_serializer->Serialize(cur.request->ajax, cur.request->ajaxpage, true);
CreateJSONAnswer();
}
}
@@ -476,6 +512,9 @@ void App::Make()
return;
}
if( cur.request->ParamValue(L"reqtype") == L"json" )
cur.request->return_json = true;
if( cur.session->ip_ban && cur.session->ip_ban->IsIPBanned() )
{
PT::Date date(cur.session->ip_ban->expires);
@@ -525,11 +564,10 @@ void App::Make()
return;
}
if( !cur.request->ajax_serializer && cur.request->ParamValue(L"reqtype") == L"json")
if( !cur.request->info_serializer )
{
log << log3 << "App: using generic JSON serializer" << logend;
ajax_generic_serializer.Clear();
cur.request->ajax_serializer = &ajax_generic_serializer;
json_generic_serializer.Clear(); // !! IMPROVE ME add to the end of a request
cur.request->info_serializer = &json_generic_serializer;
}
plugin.Call(WINIX_CONTENT_MAKE);
@@ -728,6 +766,7 @@ void App::CheckKonqueror()
void App::PrepareSessionCookie()
{
if( !cur.session || cur.session->id==0 )
@@ -812,7 +851,7 @@ void App::SendHeadersStatic()
void App::SendHeaderContentType()
{
if( cur.request->ajax_serializer )
if( cur.request->return_json )
{
FCGX_PutS("Content-Type: application/json", fcgi_request.out);
}
@@ -967,7 +1006,7 @@ void App::FilterCompressSend(bool compressing, int compress_encoding, const std:
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);
if( config.html_filter && cur.request->use_html_filter && !raw && !cur.request->ajax_serializer )
if( config.html_filter && cur.request->use_html_filter && !raw && !cur.request->return_json )
{
TemplatesFunctions::html_filter.Filter(*source, clean_html);
AddDebugInfo(clean_html);
@@ -992,6 +1031,9 @@ void App::FilterCompressSend(bool compressing, int compress_encoding, const std:
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();
}
@@ -1098,10 +1140,10 @@ Error status = cur.request->status;
bool compressing;
int compress_encoding;
if( cur.request->ajax_serializer )
source = &cur.request->ajaxpage.Str();
if( cur.request->return_json )
source = &json_out_stream.Str();
else
source = &cur.request->page.Str();
source = &cur.request->out_streams[0].Str();
SelectCompression(source->length(), compressing, compress_encoding);
@@ -1158,14 +1200,12 @@ void App::SendData(const BinaryPage & page, FCGX_Stream * out)
void App::SendBinaryAnswer()
{
BinaryPage & source = cur.request->binary_page;
BinaryPage & compressed_page = cur.request->compressed_page;
BinaryPage & source = cur.request->out_bin_stream;
Header header = h_200;
Error status = cur.request->status;
bool compressing;
int compress_encoding;
SelectCompression(source.size(), compressing, compress_encoding);
if( status == WINIX_ERR_NO_ITEM || status == WINIX_ERR_NO_FUNCTION || status == WINIX_ERR_UNKNOWN_PARAM )
@@ -1182,8 +1222,10 @@ int compress_encoding;
{
if( compressing )
{
compress.Compressing(source, compressed_page, compress_encoding);
SendData(compressed_page, fcgi_request.out);
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();
}
else
{
@@ -1195,10 +1237,10 @@ int compress_encoding;
void App::SendAnswer()
{
if( cur.request->use_text_page )
SendTextAnswer();
else
if( cur.request->send_bin_stream )
SendBinaryAnswer();
else
SendTextAnswer();
}

View File

@@ -122,7 +122,9 @@ private:
std::string sendh_t, sendh_t2, sendh_t3;
std::string sendfilea, sendfile2a;
std::string send_data_buf;
PT::SpaceToJSON ajax_generic_serializer;
PT::SpaceToJSON json_generic_serializer;
TextStream<std::wstring> json_out_stream;
BinaryPage out_bin_stream_compressed;
bool CheckAccessFromPlugins();
void ProcessRequestThrow();
@@ -137,6 +139,7 @@ private:
void SaveSessionsIfNeeded(); // !! wywalic do menagera sesji??
void LogAccess();
void SendData(const BinaryPage & page, FCGX_Stream * out);
void CreateJSONAnswer();
void ReadRequest();
void SendTextAnswer();
@@ -156,6 +159,7 @@ private:
void CheckSSL();
void SetSubdomain();
void PrepareSessionCookie();
void AddDebugInfo(std::wstring & out);
void FilterCompressSend(bool compressing, int compress_encoding, const std::wstring & source_ref);

View File

@@ -1014,4 +1014,34 @@ void SetMinMax(IntType & val, IntType min_val, IntType max_val)
template<class Stream, class StringType>
void JSONescape(Stream & out, const StringType & str)
{
// !! IMPROVE ME (optimizing)
// it is better to not write one by one character
// but use write method insted
for(size_t i=0 ; i<str.size() ; ++i)
{
switch(str[i])
{
case 0: out << '\\'; out << '0'; break;
case '\r': out << '\\'; out << 'r'; break;
case '\n': out << '\\'; out << 'n'; break;
case '\t': out << '\\'; out << 't'; break;
case 0x08: out << '\\'; out << 'b'; break;
case 0x0c: out << '\\'; out << 'f'; break;
case '\\': out << '\\'; out << '\\'; break;
//case '/': out << '\\'; out << '/'; break; // slash doesn't have to be escaped
case '"': out << '\\'; out << '\"'; break;
default:
out << str[i];
}
}
}
#endif

View File

@@ -30,36 +30,17 @@ void Request::SetConfig(Config * pconfig)
}
void Request::ClearAjax()
void Request::ClearOutputStreams()
{
size_t i = ajax.spaces.size();
out_streams.resize(16); // !! IMPROVE ME add as a constant somewhere
while( i-- > 0 )
ajax.RemoveSpace(i);
ajax.table.clear();
PT::Space::TableSingle::iterator s = ajax.table_single.begin();
while( s != ajax.table_single.end() )
{
if( s->first != L"content" && s->first != L"http_status" )
{
ajax.table_single.erase(s++);
}
else
{
// small optimization when deleting
// the memory for "content" and "http_status" will be reused
s->second.clear();
++s;
}
}
for(size_t i=0 ; i<out_streams.size() ; ++i)
out_streams[i].Clear();
}
void Request::Clear()
{
// id is never 0
@@ -67,6 +48,7 @@ void Request::Clear()
++id;
RemovePostFileTmp(post_file_tab);
ClearOutputStreams();
post_tab.clear();
post_file_tab.clear();
@@ -76,8 +58,8 @@ void Request::Clear()
role = responder;
headers.Clear();
page.Clear();
ajaxpage.Clear();
debug.Clear();
page_generated = false;
@@ -117,12 +99,13 @@ void Request::Clear()
start_date.Clear();
subdomain.clear();
ClearAjax();
ajax_serializer = 0;
return_info_only = false;
info.Clear();
info_serializer = 0;
return_json = false;
binary_page.clear();
compressed_page.clear();
use_text_page = true;
out_bin_stream.clear();
send_bin_stream = false;
gen_trim_white = false;
gen_skip_new_line = false;

View File

@@ -44,20 +44,100 @@ struct Request
// headers, page and debug
//std::ostringstream headers, page, debug;
TextStream<std::string> headers;
HtmlTextStream page, debug;
TextStream<std::wstring> ajaxpage;
// !! IMPROVE ME change headers to some kind of a map, may PT::Space ?
TextStream<std::string> headers;
HtmlTextStream debug;
// binary page
BinaryPage binary_page;
// a compressed page ready to send to the client
BinaryPage compressed_page;
// winix can return either a text answer or a binary answer
// if send_bin_stream is true then the binary answer is sent (out_bin_stream)
// or if send_bin_stream is false then the text answer is sent
// default: false
//
//
//
// winix answer send to the client's browser
// |
// |
// depending on send_bin_stream
// -------------------------------------------------
// | |
// text answer binary answer
// | |
// depending on return_json sending out_bin_stream
// ------------------------------------
// | |
// normal request ajax request
// | |
// sending out_streams[0] depending on return_info_only
// ------------------------------------------------------
// | |
// generating JSON object from: generating JSON object only from info
// out_streams and info, e.g.: e.g.:
// { { info object serialized here }
// "stream_1": "some html content",
// "stream_2": "some other html content",
// "info": { info object serialized here }
// }
// note that out_streams[0] is not sent
// in JSON answers
//
//
bool send_bin_stream;
// -------------------------------------------------------------------------------------
// binary answer
//
// binary page sent to the client if send_bin_stream is true
BinaryPage out_bin_stream;
//
// -------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------
// text answer
//
// when returning the text answer we can either return the whole html page (normal requests)
// or a JSON object (for requests generated from AJAX)
// if return_json is false then we return the whole html page (which is in out_streams[0])
// if return_json is true we are creating an JSON object from out_streams
// (zero stream is ignored) and from info space (see above picture)
// (or just only from info if return_info_only is true)
// default: false
// return_json is set to true by App at the beginning of a request
// if reqtype:json parameter is present (in the url)
// note: return_json is only valid if send_bin_stream is false
bool return_json;
// main text output streams where the html otput is generated from ezc templates
// the zero stream (out_streams[0]) is used as the main stream
// to which the whole html page (with doctype, head, body) is generated
// the rest streams can be only used in ajax requests (send in JSON format to the client)
// in ezc templates you can use [ezc stream ...] keyword
// to switch between streams e.g. [ezc stream "0" "2"]
std::vector<HtmlTextStream> out_streams;
// if true the JSON object is generated only from info (out_streams are not used)
// default: false
bool return_info_only;
// additional info added when sending the JSON answer
PT::Space info;
// info serializer
// if not set then the json_generic_serializer from App will be used
// default: null (json_generic_serializer used)
PT::SpaceToJSON * info_serializer;
//
// -------------------------------------------------------------------------------------
// if true then either page or ajaxpage will be sent to the client
// if false then binary_page is sent
// default: true
bool use_text_page;
// if set to true then the standard template system will not be generated
// default: false
@@ -67,6 +147,10 @@ struct Request
// default: true
bool use_html_filter;
// raw parameters
PostTab post_tab;
PostFileTab post_file_tab;
@@ -157,15 +241,6 @@ struct Request
// subdomain = HTTP_HOST environment variable - config->base_url
std::wstring subdomain;
// used as a JSON output (when ajax_serializer is defined)
// it will be serialized and have at least:
// 'content' string - the whole html content
// 'http_status' integer - http status code (e.g. 200) !! FIXME this is not added at the moment
PT::Space ajax;
// if not null then the request will have a JSON as an output
PT::SpaceToJSON * ajax_serializer;
// if this variable is true then winix always return 200 OK header
// when the status would be 404 (not found) or 403 (permission denied)
// default: false
@@ -222,7 +297,7 @@ private:
// used in ParamValue() and PostVar() when there is no such a param
const std::wstring str_empty;
void ClearAjax();
void ClearOutputStreams();
};

View File

@@ -2,7 +2,7 @@
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2010-2012, Tomasz Sowa
* Copyright (c) 2010-2013, Tomasz Sowa
* All rights reserved.
*
*/
@@ -144,6 +144,30 @@ bool ssl = false;
}
void System::CreateItemLink(long parent_id, const std::wstring & url, const std::wstring & subdomain,
std::wstring & link, bool clear_str)
{
PutUrlProto(config->use_ssl, link, clear_str);
if( !subdomain.empty() )
{
link += subdomain;
link += '.';
}
link += config->base_url;
dirs.MakePath(parent_id, link, false); // !! IMPROVE ME may some kind of error checks here?
link += url;
}
void System::CreateItemLink(const Item & item, std::wstring & link, bool clear_str)
{
CreateItemLink(item.parent_id, item.url, cur->request->subdomain, link, clear_str);
}
// !! IMPROVE ME
// !! mozna zrobic jakas obsluge kiedy nie mozemy sie redirectnac, np gdy wystapil blad
// !! moze zwracac jakas wartosc?

View File

@@ -2,7 +2,7 @@
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2010-2012, Tomasz Sowa
* Copyright (c) 2010-2013, Tomasz Sowa
* All rights reserved.
*
*/
@@ -171,6 +171,13 @@ public:
// reloading time zones
void ReadTimeZones();
void CreateItemLink(long parent_id, const std::wstring & url, const std::wstring & subdomain,
std::wstring & link, bool clear_str = true);
void CreateItemLink(const Item & item, std::wstring & link, bool clear_str = true);
private:
Cur * cur;

View File

@@ -13,7 +13,7 @@
#define WINIX_VER_MAJOR 0
#define WINIX_VER_MINOR 5
#define WINIX_VER_REVISION 5
#define WINIX_VER_REVISION 6
#endif