// a http request is received. process it using the standard TSAppSrv method // and then optionally also save the request to the log file void TReplaySrv::OnHttpRq(const uint64& SockId, const PHttpRq& HttpRq) { // if we are logging requests then log it if (!SOut.Empty()) { try { PUrl HttpRqUrl = HttpRq->GetUrl(); TStr FunNm = HttpRqUrl->GetPathSeg(0); if (LoggingFunNmH.IsKey(FunNm)) { THttpReqSerInfo ReqInfo(HttpRq); ReqInfo.Save(*SOut); if (FlushEachRequest) SOut->Flush(); } } catch (PExcept Except) { TFileNotify Notify("ReplaySrvError.txt"); Notify.OnNotifyFmt(ntErr, "TReplaySrv::OnHttpRq. Exception %s.", Except->GetMsgStr().CStr()); Notify.OnNotifyFmt(ntErr, "TReplaySrv::OnHttpRq. Location info: \n%s.", Except->GetLocStr().CStr()); } catch (...) { TFileNotify Notify("ReplaySrvError.txt"); Notify.OnNotify(ntErr, "TReplaySrv::OnHttpRq. Unrecognized exception."); } } // only after we've logged the request we also execute it - otherwise we could process the request and crash before saving the data TSAppSrv::OnHttpRq(SockId, HttpRq); }
// 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); } }
int TWebNetCltV::FetchUrl(const PUrl& Url, const int& _FetchId, TStr ConnUid){ IAssert(Url->IsOk(usHttp)); //FetchingP=true; // prepare fetch-id & http-request int FetchId=_FetchId; if (_FetchId==-1){ FetchId=GetNextFetchId();} PHttpRq HttpRq=THttpRq::New(Url, FetchId); // prepare host-port-string TStr HostNm=Url->GetHostNm(); int PortN=Url->GetPortN(); TStr ConnIdStr=TWebNetClt::GetConnIdStr(HostNm, PortN, ConnUid); // check if already connected PWebNetClt WebNetClt; if (IsGetWebNetClt(ConnIdStr, WebNetClt)){ if (WebNetClt->IsConnected()){ // already connected; send http-request WebNetClt->SendHttpRq(HttpRq); } else { // not connected; process of connecting WebNetClt->PushToWaitQ(FetchId, HttpRq); } } else { // not connected; connect //SaveToErrLog((TStr("NetCltConnect: ")+ConnIdStr).CStr()); WebNetClt=TWebNetClt::New(HostNm, PortN, this, ConnIdStr, Notify); AddWebNetClt(ConnIdStr, WebNetClt); WebNetClt->PushToWaitQ(FetchId, HttpRq); } //FetchingP=false; return FetchId; }
void TWebPgFetchEvent::OnFetchEnd(const PHttpResp& HttpResp){ EAssert(HttpResp->IsOk()); EndMSecs=TTm::GetCurUniMSecs(); int StatusCd=HttpResp->GetStatusCd(); if (StatusCd/100==2){ // codes 2XX - ok ChangeLastUrlToLc(HttpResp); PWebPg WebPg=TWebPg::New(UrlStrV, IpNumV, HttpResp); WebPg->PutFetchMSecs(GetFetchMSecs()); CloseConn(); Fetch->DisconnUrl(FId); Fetch->OnFetch(FId, WebPg); } else if (StatusCd/100==3){ // codes 3XX - redirection ChangeLastUrlToLc(HttpResp); if (UrlStrV.Len()<5){ TStr RedirUrlStr=HttpResp->GetFldVal("Location"); PUrl RedirUrl=TUrl::New(RedirUrlStr, CurUrl->GetUrlStr()); if (RedirUrl->IsOk(usHttp)){ TStrQuV CookieQuV; HttpResp->GetCookieKeyValDmPathQuV(CookieQuV); AddCookieKeyValDmPathQuV(CookieQuV); CurUrl=RedirUrl; Retries=0; CloseConn(); TSockHost::GetAsyncSockHost(CurUrl->GetIpNumOrHostNm(), this); } else { TStr MsgStr=TStr("Invalid Redirection URL (")+RedirUrlStr+")"; OnFetchError(MsgStr); } } else { TStr MsgStr=TStr("Cycling Redirection [")+TopUrl->GetUrlStr()+"]"; OnFetchError(MsgStr); } } else { // all other codes - error TStr MsgStr=TStr("Http Error (")+ TInt::GetStr(StatusCd)+"/"+HttpResp->GetReasonPhrase()+")"; OnFetchError(MsgStr); } }
int TWebPgFetch::FetchUrl(const PUrl& Url, const bool& QueueAtEnd){ int FId=-1; if (Url->IsOk(usHttp) && Url->IsPortOk()){ FId=GetNextFId(); ConnUrl(FId, Url, QueueAtEnd); } else { TStr MsgStr=TStr("Invalid URL [")+Url->GetUrlStr()+"]"; OnError(FId, MsgStr); } return FId; }
void TSASFunRedirect::Exec(const TStrKdV& FldNmValPrV, const PSAppSrvRqEnv& RqEnv) { PUrl Url = RqEnv->GetHttpRq()->GetUrl(); TStr FunNm = (Url->GetPathSegs() > 1) ? Url->GetPathSeg(1) : ""; EAssert(MapH.IsKey(FunNm)); const TRedirect& Redirect = MapH.GetDat(FunNm); TStrKdV _FldNmValPrV = Redirect.FldNmValPrV; for (int FldN = 0; FldN < FldNmValPrV.Len(); FldN++) { TStr OrgFldNm = FldNmValPrV[FldN].Key; if (Redirect.FldNmMapH.IsKey(OrgFldNm)) { _FldNmValPrV.Add(TStrKd(Redirect.FldNmMapH.GetDat(OrgFldNm), FldNmValPrV[FldN].Dat)); } } RqEnv->ExecFun(Redirect.FunNm, _FldNmValPrV); }
void TWebPgFetch::OpenConn(const int& FId, const PUrl& Url){ PSockEvent Event=PSockEvent(new TWebPgFetchEvent(this, FId, Url, ProxyStr, UserAgentStr, TimeOutMSecs)); TSockEvent::Reg(Event); ConnFIdToEventH.AddDat(FId, Event); TStr HostNm; if (ProxyStr.Empty()){HostNm=Url->GetIpNumOrHostNm();} else {TStr PortNStr; ProxyStr.SplitOnCh(HostNm, ':', PortNStr);} TSockHost::GetAsyncSockHost(HostNm, Event); }
void TWebPgFetchPersist::Save(TSOut& SOut) const { if (ConnFIdToEventH.Len() > 0) Notify->OnStatusFmt("TWebPgFetchPersist.Save. Saving %d pending web requests to disk...", ConnFIdToEventH.Len()); // serialize requests in the queue for (int KeyId = ConnFIdToEventH.FFirstKeyId(); ConnFIdToEventH.FNextKeyId(KeyId);) { const int FId = ConnFIdToEventH.GetKey(KeyId); PUrl Url = GetConnUrl(FId); Url->Save(SOut); } // serialize requests that are currently in progress TLstNd<TIdUrlPr>* Item = WaitFIdUrlPrL.First(); while (Item != NULL) { Item->Val.Val2->Save(SOut);; Item = Item->Next(); } if (ConnFIdToEventH.Len() > 0) Notify->OnStatusFmt("TWebPgFetchPersist.Save. Saved %d requests to the disk.", ConnFIdToEventH.Len()); }
void TWebPgFetchEvent::OnGetHost(const PSockHost& SockHost) { if (SockHost->IsOk()){ UrlStrV.Add(CurUrl->GetUrlStr()); OppSockClosed=false; SockMem.Clr(); Sock=TSock::New(this); int PortN; if (ProxyStr.Empty()){ PortN=CurUrl->GetPortN(); } else { TStr ProxyHostNm; TStr PortNStr; ProxyStr.SplitOnCh(ProxyHostNm, ':', PortNStr); PortN=PortNStr.GetInt(80); } Sock->PutTimeOut(TimeOutMSecs); Sock->Connect(SockHost, PortN); } else { OnFetchError("Invalid Host"); } }
////////////////////////////////////// // File-Download-Function PSIn TSASFunFPath::ExecSIn(const TStrKdV& FldNmValPrV, const PSAppSrvRqEnv& RqEnv, TStr& ContTypeStr) { // construct file name TStr FNm = FPath; PUrl Url = RqEnv->GetHttpRq()->GetUrl(); const int PathSegs = Url->GetPathSegs(); if ((PathSegs == 1) || (PathSegs == 2 && Url->GetPathSeg(1).Empty())) { // nothing specified, do the default TStr PathSeg = Url->GetPathSeg(0); if (PathSeg.LastCh() != '/') { FNm += "/"; } FNm += DefaultFNm; } else { // extract file name for (int PathSegN = 1; PathSegN < PathSegs; PathSegN++) { FNm += "/"; FNm += Url->GetPathSeg(PathSegN); } } // get mime-type TStr FExt = FNm.GetFExt(); if (FExt == ".htm") { ContTypeStr = THttp::TextHtmlFldVal; } else if (FExt == ".html") { ContTypeStr = THttp::TextHtmlFldVal; } else if (FExt == ".js") { ContTypeStr = THttp::TextJavaScriptFldVal; } else if (FExt == ".css") { ContTypeStr = THttp::TextCssFldVal; } else if (FExt == ".ico") { ContTypeStr = THttp::ImageIcoFldVal; } else if (FExt == ".png") { ContTypeStr = THttp::ImagePngFldVal; } else if (FExt == ".jpg") { ContTypeStr = THttp::ImageJpgFldVal; } else if (FExt == ".jpeg") { ContTypeStr = THttp::ImageJpgFldVal; } else if (FExt == ".gif") { ContTypeStr = THttp::ImageGifFldVal; } else { printf("Unknown MIME type for extension '%s' for file '%s'", FExt.CStr(), FNm.CStr()); ContTypeStr = THttp::AppOctetFldVal; } // return stream to the file return TFIn::New(FNm); }
void TWebPgFetchEvent::OnConnect(const uint64& SockId){ TChA RqChA; if (CurUrl->IsHttpRqStr()){ RqChA=CurUrl->GetHttpRqStr(); } else { // get http components TStr HostNm=CurUrl->GetHostNm(); TStr AbsPath=CurUrl->GetPathStr()+CurUrl->GetSearchStr(); // compose http request RqChA+="GET "; RqChA+=AbsPath; RqChA+=" HTTP/1.0\r\n"; RqChA+="Host: "; RqChA+=HostNm; RqChA+="\r\n"; if (!UserAgentStr.Empty()){ RqChA+="User-Agent: "; RqChA+=UserAgentStr; RqChA+="\r\n";} // add cookies if (GetCookies()>0){ RqChA+="Cookie: "; for (int CookieN=0; CookieN<GetCookies(); CookieN++){ TStr KeyNm; TStr ValStr; TStr DmNm; TStr PathStr; GetCookie(CookieN, KeyNm, ValStr, DmNm, PathStr); if (HostNm.EndsWith(DmNm)){ if (CookieN>0){RqChA+="; ";} RqChA+=KeyNm; RqChA+='='; RqChA+=ValStr; } } RqChA+="\r\n"; } // finish request RqChA+="\r\n"; } // send http request PSIn RqSIn=TMIn::New(RqChA); bool Ok; TStr ErrMsg; Sock->Send(RqSIn, Ok, ErrMsg); if (Ok){ Sock->PutTimeOut(TimeOutMSecs); } else { OnFetchError("Unable to send the data: " + ErrMsg); } }
///////////////////////////////////////////////// // Web-Fetch-Blocking void TWebFetchBlocking::GetWebPg(const PUrl& Url, bool& Ok, TStr& MsgStr, PWebPg& WebPg, const PNotify& Notify, const TStr& ProxyStr, const TStr& UserAgentStr){ TNotify::OnNotify(Notify, ntInfo, TStr("Fetching: ")+Url->GetUrlStr()); TWebFetchBlocking WebFetch; if (!UserAgentStr.Empty()) { WebFetch.PutUserAgentStr(UserAgentStr); } WebFetch.PutProxyStr(ProxyStr); WebFetch.FetchUrl(Url); TLoop::Ref(); TLoop::Run(); Ok=WebFetch.Ok; MsgStr=WebFetch.MsgStr; WebPg=WebFetch.WebPg; if (!Ok){ TNotify::OnNotify(Notify, ntInfo, TStr("Fetching Error: ["+MsgStr+"]")); } }
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); }
void *TMongSrv::HandleRequest(enum mg_event event, struct mg_connection *conn, const struct mg_request_info *request_info) { // Since this is a static request handler, find out for which // server instance this is for. The URL should tell that. TChA UrlStr = "http://"; const char *Host = mg_get_header(conn, "Host"); UrlStr += Host != NULL ? Host : "localhost"; UrlStr += request_info->uri; if (request_info->query_string != NULL) { UrlStr += "?"; UrlStr += request_info->query_string; } void *processed = (void *) "yes"; TStr UrlS = UrlStr; PUrl Url = TUrl::New(UrlS); if (!Url->IsOk(usHttp)) { TNotify::OnNotify(TNotify::StdNotify, ntErr, TStr("Invalid URI: ") + UrlStr); return NULL; } PMongSrv& Server = TMongSrv::Get(Url); if (request_info->log_message != NULL) { TNotify::OnNotify(Server->GetNotify(), ntErr, TStr(request_info->log_message)); return NULL; } THttpRqMethod Method = hrmUndef; if (strncmp(request_info->request_method, "POST", 4) == 0) { Method = hrmPost; } else if (strncmp(request_info->request_method, "GET", 3) == 0) { Method = hrmGet; } else if (strncmp(request_info->request_method, "HEAD", 4) == 0) { Method = hrmHead; } else { return NULL; } TStr ContentType = mg_get_header(conn, THttp::ContTypeFldNm.CStr()); const char *ContentLenStr = mg_get_header(conn, "Content-Length"); PHttpRq Rq; if (Method == hrmPost) { int ContentLength = atoi(ContentLenStr); char *Body = new char[ContentLength]; mg_read(conn, Body, ContentLength); Rq = THttpRq::New(Method, Url, ContentType, TMem(Body, ContentLength)); delete[] Body; } else { Rq = THttpRq::New(Method, Url, ContentType, TMem()); } int ClientId = Server->NewClient(conn, request_info); try { Server->OnHttpRq(ClientId, Rq); Server->DropClient(ClientId); return processed; } catch (PExcept& Exception) { TNotify::OnNotify(Server->GetNotify(), ntErr, Exception->GetStr()); Server->DropClient(ClientId); return NULL; } }
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); } }
bool IsCTxtHttpResp(const PUrl& Url, const PHttpResp& HttpResp, const int& MnCTxtToks){ if (HttpResp->IsStatusCd_Ok()){ PWebPg WebPg=TWebPg::New(Url->GetUrlStr(), HttpResp); if (HttpResp->IsContType(THttp::TextHtmlFldVal)){ TMem BodyMem=HttpResp->GetBodyAsMem(); PSIn BodyMemIn=TMemIn::New(BodyMem); // prepare html-tokens PHtmlDoc HtmlDoc=THtmlDoc::New(BodyMemIn, hdtAll, false); int Toks=HtmlDoc->GetToks(); THtmlLxSym TokSym; TStr TokStr; // prepare continuous-text indicators int CTxtToks=0; TChA CTxtChA; bool CTxtP=false; // prepare script & style flag bool InScript=false; bool InStyle=false; // traverse tokens for (int TokN=0; TokN<Toks; TokN++){ // get token data HtmlDoc->GetTok(TokN, TokSym, TokStr); switch (TokSym){ case hsyStr: case hsyNum: case hsySSym: if (!InScript&&!InStyle){ // text token CTxtToks++; CTxtChA+=TokStr; CTxtChA+=' '; } break; case hsyBTag: if (!InScript&&!InStyle){ if (TokStr=="<SCRIPT>"){ // start of script InScript=true; CTxtToks=0; CTxtChA.Clr(); } else if (TokStr=="<STYLE>"){ // start of style InStyle=true; CTxtToks=0; CTxtChA.Clr(); } else { if ((TokStr=="<P>")||(TokStr=="<B>")||(TokStr=="<I>")){ // skip in-text-tags } else { // non-text-tags - break continuous-text CTxtToks=0; CTxtChA.Clr(); } } } break; case hsyETag: if (InScript||InStyle){ if (TokStr=="<SCRIPT>"){ // end of script InScript=false; } else if (TokStr=="<STYLE>"){ // end of style InStyle=false; } } break; default: // non-text-token - break continuous-text CTxtToks=0; CTxtChA.Clr(); break; } // stop if enough continuous-text if (CTxtToks>MnCTxtToks){ CTxtP=true; break; } } if (CTxtP){ printf("%s\n", Url->GetUrlStr().CStr()); } return CTxtP; } } return false; }
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 HttpRqUrl = HttpRq->GetUrl(); EAssertR(HttpRqUrl->IsOk(), "Bad request URL!"); // extract function name 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 PUrlEnv HttpRqUrlEnv = HttpRq->GetUrlEnv(); TStrKdV FldNmValPrV; HttpRqUrlEnv->GetKeyValPrV(FldNmValPrV); // 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 PJsonVal FunArrVal = TJsonVal::NewArr(); int KeyId = FunNmToFunH.FFirstKeyId(); while (FunNmToFunH.FNextKeyId(KeyId)) { FunArrVal->AddToArr(TJsonVal::NewObj("name", FunNmToFunH.GetKey(KeyId))); } PJsonVal ResVal = TJsonVal::NewObj(); ResVal->AddToObj("port", GetPortN()); ResVal->AddToObj("connections", GetConns()); ResVal->AddToObj("functions", FunArrVal); TStr ResStr = ResVal->SaveStr(); // prepare response PHttpResp HttpResp = THttpResp::New(THttp::OkStatusCd, THttp::AppJSonFldVal, false, TMIn::New(ResStr)); // send response SendHttpResp(SockId, HttpResp); } } catch (PExcept Except) { // known internal error TNotify::StdNotify->OnNotifyFmt(ntErr, "Error: %s", Except->GetMsgStr().CStr()); TNotify::StdNotify->OnNotifyFmt(ntErr, "Error location info: %s", Except->GetLocStr().CStr()); PJsonVal ErrorVal = TJsonVal::NewObj(); ErrorVal->AddToObj("message", Except->GetMsgStr()); ErrorVal->AddToObj("location", Except->GetLocStr()); PJsonVal ResVal = TJsonVal::NewObj("error", ErrorVal); TStr ResStr = ResVal->SaveStr(); // prepare response PHttpResp HttpResp = THttpResp::New(ErrStatusCd, THttp::AppJSonFldVal, false, TMIn::New(ResStr)); // send response SendHttpResp(SockId, HttpResp); } catch (...) { TNotify::StdNotify->OnNotify(ntErr, "Unknown internal error"); // unknown internal error PJsonVal ResVal = TJsonVal::NewObj("error", "Unknown internal error"); TStr ResStr = ResVal->SaveStr(); // prepare response PHttpResp HttpResp = THttpResp::New(ErrStatusCd, THttp::AppJSonFldVal, false, TMIn::New(ResStr)); // send response SendHttpResp(SockId, HttpResp); } }
void TWebPgFetchEvent::OnFetchError(const TStr& MsgStr){ Fetch->OnError(FId, MsgStr+" ["+CurUrl->GetUrlStr()+"]"); CloseConn(); Fetch->DisconnUrl(FId); }
void TMongSrv::OnHttpRq(const int& SockId, const PHttpRq& HttpRq) { // check http-request correctness - return if error if (!HttpRq->IsOk()) { TNotify::OnNotify(Notify, ntInfo, "Web-Server: Bad Http Request."); return; } // check url correctness - return if error PUrl RqUrl = HttpRq->GetUrl(); if (!RqUrl->IsOk()) { TNotify::OnNotify(Notify, ntInfo, "Web-Server: Bad Url Requested."); return; } // construct http-response PHttpResp HttpResp; if (!RqUrl->GetPathStr().Empty()) { // get request-file-name TStr ExeFPath = TSysProc::GetExeFNm().GetFPath(); TStr RqFNm = RqUrl->GetPathStr(); if (RqFNm.LastCh() == '/') { RqFNm = RqFNm + "default.htm"; } if ((RqFNm[0] == '/') || (RqFNm[0] == '\\')) { RqFNm.DelSubStr(0, 0); } RqFNm = ExeFPath + RqFNm; // open file bool RqFOpened = false; PSIn RqSIn = TFIn::New(RqFNm, RqFOpened); if (!RqFOpened) { // prepare default html with time TChA HtmlChA; HtmlChA += "<html><title>Error - Not Found</title><body>"; HtmlChA += "File: "; HtmlChA += RqUrl->GetPathStr(); HtmlChA += " not found."; HtmlChA += "</body></html>"; PSIn BodySIn = TMIn::New(HtmlChA); HttpResp = PHttpResp( new THttpResp(THttp::ErrNotFoundStatusCd, THttp::TextHtmlFldVal, false, BodySIn, "")); } else { // file successfully opened PSIn BodySIn = RqSIn; if (THttp::IsHtmlFExt(RqFNm.GetFExt())) { // send text/html mime type if Html filemg_callback_t HttpResp = PHttpResp( new THttpResp(THttp::OkStatusCd, THttp::TextHtmlFldVal, false, BodySIn, "")); } else if (THttp::IsGifFExt(RqFNm.GetFExt())) { // send image/gif mime type if Gif file HttpResp = PHttpResp( new THttpResp(THttp::OkStatusCd, THttp::ImageGifFldVal, false, BodySIn, "")); } else { // send application/octet mime type HttpResp = PHttpResp( new THttpResp(THttp::OkStatusCd, THttp::AppOctetFldVal, false, BodySIn, "")); } } } else { // prepare default html with time TChA HtmlChA; HtmlChA += "<html><title>Welcome to TWebSrv (powered by mongoose 3.1)</title><body>"; HtmlChA += TSecTm::GetCurTm().GetStr(); HtmlChA += "</body></html>"; PSIn BodySIn = TMIn::New(HtmlChA); HttpResp = THttpResp::New(THttp::OkStatusCd, THttp::TextHtmlFldVal, false, BodySIn); } // construct & send response SendHttpResp(SockId, HttpResp); // notify if (RqUrl->IsOk()) { TChA MsgChA; MsgChA += "Web-Server: Request for '"; MsgChA += RqUrl->GetUrlStr(); MsgChA += "'."; TNotify::OnNotify(Notify, ntInfo, MsgChA); } }