From f7e4f73e95bbafa479e28462c1412c84e63cb519 Mon Sep 17 00:00:00 2001 From: cxl Date: Sun, 5 Aug 2012 16:41:29 +0000 Subject: [PATCH] .docs git-svn-id: svn://ultimatepp.org/upp/trunk@5265 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/Skylark/Dispatch.cpp | 816 +++++++++++++------------- uppsrc/Skylark/Http.h | 7 +- uppsrc/Skylark/src.tpp/Http$en-us.tpp | 226 ++++--- 3 files changed, 549 insertions(+), 500 deletions(-) diff --git a/uppsrc/Skylark/Dispatch.cpp b/uppsrc/Skylark/Dispatch.cpp index 43f446c6e..b167134e1 100644 --- a/uppsrc/Skylark/Dispatch.cpp +++ b/uppsrc/Skylark/Dispatch.cpp @@ -1,409 +1,409 @@ -#include "Skylark.h" - -#define LLOG(x) //DLOG(x) -#define LDUMP(x) //DDUMP(x) -#define LDUMPC(x) //DDUMPC(x) -#define LDUMPM(x) //DDUMPM(x) -#define LTIMING(x) //RTIMING(x) - -namespace Upp { - -enum { DISPATCH_VARARGS = -1 }; - -struct DispatchNode : Moveable { - VectorMap subnode; - void (*view)(Http&); - int argpos; - int method; - bool post_raw; - String id; - - enum { GET, POST }; - - DispatchNode() { view = NULL; argpos = Null; method = GET; post_raw = false; } -}; - -static Vector& sDispatchMap() -{ - static Vector x; - return x; -} - -static VectorMap >& sLinkMap() -{ - static VectorMap > x; - return x; -} - -static Index& sViewIndex() -{ - static Index x; - return x; -} - -void DumpDispatchMap() -{ - Vector& DispatchMap = sDispatchMap(); - for(int i = 0; i < DispatchMap.GetCount(); i++) { - LLOG("-------------"); - String sub; - for(int j = 0; j < DispatchMap[i].subnode.GetCount(); j++) - sub << DispatchMap[i].subnode.GetKey(j) << "->" << DispatchMap[i].subnode[j] << ", "; - LLOG(i << " " << (bool)DispatchMap[i].view << ": " << sub); - } -} - -Vector *GetUrlViewLinkParts(const String& id) -{ - int q = sLinkMap().Find(id); - if(q < 0) - return NULL; - return &sLinkMap()[q]; -} - -String MakeLink(void (*view)(Http&), const Vector& arg) -{ - int q = sViewIndex().Find((uintptr_t)view); - if(q < 0) - throw Exc("Invalid view"); - if(q < 0) - return String(); - StringBuffer out; - MakeLink(out, sLinkMap()[q], arg); - return out; -} - -void RegisterView0(void (*view)(Http&), const char *id, String path, bool primary) -{ - LLOG("RegisterView " << path); - Vector& linkpart = sLinkMap().GetAdd(id); - sViewIndex().FindAdd((uintptr_t)view); - Vector& DispatchMap = sDispatchMap(); - int method = DispatchNode::GET; - bool post_raw = false; - int q = path.Find(':'); - if(q >= 0) { - if(path.Mid(q + 1) == "POST") - method = DispatchNode::POST; - if(path.Mid(q + 1) == "POST_RAW") { - method = DispatchNode::POST; - post_raw = true; - } - path = path.Mid(0, q); - } - Vector h = Split(path, '/'); - if(DispatchMap.GetCount() == 0) - DispatchMap.Add(); - q = 0; - int linkargpos = 0; - for(int i = 0; i < h.GetCount(); i++) { - String s = h[i]; - LLOG(" Node " << h[i]); - DispatchNode& n = DispatchMap[q]; - if(*s == '*') { - int argpos = Null; - if(IsDigit(s[1])) - linkargpos = argpos = minmax(atoi(~s + 1), 0, 30); - else - if(s[1] == '*') - argpos = DISPATCH_VARARGS; - q = DispatchMap.GetCount(); - LLOG(" Adding arg " << argpos << ": " << q); - n.subnode.Add(Null, q); - DispatchMap.Add(); - DispatchMap[q].argpos = argpos; - if(primary) - linkpart.Add(String(linkargpos++, 1)); - } - else { - if(primary) - linkpart.Add(s); - q = n.subnode.Get(s, -1); - if(q < 0) { - q = DispatchMap.GetCount(); - LLOG(" Adding " << s << ": " << q); - n.subnode.Add(s, q); - DispatchMap.Add(); - } - } - } - ASSERT_(!DispatchMap[q].view, "duplicate view " + String(path)); - DispatchMap[q].view = view; - DispatchMap[q].method = method; - DispatchMap[q].id = id; - DispatchMap[q].post_raw = post_raw; -// DumpDispatchMap(); -} - -struct ViewData { - void (*view)(Http&); - String id; - String path; -}; - -static Array& sViewData() -{ - static Array x; - return x; -} - -void RegisterHandler(void (*view)(Http&), const char *id, const char *path) -{ - Array& v = sViewData(); - ViewData& w = v.Add(); - w.view = view; - w.id = id; - w.path = path; -} - -void SkylarkApp::FinalizeViews() -{ - Array& w = sViewData(); - for(int i = 0; i < w.GetCount(); i++) { - const ViewData& v = w[i]; - ASSERT_(sViewIndex().Find((uintptr_t)v.view) < 0, "duplicate view function registration " + String(v.id)); - String p = v.path; - if(*p == '/') - p = p.Mid(1); - else - p = root + '/' + p; - Vector h = Split(ReplaceVars(p, view_var, '$'), ';'); - for(int i = 0; i < h.GetCount(); i++) - RegisterView0(v.view, v.id, h[i], i == 0); - } - w.Clear(); -} - -struct BestDispatch { - void (*view)(Http&); - int matched_parts; - int matched_params; - Vector& arg; - String id; - bool post_raw; - - BestDispatch(Vector& arg) : arg(arg) { matched_parts = -1; matched_params = 0; view = NULL; post_raw = false; } -}; - -void GetBestDispatch(int method, - const Vector& part, int ii, const DispatchNode& n, Vector& arg, - BestDispatch& bd, int matched_parts, int matched_params) -{ - Vector& DispatchMap = sDispatchMap(); - if(ii >= part.GetCount()) { - if(n.view && n.method == method && - (matched_parts > bd.matched_parts || - matched_parts == bd.matched_parts && matched_params > bd.matched_params)) { - LLOG("Matched " << n.id << " parts " << matched_parts << " params " << matched_params); - bd.arg <<= arg; - bd.view = n.view; - bd.matched_parts = matched_parts; - bd.id = n.id; - bd.post_raw = n.post_raw; - } - if(!bd.view) { - int q = n.subnode.Find(String()); - while(q >= 0) { - const DispatchNode& an = DispatchMap[n.subnode[q]]; - if(an.argpos == DISPATCH_VARARGS && an.view && an.method == method) { - bd.view = an.view; - bd.id = n.id; - bd.arg.Clear(); - break; - } - q = n.subnode.FindNext(q); - } - } - return; - } - int qq = n.subnode.Get(part[ii], -1); - if(qq >= 0) - GetBestDispatch(method, part, ii + 1, DispatchMap[qq], arg, bd, matched_parts + 1, matched_params); - int q = n.subnode.Find(String()); - while(q >= 0) { - int qq = n.subnode[q]; - int ac = arg.GetCount(); - const DispatchNode& an = DispatchMap[qq]; - int apos = an.argpos; - LLOG(" *" << qq << " apos: " << apos); - if(apos == DISPATCH_VARARGS) { - if(an.view && an.method == method && - (matched_parts > bd.matched_parts || matched_parts == bd.matched_parts && matched_params > bd.matched_params)) { - LLOG("Matched VARARGS " << an.id << " parts " << matched_parts << " params " << matched_params); - bd.arg <<= arg; - bd.arg.Append(part, ii, part.GetCount() - ii); - bd.view = an.view; - bd.matched_parts = matched_parts; - bd.id = an.id; - } - } - else { - String pv; - if(IsNull(apos)) - arg.Add(part[ii]); - else { - String& at = arg.At(apos); - pv = at; - at = part[ii]; - } - GetBestDispatch(method, part, ii + 1, an, arg, bd, matched_parts, matched_params + 1); - if(!IsNull(apos)) - arg[apos] = pv; - } - arg.SetCount(ac); - q = n.subnode.FindNext(q); - } -} - -void Http::Dispatch(TcpSocket& socket) -{ - const Vector& DispatchMap = sDispatchMap(); - if(hdr.Read(socket)) { - int len = GetLength(); - content = socket.GetAll(len); - LLOG("--------------------------------------------"); - SKYLARKLOG(hdr.GetMethod() << " " << hdr.GetURI()); - LDUMP(content); - String r; - var.Clear(); - arg.Clear(); - LTIMING("Request processing"); - request_content_type = GetHeader("content-type"); - String rc = ToLower(request_content_type); - bool post = hdr.GetMethod() == "POST"; - if(post) - if(rc.StartsWith("application/x-www-form-urlencoded")) - ParseRequest(content); - else - if(rc.StartsWith("multipart/")) - ReadMultiPart(content); - String uri = hdr.GetURI(); - int q = uri.Find('?'); - if(q >= 0) { - if(!post) - ParseRequest(~uri + q + 1); - uri.Trim(q); - } - for(int i = hdr.fields.Find("cookie"); i >= 0; i = hdr.fields.FindNext(i)) { - const String& h = hdr.fields[i]; - int q = 0; - for(;;) { - int qq = h.Find('=', q); - if(qq < 0) - break; - String id = ToLower(TrimBoth(h.Mid(q, qq - q))); - qq++; - q = h.Find(';', qq); - if(q < 0) { - var.Add('@' + id, UrlDecode(h.Mid(qq))); - break; - } - var.Add('@' + id, UrlDecode(h.Mid(qq, q - qq))); - q++; - } - } - var.GetAdd("static") = app.static_dir; - var.GetAdd(".__identity__"); // To make StdLib.icpp GetIndentity work without changing preset stack positions - LDUMPM(var); - Vector part = Split(uri, '/'); - for(int i = 0; i < part.GetCount(); i++) - part[i] = UrlDecode(part[i]); - LDUMPC(part); - Vector a; - BestDispatch bd(arg); - if(DispatchMap.GetCount()) - GetBestDispatch(post ? DispatchNode::POST : DispatchNode::GET, part, 0, DispatchMap[0], a, bd, 0, 0); - LDUMPC(arg); - response.Clear(); - if(bd.view) { - try { - if(SQL.IsOpen()) - SQL.Begin(); - LoadSession(); - session_dirty = false; - if(post && !bd.post_raw) { - String id = Nvl((*this)["__post_identity__"], (*this)["__js_identity__"]); - if(id != (*this)[".__identity__"]) - throw AuthExc("identity error"); - } - lang = Nvl(Int(".__lang__"), LNG_ENGLISH); - Upp::SetLanguage(lang); - var.GetAdd(".__lang__") = lang; - var.GetAdd(".language") = ToLower(LNGAsText(lang)); - viewid = bd.id; - LDUMP(viewid); - (*bd.view)(*this); - if(session_dirty) - SaveSession(); - if(SQL.IsOpen()) - SQL.Commit(); - } - catch(SqlExc e) { - if(SQL.IsOpen()) - SQL.Rollback(); - response << "Internal server error
" - << "SQL ERROR: " << e; - code = 500; - code_text = "Internal server error"; - app.SqlError(*this); - } - catch(AuthExc e) { - if(SQL.IsOpen()) - SQL.Rollback(); - response << e; - code = 403; - code_text = "Unauthorized"; - app.Unauthorized(*this); - } - catch(BadRequestExc e) { - if(SQL.IsOpen()) - SQL.Rollback(); - response << "Bad request"; - code = 400; - code_text = "Bad request"; - app.Unauthorized(*this); - } - catch(Exc e) { - if(SQL.IsOpen()) - SQL.Rollback(); - response << "Internal server error
" - << e; - code = 500; - code_text = "Internal server error"; - app.InternalError(*this); - } - } - else { - response << "Page not found"; - code = 404; - code_text = "Not found"; - app.NotFound(*this); - } - r.Clear(); - SKYLARKLOG("=== Response: " << code << ' ' << code_text); - if(redirect.GetCount()) { - SKYLARKLOG("Redirect to: " << redirect); - r << "HTTP/1.1 " << code << " Found\r\n"; - r << "Location: " << redirect << "\r\n"; - for(int i = 0; i < cookies.GetCount(); i++) - r << cookies[i]; - } - else { - r << - "HTTP/1.0 " << code << ' ' << code_text << "\r\n" - "Date: " << WwwFormat(GetUtcTime()) << "\r\n" - "Server: U++\r\n" - "Content-Length: " << response.GetCount() << "\r\n" - "Connection: close\r\n" - "Cache-Control: no-cache\r\n" - "Content-Type: " << content_type << "\r\n"; - for(int i = 0; i < cookies.GetCount(); i++) - r << cookies[i]; - r << "\r\n"; - } - socket.PutAll(r); - socket.PutAll(response); - } -} - +#include "Skylark.h" + +#define LLOG(x) //DLOG(x) +#define LDUMP(x) //DDUMP(x) +#define LDUMPC(x) //DDUMPC(x) +#define LDUMPM(x) //DDUMPM(x) +#define LTIMING(x) //RTIMING(x) + +namespace Upp { + +enum { DISPATCH_VARARGS = -1 }; + +struct DispatchNode : Moveable { + VectorMap subnode; + void (*view)(Http&); + int argpos; + int method; + bool post_raw; + String id; + + enum { GET, POST }; + + DispatchNode() { view = NULL; argpos = Null; method = GET; post_raw = false; } +}; + +static Vector& sDispatchMap() +{ + static Vector x; + return x; +} + +static VectorMap >& sLinkMap() +{ + static VectorMap > x; + return x; +} + +static Index& sViewIndex() +{ + static Index x; + return x; +} + +void DumpDispatchMap() +{ + Vector& DispatchMap = sDispatchMap(); + for(int i = 0; i < DispatchMap.GetCount(); i++) { + LLOG("-------------"); + String sub; + for(int j = 0; j < DispatchMap[i].subnode.GetCount(); j++) + sub << DispatchMap[i].subnode.GetKey(j) << "->" << DispatchMap[i].subnode[j] << ", "; + LLOG(i << " " << (bool)DispatchMap[i].view << ": " << sub); + } +} + +Vector *GetUrlViewLinkParts(const String& id) +{ + int q = sLinkMap().Find(id); + if(q < 0) + return NULL; + return &sLinkMap()[q]; +} + +String MakeLink(void (*view)(Http&), const Vector& arg) +{ + int q = sViewIndex().Find((uintptr_t)view); + if(q < 0) + throw Exc("Invalid view"); + if(q < 0) + return String(); + StringBuffer out; + MakeLink(out, sLinkMap()[q], arg); + return out; +} + +void RegisterView0(void (*view)(Http&), const char *id, String path, bool primary) +{ + LLOG("RegisterView " << path); + Vector& linkpart = sLinkMap().GetAdd(id); + sViewIndex().FindAdd((uintptr_t)view); + Vector& DispatchMap = sDispatchMap(); + int method = DispatchNode::GET; + bool post_raw = false; + int q = path.Find(':'); + if(q >= 0) { + if(path.Mid(q + 1) == "POST") + method = DispatchNode::POST; + if(path.Mid(q + 1) == "POST_RAW") { + method = DispatchNode::POST; + post_raw = true; + } + path = path.Mid(0, q); + } + Vector h = Split(path, '/'); + if(DispatchMap.GetCount() == 0) + DispatchMap.Add(); + q = 0; + int linkargpos = 0; + for(int i = 0; i < h.GetCount(); i++) { + String s = h[i]; + LLOG(" Node " << h[i]); + DispatchNode& n = DispatchMap[q]; + if(*s == '*') { + int argpos = Null; + if(IsDigit(s[1])) + linkargpos = argpos = minmax(atoi(~s + 1), 0, 30); + else + if(s[1] == '*') + argpos = DISPATCH_VARARGS; + q = DispatchMap.GetCount(); + LLOG(" Adding arg " << argpos << ": " << q); + n.subnode.Add(Null, q); + DispatchMap.Add(); + DispatchMap[q].argpos = argpos; + if(primary) + linkpart.Add(String(linkargpos++, 1)); + } + else { + if(primary) + linkpart.Add(s); + q = n.subnode.Get(s, -1); + if(q < 0) { + q = DispatchMap.GetCount(); + LLOG(" Adding " << s << ": " << q); + n.subnode.Add(s, q); + DispatchMap.Add(); + } + } + } + ASSERT_(!DispatchMap[q].view, "duplicate view " + String(path)); + DispatchMap[q].view = view; + DispatchMap[q].method = method; + DispatchMap[q].id = id; + DispatchMap[q].post_raw = post_raw; +// DumpDispatchMap(); +} + +struct ViewData { + void (*view)(Http&); + String id; + String path; +}; + +static Array& sViewData() +{ + static Array x; + return x; +} + +void RegisterHandler(void (*view)(Http&), const char *id, const char *path) +{ + Array& v = sViewData(); + ViewData& w = v.Add(); + w.view = view; + w.id = id; + w.path = path; +} + +void SkylarkApp::FinalizeViews() +{ + Array& w = sViewData(); + for(int i = 0; i < w.GetCount(); i++) { + const ViewData& v = w[i]; + ASSERT_(sViewIndex().Find((uintptr_t)v.view) < 0, "duplicate view function registration " + String(v.id)); + String p = v.path; + if(*p == '/') + p = p.Mid(1); + else + p = root + '/' + p; + Vector h = Split(ReplaceVars(p, view_var, '$'), ';'); + for(int i = 0; i < h.GetCount(); i++) + RegisterView0(v.view, v.id, h[i], i == 0); + } + w.Clear(); +} + +struct BestDispatch { + void (*view)(Http&); + int matched_parts; + int matched_params; + Vector& arg; + String id; + bool post_raw; + + BestDispatch(Vector& arg) : arg(arg) { matched_parts = -1; matched_params = 0; view = NULL; post_raw = false; } +}; + +void GetBestDispatch(int method, + const Vector& part, int ii, const DispatchNode& n, Vector& arg, + BestDispatch& bd, int matched_parts, int matched_params) +{ + Vector& DispatchMap = sDispatchMap(); + if(ii >= part.GetCount()) { + if(n.view && n.method == method && + (matched_parts > bd.matched_parts || + matched_parts == bd.matched_parts && matched_params > bd.matched_params)) { + LLOG("Matched " << n.id << " parts " << matched_parts << " params " << matched_params); + bd.arg <<= arg; + bd.view = n.view; + bd.matched_parts = matched_parts; + bd.id = n.id; + bd.post_raw = n.post_raw; + } + if(!bd.view) { + int q = n.subnode.Find(String()); + while(q >= 0) { + const DispatchNode& an = DispatchMap[n.subnode[q]]; + if(an.argpos == DISPATCH_VARARGS && an.view && an.method == method) { + bd.view = an.view; + bd.id = n.id; + bd.arg.Clear(); + break; + } + q = n.subnode.FindNext(q); + } + } + return; + } + int qq = n.subnode.Get(part[ii], -1); + if(qq >= 0) + GetBestDispatch(method, part, ii + 1, DispatchMap[qq], arg, bd, matched_parts + 1, matched_params); + int q = n.subnode.Find(String()); + while(q >= 0) { + int qq = n.subnode[q]; + int ac = arg.GetCount(); + const DispatchNode& an = DispatchMap[qq]; + int apos = an.argpos; + LLOG(" *" << qq << " apos: " << apos); + if(apos == DISPATCH_VARARGS) { + if(an.view && an.method == method && + (matched_parts > bd.matched_parts || matched_parts == bd.matched_parts && matched_params > bd.matched_params)) { + LLOG("Matched VARARGS " << an.id << " parts " << matched_parts << " params " << matched_params); + bd.arg <<= arg; + bd.arg.Append(part, ii, part.GetCount() - ii); + bd.view = an.view; + bd.matched_parts = matched_parts; + bd.id = an.id; + } + } + else { + String pv; + if(IsNull(apos)) + arg.Add(part[ii]); + else { + String& at = arg.At(apos); + pv = at; + at = part[ii]; + } + GetBestDispatch(method, part, ii + 1, an, arg, bd, matched_parts, matched_params + 1); + if(!IsNull(apos)) + arg[apos] = pv; + } + arg.SetCount(ac); + q = n.subnode.FindNext(q); + } +} + +void Http::Dispatch(TcpSocket& socket) +{ + const Vector& DispatchMap = sDispatchMap(); + if(hdr.Read(socket)) { + int len = GetLength(); + content = socket.GetAll(len); + LLOG("--------------------------------------------"); + SKYLARKLOG(hdr.GetMethod() << " " << hdr.GetURI()); + LDUMP(content); + String r; + var.Clear(); + arg.Clear(); + LTIMING("Request processing"); + request_content_type = GetHeader("content-type"); + String rc = ToLower(request_content_type); + bool post = hdr.GetMethod() == "POST"; + if(post) + if(rc.StartsWith("application/x-www-form-urlencoded")) + ParseRequest(content); + else + if(rc.StartsWith("multipart/")) + ReadMultiPart(content); + String uri = hdr.GetURI(); + int q = uri.Find('?'); + if(q >= 0) { + if(!post) + ParseRequest(~uri + q + 1); + uri.Trim(q); + } + for(int i = hdr.fields.Find("cookie"); i >= 0; i = hdr.fields.FindNext(i)) { + const String& h = hdr.fields[i]; + int q = 0; + for(;;) { + int qq = h.Find('=', q); + if(qq < 0) + break; + String id = ToLower(TrimBoth(h.Mid(q, qq - q))); + qq++; + q = h.Find(';', qq); + if(q < 0) { + var.Add('@' + id, UrlDecode(h.Mid(qq))); + break; + } + var.Add('@' + id, UrlDecode(h.Mid(qq, q - qq))); + q++; + } + } + var.GetAdd("static") = app.static_dir; + var.GetAdd(".__identity__"); // To make StdLib.icpp GetIndentity work without changing preset stack positions + LDUMPM(var); + Vector part = Split(uri, '/'); + for(int i = 0; i < part.GetCount(); i++) + part[i] = UrlDecode(part[i]); + LDUMPC(part); + Vector a; + BestDispatch bd(arg); + if(DispatchMap.GetCount()) + GetBestDispatch(post ? DispatchNode::POST : DispatchNode::GET, part, 0, DispatchMap[0], a, bd, 0, 0); + LDUMPC(arg); + response.Clear(); + if(bd.view) { + try { + if(SQL.IsOpen()) + SQL.Begin(); + LoadSession(); + session_dirty = false; + if(post && !bd.post_raw) { + String id = Nvl((*this)["__post_identity__"], (*this)["__js_identity__"]); + if(id != (*this)[".__identity__"]) + throw AuthExc("identity error"); + } + lang = Nvl(Int(".__lang__"), LNG_ENGLISH); + Upp::SetLanguage(lang); + var.GetAdd(".__lang__") = lang; + var.GetAdd(".language") = ToLower(LNGAsText(lang)); + handlerid = bd.id; + LDUMP(viewid); + (*bd.view)(*this); + if(session_dirty) + SaveSession(); + if(SQL.IsOpen()) + SQL.Commit(); + } + catch(SqlExc e) { + if(SQL.IsOpen()) + SQL.Rollback(); + response << "Internal server error
" + << "SQL ERROR: " << e; + code = 500; + code_text = "Internal server error"; + app.SqlError(*this); + } + catch(AuthExc e) { + if(SQL.IsOpen()) + SQL.Rollback(); + response << e; + code = 403; + code_text = "Unauthorized"; + app.Unauthorized(*this); + } + catch(BadRequestExc e) { + if(SQL.IsOpen()) + SQL.Rollback(); + response << "Bad request"; + code = 400; + code_text = "Bad request"; + app.Unauthorized(*this); + } + catch(Exc e) { + if(SQL.IsOpen()) + SQL.Rollback(); + response << "Internal server error
" + << e; + code = 500; + code_text = "Internal server error"; + app.InternalError(*this); + } + } + else { + response << "Page not found"; + code = 404; + code_text = "Not found"; + app.NotFound(*this); + } + r.Clear(); + SKYLARKLOG("=== Response: " << code << ' ' << code_text); + if(redirect.GetCount()) { + SKYLARKLOG("Redirect to: " << redirect); + r << "HTTP/1.1 " << code << " Found\r\n"; + r << "Location: " << redirect << "\r\n"; + for(int i = 0; i < cookies.GetCount(); i++) + r << cookies[i]; + } + else { + r << + "HTTP/1.0 " << code << ' ' << code_text << "\r\n" + "Date: " << WwwFormat(GetUtcTime()) << "\r\n" + "Server: U++\r\n" + "Content-Length: " << response.GetCount() << "\r\n" + "Connection: close\r\n" + "Cache-Control: no-cache\r\n" + "Content-Type: " << content_type << "\r\n"; + for(int i = 0; i < cookies.GetCount(); i++) + r << cookies[i]; + r << "\r\n"; + } + socket.PutAll(r); + socket.PutAll(response); + } +} + }; \ No newline at end of file diff --git a/uppsrc/Skylark/Http.h b/uppsrc/Skylark/Http.h index d7fba999b..035fde8ac 100644 --- a/uppsrc/Skylark/Http.h +++ b/uppsrc/Skylark/Http.h @@ -41,7 +41,7 @@ class Http : public Renderer { HttpHeader hdr; String content; - String viewid; + String handlerid; Vector arg; String session_id; @@ -82,7 +82,7 @@ public: String GetHeader(const char *s) const { return hdr[s]; } int GetLength() const { return atoi(GetHeader("content-length")); } - String GetViewId() const { return viewid; } + String GetHandlerId() const { return viewid; } Value operator[](const char *id) const { return Renderer::operator[](id); } int Int(const char *id) const; @@ -106,9 +106,10 @@ public: Http& ClearSession(); Http& SessionSet(const char *id, const Value& value); + Http& NewSessionId(); Http& NewIdentity() { SessionSet("__identity__", Null); return *this; } - Http& NewSessionId(); + Http& SetLanguage(int lang); Http& Response(int code_, const String& ctext) { code = code_; code_text = ctext; return *this; } diff --git a/uppsrc/Skylark/src.tpp/Http$en-us.tpp b/uppsrc/Skylark/src.tpp/Http$en-us.tpp index 693dc1d1f..cd1739cf0 100644 --- a/uppsrc/Skylark/src.tpp/Http$en-us.tpp +++ b/uppsrc/Skylark/src.tpp/Http$en-us.tpp @@ -1,4 +1,4 @@ -topic ""; +topic "Http"; [2 $$0,0#00000000000000000000000000000000:Default] [i448;a25;kKO9;2 $$1,0#37138531426314131252341829483380:class] [l288;2 $$2,2#27521748481378242620020725143825:desc] @@ -10,134 +10,163 @@ topic ""; [i448;b42;O9;2 $$8,8#61672508125594000341940100500538:tparam] [b42;2 $$9,9#13035079074754324216151401829390:normal] [{_}%EN-US -[ {{10000@(113.42.0) [s0; [*@7;4 Title]]}}&] +[ {{10000@(113.42.0) [s0; [*@7;4 Http]]}}&] [s0;%- &] [s1;:Http`:`:class:%- [@(0.0.255)3 class][3 _][*3 Http][3 _:_][@(0.0.255)3 public][3 _][*@3;3 Render er]&] +[s2; Http is the reference parameter passed to Skylark handlers. +It provides data associated with request, like POST or GET form +values, session variables or cookie values, and is used to store +any `'output`' values like response fields, cookies, new values +of session variables..&] [s2; &] [ {{10000F(128)G(128)@1 [s0; [* Public Method List]]}}&] -[s4;%- &] +[s3;%- &] [s5;:Http`:`:operator`(`)`(const char`*`,const Value`&`):%- [_^Http^ Http][@(0.0.255) `&]_ [* operator()]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 id], [@(0.0.255) const]_[_^Value^ V alue][@(0.0.255) `&]_[*@3 v])&] [s2; Calls Renderer`::operator([%-*@3 id] , [%-*@3 v]) to set the value -of variable from shared variable space. Return `*this.&] +of shared space variable. Returns `*this.&] [s3; &] [s4; &] [s5;:Http`:`:operator`(`)`(const ValueMap`&`):%- [@(0.0.255) virtual] [_^Http^ Http][@(0.0.255) `&]_[* operator()]([@(0.0.255) const]_[_^ValueMap^ ValueMap][@(0.0.255) `& ]_[*@3 map])&] -[s2; Calls Renderer`::operator([%-*@3 map]) to set the values of variables -from shared variable space based on key`-value pairs of [%-*@3 map]. -Return `*this.&] +[s2; Calls Renderer`::operator([%-*@3 map]) to set the values of shared +space variables based on key`-value pairs of [%-*@3 map]. Returns +`*this.&] [s3; &] [s4; &] [s5;:Http`:`:operator`(`)`(const char`*`,void`(`*`)`(Http`&`)`):%- [_^Http^ Http][@(0.0.255) `& -]_[* operator()]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 id], [@(0.0.255) void]_(`*[*@3 v -iew])([_^Http^ Http][@(0.0.255) `&]))&] -[s2; Calls Render [%-*@3 id] [%-*@3 view] .&] +]_[* operator()]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 id], [@(0.0.255) void]_(`*[*@3 h +andler])([_^Http^ Http][@(0.0.255) `&]))&] +[s2; Calls Renderer`::operator([%-*@3 id], [%-*@3 handler]) to set the +value of shared space variable to url link. Returns `*this.&] [s3; &] [s4; &] [s5;:Http`:`:operator`(`)`(const char`*`,void`(`*`)`(Http`&`)`,const Value`&`):%- [@(0.0.255) v irtual] [_^Http^ Http][@(0.0.255) `&]_[* operator()]([@(0.0.255) const]_[@(0.0.255) char]_`* -[*@3 id], [@(0.0.255) void]_(`*[*@3 view])([_^Http^ Http][@(0.0.255) `&]), +[*@3 id], [@(0.0.255) void]_(`*[*@3 handler])([_^Http^ Http][@(0.0.255) `&]), [@(0.0.255) const]_Value[@(0.0.255) `&]_[*@3 arg1])&] -[s2; [%-*@3 id] [%-*@3 view] [%-*@3 arg1] .&] +[s2; Calls Renderer`::operator([%-*@3 id], [%-*@3 handler], [%-*@3 arg1]) +to set the value of shared space variable to url link with one +url argument. Returns `*this.&] [s3; &] [s4; &] [s5;:Http`:`:operator`(`)`(const char`*`,void`(`*`)`(Http`&`)`,const Value`&`,const Value`&`):%- [@(0.0.255) v irtual] [_^Http^ Http][@(0.0.255) `&]_[* operator()]([@(0.0.255) const]_[@(0.0.255) char]_`* -[*@3 id], [@(0.0.255) void]_(`*[*@3 view])([_^Http^ Http][@(0.0.255) `&]), +[*@3 id], [@(0.0.255) void]_(`*[*@3 handler])([_^Http^ Http][@(0.0.255) `&]), [@(0.0.255) const]_Value[@(0.0.255) `&]_[*@3 arg1], [@(0.0.255) const]_Value[@(0.0.255) `&]_ [*@3 arg2])&] -[s2; [%-*@3 id] [%-*@3 view] [%-*@3 arg1] [%-*@3 arg2] .&] +[s2; Calls Renderer`::operator([%-*@3 id], [%-*@3 handler], [%-*@3 arg1], +[%-*@3 arg2]) to set the value of shared space variable to url +link with two url arguments. Returns `*this.&] [s3; &] [s4; &] [s5;:Http`:`:operator`(`)`(const Sql`&`):%- [_^Http^ Http][@(0.0.255) `&]_[* operator()]([@(0.0.255) c onst]_[_^Sql^ Sql][@(0.0.255) `&]_[*@3 sql])&] -[s2; [%-*@3 sql] .&] +[s2; Calls Renderer`::operator([%-*@3 sql]) to set the values of shared +space variables based on column`-name/value pairs of current +row fetched in [%-*@3 sql]. Returns `*this.&] [s3; &] [s4; &] [s5;:Http`:`:operator`(`)`(Fields`):%- [_^Http^ Http][@(0.0.255) `&]_[* operator()]([_^Fields^ F ields]_[*@3 rec])&] -[s2; [%-*@3 rec] .&] +[s2; Calls Renderer`::operator([%-*@3 rec]) to set the values of shared +space variables based on column`-name/value pairs of [%-*@3 rec] +fields. Returns `*this.&] [s3; &] [s4; &] [s5;:Http`:`:operator`(`)`(const SqlSelect`&`):%- [_^Http^ Http][@(0.0.255) `&]_[* operator ()]([@(0.0.255) const]_[_^SqlSelect^ SqlSelect][@(0.0.255) `&]_[*@3 row`_sel])&] -[s2; [%-*@3 row`_sel] .&] +[s2; Calls Renderer`::operator([%-*@3 row`_sel]) to set the values of +shared space variables based on column`-name/value pairs of single +row fetched from database using [%-*@3 row`_sel]. Returns `*this.&] [s3; &] [s4; &] [s5;:Http`:`:operator`(`)`(const char`*`,const SqlSelect`&`):%- [_^Http^ Http][@(0.0.255) `& ]_[* operator()]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 id], [@(0.0.255) const]_[_^SqlSelect^ S qlSelect][@(0.0.255) `&]_[*@3 sel])&] -[s2; [%-*@3 id] [%-*@3 sel] .&] +[s2; Calls Renderer`::operator([%-*@3 id], [%-*@3 sel]) to set the value +of shared space variable [%-*@3 id] to the complete result set +of [%-*@3 sel] represented as ValueArray of ValueMaps. Returns +`*this.&] [s3; &] [s4; &] -[s5;:Http`:`:Render`(const char`*`,const String`&`):%- [@(0.0.255) virtual] -[_^Http^ Http][@(0.0.255) `&]_[* Render]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 id], -[@(0.0.255) const]_[_^String^ String][@(0.0.255) `&]_[*@3 template`_name])&] -[s2; [%-*@3 id] [%-*@3 template`_name] .&] +[s5;:Http`:`:Render`(const char`*`,const String`&`):%- [_^Http^ Http][@(0.0.255) `&]_[* Ren +der]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 id], [@(0.0.255) const]_[_^String^ String][@(0.0.255) `& +]_[*@3 template`_name])&] +[s2; Calls Renderer`::Render([%-*@3 id], [%-*@3 template`_name]) to render +witz template as RawHtmlText into shared space variable [%-*@3 id]. +Returns `*this.&] [s3; &] [s4; &] -[s5;:Http`:`:Render`(const String`&`):%- [@(0.0.255) virtual] [_^Value^ Value]_[* Render]([@(0.0.255) c -onst]_[_^String^ String][@(0.0.255) `&]_[*@3 template`_name])&] -[s2; [%-*@3 template`_name] .&] +[s5;:Http`:`:Render`(const String`&`):%- [_^Value^ Value]_[* Render]([@(0.0.255) const]_[_^String^ S +tring][@(0.0.255) `&]_[*@3 template`_name])&] +[s2; Calls Renderer`::Render([%-*@3 template`_name]) to render witz +template and return the result as RawHtmlText.&] [s3; &] [s4; &] [s5;:Http`:`:GetHeader`(const char`*`)const:%- [_^String^ String]_[* GetHeader]([@(0.0.255) c onst]_[@(0.0.255) char]_`*[*@3 s])_[@(0.0.255) const]&] -[s2; [%-*@3 s] .&] +[s2; Returns HTTP request header field value.&] [s3; &] [s4; &] [s5;:Http`:`:GetLength`(`)const:%- [@(0.0.255) int]_[* GetLength]()_[@(0.0.255) const]&] -[s2; &] +[s2; Returns request content length.&] +[s3; &] +[s4;%- &] +[s5;:Http`:`:GetHandlerId`(`)const:%- [_^String^ String]_[* GetHandlerId]()_[@(0.0.255) con +st]&] +[s2; Returns the name of handler currently invoked.&] [s3; &] [s4; &] -[s5;:Http`:`:GetViewId`(`)const:%- [_^String^ String]_[* GetViewId]()_[@(0.0.255) const]&] -[s2; &] -[s3; &] -[s4; &] -[s5;:Http`:`:operator`[`]`(const char`*`)const:%- [@(0.0.255) virtual] -[_^Value^ Value]_[* operator`[`]]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 id])_[@(0.0.255) c -onst]&] -[s2; [%-*@3 id] .&] +[s5;:Http`:`:operator`[`]`(const char`*`)const:%- [_^Value^ Value]_[* operator`[`]]([@(0.0.255) c +onst]_[@(0.0.255) char]_`*[*@3 id])_[@(0.0.255) const]&] +[s2; Returns the shared space variable [%-*@3 id, ]void Value if missing.&] [s3; &] [s4; &] [s5;:Http`:`:Int`(const char`*`)const:%- [@(0.0.255) int]_[* Int]([@(0.0.255) const]_[@(0.0.255) c har]_`*[*@3 id])_[@(0.0.255) const]&] -[s2; [%-*@3 id] .&] +[s2; Returns the shared space variable [%-*@3 id] converted to integer, +Null if missing or if it cannot be converted.&] [s3; &] [s4; &] [s5;:Http`:`:operator`[`]`(int`)const:%- [_^String^ String]_[* operator`[`]]([@(0.0.255) in t]_[*@3 i])_[@(0.0.255) const]&] -[s2; [%-*@3 i] .&] +[s2; Returns the value of URL argument at position [%-*@3 i], empty +String if not available.&] [s3; &] [s4; &] [s5;:Http`:`:Int`(int`)const:%- [@(0.0.255) int]_[* Int]([@(0.0.255) int]_[*@3 i])_[@(0.0.255) c onst]&] -[s2; [%-*@3 i] .&] +[s2; Returns the value of URL argument at position [%-*@3 i] converted +to integer, Null if not available.&] [s3; &] [s4; &] [s5;:Http`:`:GetParamCount`(`)const:%- [@(0.0.255) int]_[* GetParamCount]()_[@(0.0.255) con st]&] -[s2; &] +[s2; Returns the number of URL arguments.&] [s3; &] [s4; &] [s5;:Http`:`:ContentType`(const char`*`):%- [_^Http^ Http][@(0.0.255) `&]_[* ContentType]([@(0.0.255) c onst]_[@(0.0.255) char]_`*[*@3 s])&] -[s2; [%-*@3 s] .&] +[s2; Sets the response content`-type. Default value is `"text/html; +charset`=UTF`-8`". Returns `*this.&] [s3; &] [s4; &] [s5;:Http`:`:Content`(const char`*`,const Value`&`):%- [_^Http^ Http][@(0.0.255) `&]_[* Con tent]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 s], [@(0.0.255) const]_[_^Value^ Value][@(0.0.255) `& ]_[*@3 data])&] -[s2; [%-*@3 s] [%-*@3 data] .&] +[s2; Sets the response content`-type to [%-*@3 s] and response content +to [%-*@3 data] converted to text. No html escaping is performed. +Returns `*this.&] [s3; &] [s4; &] [s5;:Http`:`:operator`<`<`(const Value`&`):%- [_^Http^ Http][@(0.0.255) `&]_[* operator<<]( [@(0.0.255) const]_[_^Value^ Value][@(0.0.255) `&]_[*@3 s])&] -[s2; [%-*@3 s] .&] +[s2; Sets the response content to [%-*@3 data] converted to text. No +html escaping is performed. Returns `*this.&] [s3; &] [s4; &] [s5;:Http`:`:SetRawCookie`(const char`*`,const String`&`,Time`,const char`*`,const char`*`,bool`,bool`):%- [_^Http^ H @@ -146,8 +175,9 @@ ttp][@(0.0.255) `&]_[* SetRawCookie]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 ]_`=_Null, [@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 path]_`=_NULL, [@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 domain]_`=_NULL, [@(0.0.255) bool]_[*@3 secure]_ `=_[@(0.0.255) false], [@(0.0.255) bool]_[*@3 httponly]_`=_[@(0.0.255) false])&] -[s2; [%-*@3 id] [%-*@3 value] [%-*@3 expires] [%-*@3 path] [%-*@3 domain] -[%-*@3 secure] [%-*@3 httponly] .&] +[s2; Sets the cookie [%-*@3 id] to [%-*@3 value], using [%-*@3 expires], +[%-*@3 path], [%-*@3 domain], [%-*@3 secure], [%-*@3 httponly] to setup +cookie attributes. [%-*@3 value] is not url`-encoded. Returns `*this.&] [s3; &] [s4; &] [s5;:Http`:`:SetCookie`(const char`*`,const String`&`,Time`,const char`*`,const char`*`,bool`,bool`):%- [_^Http^ H @@ -156,113 +186,131 @@ ttp][@(0.0.255) `&]_[* SetCookie]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 id ]_`=_Null, [@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 path]_`=_NULL, [@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 domain]_`=_NULL, [@(0.0.255) bool]_[*@3 secure]_ `=_[@(0.0.255) false], [@(0.0.255) bool]_[*@3 httponly]_`=_[@(0.0.255) false])&] -[s2; [%-*@3 id] [%-*@3 value] [%-*@3 expires] [%-*@3 path] [%-*@3 domain] -[%-*@3 secure] [%-*@3 httponly] .&] +[s2; Same as SetRawCookie, but url`-encoding the [%-*@3 value]. Returns +`*this.&] [s3; &] [s4; &] [s5;:Http`:`:ClearSession`(`):%- [_^Http^ Http][@(0.0.255) `&]_[* ClearSession]()&] -[s2; &] +[s2; Clears the session variables and session id (but their values +in shared variable space are retained). Returns `*this.&] [s3; &] [s4; &] [s5;:Http`:`:SessionSet`(const char`*`,const Value`&`):%- [_^Http^ Http][@(0.0.255) `&]_[* S essionSet]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 id], [@(0.0.255) const]_[_^Value^ Va lue][@(0.0.255) `&]_[*@3 value])&] -[s2; [%-*@3 id] [%-*@3 value] .&] -[s3; &] -[s4; &] -[s5;:Http`:`:NewIdentity`(`):%- [_^Http^ Http][@(0.0.255) `&]_[* NewIdentity]()&] -[s2; &] +[s2; Sets the session value [%-*@3 id] to [%-*@3 value], also sets shared +variable space to the same value. [%-*@3 id] must start with `'.`'. +Session variables are preserved for session across HTTP requests +(using session cookies). Returns `*this.&] [s3; &] [s4; &] [s5;:Http`:`:NewSessionId`(`):%- [_^Http^ Http][@(0.0.255) `&]_[* NewSessionId]()&] -[s2; &] +[s2; Sets the new session id, effectively changing the session cookie +value and storage for current session. Returns `*this.&] +[s3; &] +[s4; &] +[s5;:Http`:`:NewIdentity`(`):%- [_^Http^ Http][@(0.0.255) `&]_[* NewIdentity]()&] +[s2; Sets the new CSRF prevention identity. It might be a good idea +to call this function after login. Returns `*this.&] [s3; &] [s4; &] [s5;:Http`:`:SetLanguage`(int`):%- [_^Http^ Http][@(0.0.255) `&]_[* SetLanguage]([@(0.0.255) i nt]_[*@3 lang])&] -[s2; [%-*@3 lang] .&] +[s2; Sets the session language to [%-*@3 lang]. This calls Renderer`::SetLanguage +to change the language of witz templates and also sets language +related session variables `".`_`_lang`_`_`" (integer value) and +`".language`" (text value), so that language can be restored +during following HTTP requests. Returns `*this.&] [s3; &] [s4; &] [s5;:Http`:`:Response`(int`,const String`&`):%- [_^Http^ Http][@(0.0.255) `&]_[* Response]( -[@(0.0.255) int]_[*@3 code`_], [@(0.0.255) const]_[_^String^ String][@(0.0.255) `&]_[*@3 ctex -t])&] -[s2; [%-*@3 code`_] [%-*@3 ctext] .&] +[@(0.0.255) int]_[*@3 code], [@(0.0.255) const]_[_^String^ String][@(0.0.255) `&]_[*@3 ctext]) +&] +[s2; Sets the HTTP response [%-*@3 code] and reason [%-*@3 ctext]. Returns +`*this.&] [s3; &] [s4; &] [s5;:Http`:`:RenderResult`(const char`*`):%- [_^Http^ Http][@(0.0.255) `&]_[* RenderResult]( [@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 template`_name])&] -[s2; [%-*@3 template`_name] .&] +[s2; Renders result content using witz template. Returns `*this.&] [s3; &] [s4; &] [s5;:Http`:`:Redirect`(const char`*`,int`):%- [_^Http^ Http][@(0.0.255) `&]_[* Redirect]([@(0.0.255) c -onst]_[@(0.0.255) char]_`*[*@3 url], [@(0.0.255) int]_[*@3 code`_]_`=_[@3 302])&] -[s2; [%-*@3 url] [%-*@3 code`_] .&] +onst]_[@(0.0.255) char]_`*[*@3 url], [@(0.0.255) int]_[*@3 code]_`=_[@3 302])&] +[s2; Sets the response to be redirection. [%-*@3 url][%- sets the Location: +header of response, ][%-*@3 code][%- the response code.] Returns +`*this.&] [s3; &] [s4; &] [s5;:Http`:`:Redirect`(void`(`*`)`(Http`&`)`,const Vector``&`):%- [_^Http^ Http -][@(0.0.255) `&]_[* Redirect]([@(0.0.255) void]_(`*[*@3 view])([_^Http^ Http][@(0.0.255) `&]) -, [@(0.0.255) const]_Vector`&_[*@3 arg])&] -[s2; [%-*@3 view] [%-*@3 arg] .&] +][@(0.0.255) `&]_[* Redirect]([@(0.0.255) void]_(`*[*@3 handler])([_^Http^ Http][@(0.0.255) `& +]), [@(0.0.255) const]_Vector`&_[*@3 arg])&] +[s2; Sets the redirection response to [%-*@3 handler] with a set of +url arguments [%-*@3 arg]. Returns `*this.&] [s3; &] [s4; &] [s5;:Http`:`:Redirect`(void`(`*`)`(Http`&`)`):%- [_^Http^ Http][@(0.0.255) `&]_[* Redirect]( -[@(0.0.255) void]_(`*[*@3 view])([_^Http^ Http][@(0.0.255) `&]))&] -[s2; [%-*@3 view] .&] +[@(0.0.255) void]_(`*[*@3 handler])([_^Http^ Http][@(0.0.255) `&]))&] +[s2; Sets the redirection response to [%-*@3 handler]. Returns `*this.&] [s3; &] [s4; &] [s5;:Http`:`:Redirect`(void`(`*`)`(Http`&`)`,const Value`&`):%- [_^Http^ Http][@(0.0.255) `& -]_[* Redirect]([@(0.0.255) void]_(`*[*@3 view])([_^Http^ Http][@(0.0.255) `&]), -[@(0.0.255) const]_Value[@(0.0.255) `&]_[*@3 v1])&] -[s2; [%-*@3 view] [%-*@3 v1] .&] +]_[* Redirect]([@(0.0.255) void]_(`*[*@3 handler])([_^Http^ Http][@(0.0.255) `&]), +[@(0.0.255) const]_Value[@(0.0.255) `&]_[*@3 arg1])&] +[s2; Sets the redirection response to [%-*@3 handler] with one url +argument. Returns `*this.&] [s3; &] [s4; &] [s5;:Http`:`:Redirect`(void`(`*`)`(Http`&`)`,const Value`&`,const Value`&`):%- [_^Http^ H -ttp][@(0.0.255) `&]_[* Redirect]([@(0.0.255) void]_(`*[*@3 view])([_^Http^ Http][@(0.0.255) `& -]), [@(0.0.255) const]_Value[@(0.0.255) `&]_[*@3 v1], [@(0.0.255) const]_Value[@(0.0.255) `& -]_[*@3 v2])&] -[s2; [%-*@3 view] [%-*@3 v1] [%-*@3 v2] .&] +ttp][@(0.0.255) `&]_[* Redirect]([@(0.0.255) void]_(`*[*@3 handler])([_^Http^ Http][@(0.0.255) `& +]), [@(0.0.255) const]_Value[@(0.0.255) `&]_[*@3 arg1], [@(0.0.255) const]_Value[@(0.0.255) `& +]_[*@3 arg2])&] +[s2; Sets the redirection response to [%-*@3 handler] with two url +arguments. Returns `*this.&] [s3; &] [s4; &] [s5;:Http`:`:Ux`(const char`*`,const String`&`):%- [_^Http^ Http][@(0.0.255) `&]_[* Ux]([@(0.0.255) c onst]_[@(0.0.255) char]_`*[*@3 id], [@(0.0.255) const]_[_^String^ String][@(0.0.255) `&]_[*@3 t ext])&] -[s2; [%-*@3 id] [%-*@3 text] .&] +[s2; Sets the response in special Skylark format used to provide +Ajax support. When using `"skylark.js`" module for Ajax, this +response replaces html element with specified html id to [%-*@3 text]. +(text is not html`-escaped). Returns `*this.&] [s3; &] [s4; &] [s5;:Http`:`:UxRender`(const char`*`,const char`*`):%- [_^Http^ Http][@(0.0.255) `&]_[* UxR ender]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 id], [@(0.0.255) const]_[@(0.0.255) char ]_`*[*@3 template`_name])&] -[s2; [%-*@3 id] [%-*@3 template`_name] .&] +[s2; Sets the response in special Skylark format used to provide +Ajax support. When using `"skylark.js`" module for Ajax, this +response replaces html element with specified html id to the +rendered template. Returns `*this.&] [s3; &] [s4; &] [s5;:Http`:`:UxSet`(const char`*`,const String`&`):%- [_^Http^ Http][@(0.0.255) `&]_[* UxSe t]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 id], [@(0.0.255) const]_[_^String^ String][@(0.0.255) `& ]_[*@3 value])&] -[s2; [%-*@3 id] [%-*@3 value] .&] +[s2; Sets the response in special Skylark format used to provide +Ajax support. When using `"skylark.js`" module for Ajax, this +response replaces [*/ the value] of html element with specified +html id to the rendered template. Returns `*this.&] [s3; &] [s4; &] [s5;:Http`:`:UxRun`(const String`&`):%- [_^Http^ Http][@(0.0.255) `&]_[* UxRun]([@(0.0.255) c onst]_[_^String^ String][@(0.0.255) `&]_[*@3 js`_code])&] -[s2; [%-*@3 js`_code] .&] +[s2; Sets the response in special Skylark format used to provide +Ajax support. When using `"skylark.js`" module for Ajax, this +response makes browser to run arbitrary javascript code. Returns +`*this.&] [s3; &] [s4; &] [s5;:Http`:`:GetResponse`(`)const:%- [_^String^ String]_[* GetResponse]()_[@(0.0.255) const ]&] -[s2; &] +[s2; Returns the current response.&] [s3; &] [s4; &] [s5;:Http`:`:Dispatch`(TcpSocket`&`):%- [@(0.0.255) void]_[* Dispatch]([_^TcpSocket^ TcpSoc ket][@(0.0.255) `&]_[*@3 socket])&] -[s2; [%-*@3 socket] .&] -[s3; &] -[s4; &] -[s5;:Http`:`:App`(`)const:%- [@(0.0.255) const]_[_^SkylarkApp^ SkylarkApp][@(0.0.255) `&]_[* A -pp]()_[@(0.0.255) const]&] -[s2; &] -[s3; &] -[s4; &] -[s5;:Http`:`:Http`(SkylarkApp`&`):%- [* Http]([_^SkylarkApp^ SkylarkApp][@(0.0.255) `&]_[*@3 a -pp])&] -[s2; [%-*@3 app] .&] -[s3; &] +[s2; This method is not usually called by client application. Skylark +framework calls it to process incoming HTTP request.&] [s0; ]] \ No newline at end of file