git-svn-id: svn://ultimatepp.org/upp/trunk@5265 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2012-08-05 16:41:29 +00:00
parent 1d8e2578d9
commit f7e4f73e95
3 changed files with 549 additions and 500 deletions

View file

@ -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<DispatchNode> {
VectorMap<String, int> 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<DispatchNode>& sDispatchMap()
{
static Vector<DispatchNode> x;
return x;
}
static VectorMap<String, Vector<String> >& sLinkMap()
{
static VectorMap<String, Vector<String> > x;
return x;
}
static Index<uintptr_t>& sViewIndex()
{
static Index<uintptr_t> x;
return x;
}
void DumpDispatchMap()
{
Vector<DispatchNode>& 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<String> *GetUrlViewLinkParts(const String& id)
{
int q = sLinkMap().Find(id);
if(q < 0)
return NULL;
return &sLinkMap()[q];
}
String MakeLink(void (*view)(Http&), const Vector<Value>& 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<String>& linkpart = sLinkMap().GetAdd(id);
sViewIndex().FindAdd((uintptr_t)view);
Vector<DispatchNode>& 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<String> 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<ViewData>& sViewData()
{
static Array<ViewData> x;
return x;
}
void RegisterHandler(void (*view)(Http&), const char *id, const char *path)
{
Array<ViewData>& v = sViewData();
ViewData& w = v.Add();
w.view = view;
w.id = id;
w.path = path;
}
void SkylarkApp::FinalizeViews()
{
Array<ViewData>& 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<String> 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<String>& arg;
String id;
bool post_raw;
BestDispatch(Vector<String>& arg) : arg(arg) { matched_parts = -1; matched_params = 0; view = NULL; post_raw = false; }
};
void GetBestDispatch(int method,
const Vector<String>& part, int ii, const DispatchNode& n, Vector<String>& arg,
BestDispatch& bd, int matched_parts, int matched_params)
{
Vector<DispatchNode>& 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<DispatchNode>& 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<String> part = Split(uri, '/');
for(int i = 0; i < part.GetCount(); i++)
part[i] = UrlDecode(part[i]);
LDUMPC(part);
Vector<String> 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<br>"
<< "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<br>"
<< 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<DispatchNode> {
VectorMap<String, int> 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<DispatchNode>& sDispatchMap()
{
static Vector<DispatchNode> x;
return x;
}
static VectorMap<String, Vector<String> >& sLinkMap()
{
static VectorMap<String, Vector<String> > x;
return x;
}
static Index<uintptr_t>& sViewIndex()
{
static Index<uintptr_t> x;
return x;
}
void DumpDispatchMap()
{
Vector<DispatchNode>& 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<String> *GetUrlViewLinkParts(const String& id)
{
int q = sLinkMap().Find(id);
if(q < 0)
return NULL;
return &sLinkMap()[q];
}
String MakeLink(void (*view)(Http&), const Vector<Value>& 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<String>& linkpart = sLinkMap().GetAdd(id);
sViewIndex().FindAdd((uintptr_t)view);
Vector<DispatchNode>& 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<String> 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<ViewData>& sViewData()
{
static Array<ViewData> x;
return x;
}
void RegisterHandler(void (*view)(Http&), const char *id, const char *path)
{
Array<ViewData>& v = sViewData();
ViewData& w = v.Add();
w.view = view;
w.id = id;
w.path = path;
}
void SkylarkApp::FinalizeViews()
{
Array<ViewData>& 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<String> 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<String>& arg;
String id;
bool post_raw;
BestDispatch(Vector<String>& arg) : arg(arg) { matched_parts = -1; matched_params = 0; view = NULL; post_raw = false; }
};
void GetBestDispatch(int method,
const Vector<String>& part, int ii, const DispatchNode& n, Vector<String>& arg,
BestDispatch& bd, int matched_parts, int matched_params)
{
Vector<DispatchNode>& 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<DispatchNode>& 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<String> part = Split(uri, '/');
for(int i = 0; i < part.GetCount(); i++)
part[i] = UrlDecode(part[i]);
LDUMPC(part);
Vector<String> 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<br>"
<< "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<br>"
<< 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);
}
}
};

View file

@ -41,7 +41,7 @@ class Http : public Renderer {
HttpHeader hdr;
String content;
String viewid;
String handlerid;
Vector<String> 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; }

View file

@ -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`<Value`>`&`):%- [_^Http^ Http
][@(0.0.255) `&]_[* Redirect]([@(0.0.255) void]_(`*[*@3 view])([_^Http^ Http][@(0.0.255) `&])
, [@(0.0.255) const]_Vector<Value>`&_[*@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<Value>`&_[*@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; ]]