// replay a particular http request void TReplaySrv::ReplayHttpRq(const PHttpRq& HttpRq) { PUrl HttpRqUrl = HttpRq->GetUrl(); // extract function name TStr FunNm = HttpRqUrl->GetPathSeg(0); // extract parameters TStrKdV FldNmValPrV; PUrlEnv HttpRqUrlEnv = HttpRq->GetUrlEnv(); const int Keys = HttpRqUrlEnv->GetKeys(); for (int KeyN = 0; KeyN < Keys; KeyN++) { TStr KeyNm = HttpRqUrlEnv->GetKeyNm(KeyN); const int Vals = HttpRqUrlEnv->GetVals(KeyN); for (int ValN = 0; ValN < Vals; ValN++) { TStr Val = HttpRqUrlEnv->GetVal(KeyN, ValN); FldNmValPrV.Add(TStrKd(KeyNm, Val)); } } // processed requested function if (!FunNm.Empty()) { // prepare request environment PSAppSrvRqEnv RqEnv = TSAppSrvRqEnv::New(this, TUInt64::Mx, HttpRq, FunNmToFunH); // retrieve function PSAppSrvFun SrvFun = FunNmToFunH.GetDat(FunNm); // call function SrvFun->Exec(FldNmValPrV, RqEnv); } }
// if one or more items with FldNm already exist remove them first // add to FldNmValPrV pair (FldNm, FldVal) void TSAppSrvFun::SetFldNmVal(TStrKdV& FldNmValPrV, const TStr& FldNm, const TStr& FldVal) { for (int N = FldNmValPrV.Len() - 1; N >= 0; N--) { if (FldNmValPrV[N].Key == FldNm) FldNmValPrV.Del(N); } FldNmValPrV.Add(TStrKd(FldNm, FldVal)); }
void TSAppSrv::OnHttpRq(const uint64& SockId, const PHttpRq& HttpRq) { // last appropriate error code, start with bad request int ErrStatusCd = THttp::BadRqStatusCd; try { // check http-request correctness - return if error EAssertR(HttpRq->IsOk(), "Bad HTTP request!"); // check url correctness - return if error PUrl RqUrl = HttpRq->GetUrl(); EAssertR(RqUrl->IsOk(), "Bad request URL!"); // extract function name PUrl HttpRqUrl = HttpRq->GetUrl(); TStr FunNm = HttpRqUrl->GetPathSeg(0); // check if we have the function registered if (FunNm == "favicon.ico") { PHttpResp HttpResp = THttpResp::New(THttp::OkStatusCd, THttp::ImageIcoFldVal, false, Favicon.GetSIn()); SendHttpResp(SockId, HttpResp); return; } else if (!FunNm.Empty() && !FunNmToFunH.IsKey(FunNm)) { ErrStatusCd = THttp::ErrNotFoundStatusCd; GetNotify()->OnStatusFmt("[AppSrv] Unknown function '%s'!", FunNm.CStr()); TExcept::Throw("Unknown function '" + FunNm + "'!"); } // extract parameters TStrKdV FldNmValPrV; PUrlEnv HttpRqUrlEnv = HttpRq->GetUrlEnv(); const int Keys = HttpRqUrlEnv->GetKeys(); for (int KeyN = 0; KeyN < Keys; KeyN++) { TStr KeyNm = HttpRqUrlEnv->GetKeyNm(KeyN); const int Vals = HttpRqUrlEnv->GetVals(KeyN); for (int ValN = 0; ValN < Vals; ValN++) { TStr Val = HttpRqUrlEnv->GetVal(KeyN, ValN); FldNmValPrV.Add(TStrKd(KeyNm, Val)); } } // report call if (ShowParamP) { GetNotify()->OnStatus(" " + HttpRq->GetUrl()->GetUrlStr()); } // request parsed well, from now on it's internal error ErrStatusCd = THttp::InternalErrStatusCd; // processed requested function if (!FunNm.Empty()) { // prepare request environment PSAppSrvRqEnv RqEnv = TSAppSrvRqEnv::New(this, SockId, HttpRq, FunNmToFunH); // retrieve function PSAppSrvFun SrvFun = FunNmToFunH.GetDat(FunNm); // call function SrvFun->Exec(FldNmValPrV, RqEnv); } else { // internal SAppSrv call if (!ListFunP) { // we are not allowed to list functions ErrStatusCd = THttp::ErrNotFoundStatusCd; TExcept::Throw("Unknown page"); } // prepare a list of registered functions PXmlTok TopTok = TXmlTok::New("registered-functions"); int KeyId = FunNmToFunH.FFirstKeyId(); while (FunNmToFunH.FNextKeyId(KeyId)) { PXmlTok FunTok = TXmlTok::New("function"); FunTok->AddArg("name", FunNmToFunH.GetKey(KeyId)); TopTok->AddSubTok(FunTok); } TStr ResXmlStr; TXmlDoc::New(TopTok)->SaveStr(ResXmlStr); PSIn BodySIn = TMIn::New(TSAppSrvFun::XmlHdStr + ResXmlStr); // prepare response PHttpResp HttpResp = THttpResp::New(THttp::OkStatusCd, THttp::TextXmlFldVal, false, BodySIn); // send response SendHttpResp(SockId, HttpResp); } } catch (PExcept Except) { // known internal error PXmlTok TopTok = TXmlTok::New("error"); TopTok->AddSubTok(TXmlTok::New("message", Except->GetMsgStr())); TopTok->AddSubTok(TXmlTok::New("location", Except->GetLocStr())); PXmlDoc ErrorXmlDoc = TXmlDoc::New(TopTok); TStr ResXmlStr; ErrorXmlDoc->SaveStr(ResXmlStr); // prepare response PHttpResp HttpResp = THttpResp::New(ErrStatusCd, THttp::TextHtmlFldVal, false, TMIn::New(TSAppSrvFun::XmlHdStr + ResXmlStr)); // send response SendHttpResp(SockId, HttpResp); } catch (...) { // unknown internal error PXmlDoc ErrorXmlDoc = TXmlDoc::New(TXmlTok::New("error")); TStr ResXmlStr; ErrorXmlDoc->SaveStr(ResXmlStr); // prepare response PHttpResp HttpResp = THttpResp::New(ErrStatusCd, THttp::TextHtmlFldVal, false, TMIn::New(TSAppSrvFun::XmlHdStr + ResXmlStr)); // send response SendHttpResp(SockId, HttpResp); } }
void TSAppSrv::OnHttpRq(const int& SockId, const PHttpRq& HttpRq) { PHttpResp HttpResp; try { // check http-request correctness - return if error EAssertR(HttpRq->IsOk(), "Bad HTTP request!"); // check url correctness - return if error PUrl RqUrl = HttpRq->GetUrl(); EAssertR(RqUrl->IsOk(), "Bad request URL!"); // extract function name PUrl HttpRqUrl = HttpRq->GetUrl(); TStr FunNm = HttpRqUrl->GetPathSeg(0); EAssertR(FunNmToFunH.IsKey(FunNm) || FunNm.Empty(), "Unknown function '" + FunNm + "' !"); // extract parameters TStrKdV FldNmValPrV; PUrlEnv HttpRqUrlEnv = HttpRq->GetUrlEnv(); const int Keys = HttpRqUrlEnv->GetKeys(); for (int KeyN = 0; KeyN < Keys; KeyN++) { TStr KeyNm = HttpRqUrlEnv->GetKeyNm(KeyN); const int Vals = HttpRqUrlEnv->GetVals(KeyN); for (int ValN = 0; ValN < Vals; ValN++) { TStr Val = HttpRqUrlEnv->GetVal(KeyN, ValN); FldNmValPrV.Add(TStrKd(KeyNm, Val)); } } // log the call TStr TimeNow = TTm::GetCurLocTm().GetWebLogDateTimeStr(true); GetNotify()->OnStatus(TStr::Fmt("[%s] Request %s", TimeNow.CStr(), FunNm.CStr())); // prepare request environment PSAppSrvRqEnv RqEnv = TSAppSrvRqEnv::New(this, SockId, HttpRq); PSIn BodySIn; TStr ContTypeVal; if (!FunNm.Empty()) { // call function PSAppSrvFun SrvFun = FunNmToFunH.GetDat(FunNm); if (SrvFun->GetFunOutType() == saotXml) { PXmlDoc ResXmlDoc = SrvFun->Exec(FldNmValPrV, RqEnv); TStr ResXmlStr; ResXmlDoc->SaveStr(ResXmlStr); //ResXmlDoc->SaveTxt(TFile::GetUniqueFNm("test.xml")); BodySIn = TMIn::New(XmlHdStr + ResXmlStr); ContTypeVal = THttp::TextXmlFldVal; } else if (SrvFun->GetFunOutType() == saotJSon) { TStr ResStr = SrvFun->ExecJSon(FldNmValPrV, RqEnv); BodySIn = TMIn::New(ResStr); //ContTypeVal = THttp::TextHtmlFldVal; ContTypeVal = THttp::AppJSonFldVal; } else { BodySIn = SrvFun->ExecCustom(FldNmValPrV, RqEnv, ContTypeVal); } } else { PXmlTok TopTok = TXmlTok::New("registered-functions"); int KeyId = FunNmToFunH.FFirstKeyId(); while (FunNmToFunH.FNextKeyId(KeyId)) { PXmlTok FunTok = TXmlTok::New("function"); FunTok->AddArg("name", FunNmToFunH.GetKey(KeyId)); TopTok->AddSubTok(FunTok); } PXmlDoc ResXmlDoc = TXmlDoc::New(TopTok); TStr ResXmlStr; ResXmlDoc->SaveStr(ResXmlStr); BodySIn = TMIn::New(XmlHdStr + ResXmlStr); ContTypeVal = THttp::TextXmlFldVal; } // prepare response HttpResp = THttpResp::New(THttp::OkStatusCd, ContTypeVal, false, BodySIn); // send response } catch (PExcept Except) { PXmlTok TopTok = TXmlTok::New("error"); TopTok->AddSubTok(TXmlTok::New("message", Except->GetMsgStr())); TopTok->AddSubTok(TXmlTok::New("location", Except->GetLocStr())); PXmlDoc ErrorXmlDoc = TXmlDoc::New(TopTok); TStr ResXmlStr; ErrorXmlDoc->SaveStr(ResXmlStr); HttpResp = THttpResp::New(THttp::OkStatusCd, THttp::TextHtmlFldVal, false, TMIn::New(XmlHdStr + ResXmlStr)); } catch (...) { PXmlDoc ErrorXmlDoc = TXmlDoc::New(TXmlTok::New("error")); TStr ResXmlStr; ErrorXmlDoc->SaveStr(ResXmlStr); HttpResp = THttpResp::New(THttp::OkStatusCd, THttp::TextHtmlFldVal, false, TMIn::New(XmlHdStr + ResXmlStr)); } SendHttpResp(SockId, HttpResp); }