From 50d9e7c6f2c43c03621313684f9f17445717f8da Mon Sep 17 00:00:00 2001 From: konrad Date: Wed, 29 Sep 2010 19:58:03 +0000 Subject: [PATCH] convert transaction from QHttp to QNetworkAccessManager git-svn-id: https://silmor.de/svn/softmagic/pack/trunk@594 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33 --- qtbase/include/WTransaction_Private | 1 + qtbase/include/interface.h | 14 ++- qtbase/include/transaction.h | 43 +++---- qtbase/include/transaction_p.h | 45 ++++++++ qtbase/src/interface.cpp | 29 ++++- qtbase/src/transaction.cpp | 214 +++++++++++++++++++++-------------- woc/qt/qtctrans.cpp | 21 ++-- 7 files changed, 237 insertions(+), 130 deletions(-) create mode 100644 qtbase/include/WTransaction_Private create mode 100644 qtbase/include/transaction_p.h diff --git a/qtbase/include/WTransaction_Private b/qtbase/include/WTransaction_Private new file mode 100644 index 0000000..6530292 --- /dev/null +++ b/qtbase/include/WTransaction_Private @@ -0,0 +1 @@ +#include "transaction_p.h" diff --git a/qtbase/include/interface.h b/qtbase/include/interface.h index 3cac7c4..70531fe 100644 --- a/qtbase/include/interface.h +++ b/qtbase/include/interface.h @@ -18,12 +18,21 @@ #include #include +class QNetworkAccessManager; +class QNetworkRequest; +class QNetworkReply; + class WInterface:public QObject { Q_OBJECT protected: + ///used by child classes for instantiation WInterface(QString name); + friend class WTransaction; + ///called by WTransaction to post a request + QNetworkReply* post(const QNetworkRequest&request,const QByteArray&data); + public: virtual ~WInterface(); /**overwrite if you need additional headers (eg. session-ids) for certain transactions (transaction name is handed in as string argument); per default returns empty map*/ @@ -81,13 +90,13 @@ class WInterface:public QObject /**resets the proxy settings to no proxy use*/ void resetProxy(){m_proxyhost="";m_proxyport=0;m_proxyuser="";m_proxypass="";} /**sets the proxy settings*/ - void setProxy(QString proxyhost,unsigned short proxyport,QString proxyuser="",QString proxypassword=""){m_proxyhost=proxyhost;m_proxyport=proxyport;m_proxyuser=proxyuser;m_proxypass=proxypassword;} + void setProxy(QString proxyhost,unsigned short proxyport,QString proxyuser=QString(),QString proxypassword=QString()); /**sets the URL of the interface*/ void setUrl(QUrl u){m_url=u;} /**handles SSL errors, per default ignores them, overwrite it if you need more sophisticated behavior*/ - virtual void sslErrors(const QList&); + virtual void sslErrors(QNetworkReply *,const QList&); private: static QMapinst; @@ -96,6 +105,7 @@ class WInterface:public QObject unsigned short m_proxyport; int m_wtimeout; LogLevel loglvl; + QNetworkAccessManager*m_netman; }; #endif diff --git a/qtbase/include/transaction.h b/qtbase/include/transaction.h index f2a75a2..8932010 100644 --- a/qtbase/include/transaction.h +++ b/qtbase/include/transaction.h @@ -28,22 +28,27 @@ class WTransaction:public WHelper /**stage the transaction is in*/ enum Stage { Uninitialized,///, (C) 2010 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#ifndef WOLF_TRANSACTION_PH +#define WOLF_TRANSACTION_PH + +#include +#include + +#include "WTransaction" + +///\internal private logger class +class WTransaction::Log{ + public: + Log(WTransaction*,const QString&); + ~Log(); + void setRequ(const QString&,const QString&); + void setResp(const QString&,const QString&); + void setError(const QString&); + void setInfo(const QString&); + private: + QByteArray req,rsp; + QString trn; + WTransaction*parent; + int lvl; +}; + +///\internal private iface +class WTransaction::Private { + public: + Stage m_stage; + QString m_errtype,m_errstr,m_iface,m_wobstatus; + Log*m_log; +}; + +#endif diff --git a/qtbase/src/interface.cpp b/qtbase/src/interface.cpp index c85e80b..ba825da 100644 --- a/qtbase/src/interface.cpp +++ b/qtbase/src/interface.cpp @@ -12,9 +12,13 @@ #include "WInterface" -#include +// #include #include #include +#include +#include +#include +#include QMap WInterface::inst; @@ -37,6 +41,8 @@ WInterface::WInterface(QString name) delete inst[name]; } inst.insert(name,this); + m_netman=new QNetworkAccessManager(this); + connect(m_netman,SIGNAL(sslErrors(QNetworkReply*,QList)), this,SLOT(sslErrors(QNetworkReply*,QList))); } QString WInterface::name()const @@ -56,9 +62,22 @@ QMap WInterface::headers(QString)const return QMap(); } -void WInterface::sslErrors(const QList&) +void WInterface::sslErrors(QNetworkReply *reply,const QList&) { - QHttp*src=qobject_cast(sender()); - if(!src)return; - src->ignoreSslErrors(); + if(!reply)return; + reply->ignoreSslErrors(); +} + +QNetworkReply* WInterface::post(const QNetworkRequest&request,const QByteArray&data ) +{ + return m_netman->post(request,data); +} + +void WInterface::setProxy(QString proxyhost,unsigned short proxyport,QString proxyuser,QString proxypassword) +{ + m_proxyhost=proxyhost; + m_proxyport=proxyport; + m_proxyuser=proxyuser; + m_proxypass=proxypassword; + m_netman->setProxy(QNetworkProxy(QNetworkProxy::HttpProxy,proxyhost,proxyport,proxyuser,proxypassword)); } diff --git a/qtbase/src/transaction.cpp b/qtbase/src/transaction.cpp index 50f83f2..3e9ce5b 100644 --- a/qtbase/src/transaction.cpp +++ b/qtbase/src/transaction.cpp @@ -10,41 +10,50 @@ // // +#include "WTransaction_Private" #include "WTransaction" #include "WInterface" #include #include #include -#include +#include +#include +#include +#include #include #include WTransaction::WTransaction(QString ifc) { - m_stage=Uninitialized; - m_httpid=-1; - m_iface=ifc; - m_log=0; + d=new Private; + d->m_stage=Uninitialized; + d->m_iface=ifc; + d->m_log=0; } WTransaction::WTransaction(const WTransaction&t) :WHelper() { - m_stage=t.m_stage; - m_errstr=t.m_errstr; - m_errtype=t.m_errtype; - m_iface=t.m_iface; - m_httpid=-1; - m_log=0; + d=new Private; + d->m_stage=t.d->m_stage; + d->m_errstr=t.d->m_errstr; + d->m_errtype=t.d->m_errtype; + d->m_iface=t.d->m_iface; + d->m_log=0; +} + +WTransaction::~WTransaction() +{ + if(d)delete d; + d=0; } WTransaction& WTransaction::operator=(const WTransaction&t) { - m_stage=t.m_stage; - m_errstr=t.m_errstr; - m_errtype=t.m_errtype; - m_iface=t.m_iface; - m_httpid=-1; + d->m_stage=t.d->m_stage; + d->m_errstr=t.d->m_errstr; + d->m_errtype=t.d->m_errtype; + d->m_iface=t.d->m_iface; return *this; } @@ -60,150 +69,181 @@ static inline QString esc(const QByteArray ar) return r; } +static inline QString hd2str(const QList&hl) +{ + QString r; + for(int i=0;i rqpairs(const QNetworkRequest&req) +{ + QListhds=req.rawHeaderList(); + QListret; + for(int i=0;im_iface); if(!iface){ - if(m_log)m_log->setError("cannot find interface."); + if(d->m_log)d->m_log->setError("cannot find interface."); else qDebug("Error: transaction cannot find interface."); - m_stage=Error; - m_errtype="_iface"; - m_errstr=tr("interface not found"); + d->m_stage=Error; + d->m_errtype="_iface"; + d->m_errstr=tr("interface not found"); return QByteArray(); } - connect(&req,SIGNAL(sslErrors(const QList&)),iface,SLOT(sslErrors(const QList&))); + //set target QUrl url=iface->url(); int port=url.port(); if(port<=0){ if(url.scheme().toLower()=="http")port=80; else port=443; } - if(m_log)m_log->setInfo(QString("New HTTP Request %1 URL %2\n\tto host=%3 port=%4 scheme=%5") + if(d->m_log)d->m_log->setInfo(QString("New HTTP Request %1 URL %2\n\tto host=%3 port=%4 scheme=%5") .arg(hreq) .arg(url.toString()) .arg(url.host()) .arg(port) .arg(url.scheme())); - QHttp::ConnectionMode conm; - if(url.scheme().toLower()=="http")conm=QHttp::ConnectionModeHttp; - else conm=QHttp::ConnectionModeHttps; - req.setHost(url.host(),conm,port); - if(iface->useProxy())req.setProxy(iface->proxyHost(),iface->proxyPort(),iface->proxyUser(),iface->proxyPassword()); - QString pathspec=url.path(); - if(pathspec=="")pathspec="/"; - if(url.encodedQuery()!="")pathspec+="?"+url.encodedQuery(); - QHttpRequestHeader hrh("POST",pathspec); - QString hostspec=url.host(); - if(url.port()>0)hostspec+=":"+QString::number(port); - hrh.setValue("Host",hostspec); + req.setUrl(url); + //set headers QMaphdrs=iface->headers(hreq); QStringList hdrn=hdrs.keys(); for(int i=0;isetRequ(hrh.toString(),esc(data),m_httpid); - m_log->setInfo(QString("HTTP ID %1").arg(m_httpid)); + req.setRawHeader("X-"+hdrn[i].toAscii(),hdrs[hdrn[i]].toAscii()); + req.setRawHeader("X-WobRequest",hreq.toAscii()); + req.setHeader(QNetworkRequest::ContentLengthHeader,QByteArray::number(data.size())); + req.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-webobject; charset=UTF-8"); + //send it (with body) + QNetworkReply*rsp=iface->post(req,data); + //log request + if(d->m_log){ + d->m_log->setRequ(hd2str(rqpairs(req)),esc(data)); } + //make sure response is deleted + QObject rspown; + rsp->setParent(&rspown); + //we are requesting now... + d->m_stage=Request; ///////////////////////////////////////////////////////////////////// //start loop QTimer tmr; tmr.setSingleShot(true);tmr.start(iface->webTimeout()*1000); connect(&tmr,SIGNAL(timeout()),this,SLOT(webTimeout())); + connect(rsp,SIGNAL(finished()),this,SLOT(webReady())); + connect(rsp,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(webError())); loop.exec(); tmr.stop();tmr.disconnect(SIGNAL(timeout()),this,SLOT(webTimeout())); ///////////////////////////////////////////////////////////////////// //process result - if(m_stage==Error && m_errtype=="_timeout"){ + if(d->m_stage==Error && d->m_errtype=="_timeout"){ //it did not finish yet, caught a timeout. - req.abort(); - m_errstr=tr("Web Request timed out."); - if(m_log)m_log->setError(QString("Request %1 timed out.").arg(m_httpid)); + rsp->abort(); + d->m_errstr=tr("Web Request timed out."); + if(d->m_log)d->m_log->setError("Request timed out."); return QByteArray(); }else //finished with low-level error? - if(m_stage==Error){ - m_errstr="HTTP Error: "+req.errorString(); - if(m_log)m_log->setError(QString("Request %2 finished with HTTP level error: %1").arg(m_errstr).arg(m_httpid)); + if(d->m_stage==Error){ + d->m_errstr="HTTP Error: "+rsp->errorString(); + if(d->m_log)d->m_log->setError(QString("Request finished with HTTP level error: %1").arg(d->m_errstr)); return QByteArray(); } //get data - QHttpResponseHeader rsph=req.lastResponse(); - m_wobstatus=rsph.value("X-WobResponse-Status"); - m_wobstatus=m_wobstatus.replace("\"","").trimmed().toLower(); - QByteArray rspdata=req.readAll(); - if(m_log)m_log->setResp(rsph.toString(),esc(rspdata),m_httpid); + d->m_wobstatus=rsp->rawHeader("X-WobResponse-Status"); + d->m_wobstatus=d->m_wobstatus.replace("\"","").trimmed().toLower(); + QByteArray rspdata=rsp->readAll(); + if(d->m_log)d->m_log->setResp(hd2str(rsp->rawHeaderPairs()),esc(rspdata)); //check for high level error - if(rsph.statusCode()!=200){ - m_errstr=tr("HTTP Error, return code %1 %2") .arg(rsph.statusCode()).arg(rsph.reasonPhrase()); - m_errtype="_HTTP"; - m_stage=Error; - if(m_log)m_log->setError(QString("Request %2 finished with HTTP level error: %1").arg(m_errstr).arg(m_httpid)); + int statcode=rsp->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + if(statcode!=200){ + d->m_errstr=tr("HTTP Error, return code %1 %2") .arg(statcode).arg(rsp->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString()); + d->m_errtype="_HTTP"; + d->m_stage=Error; + if(d->m_log)d->m_log->setError(QString("Request finished with HTTP level error: %1").arg(d->m_errstr)); return QByteArray(); } - if(m_stage!=Error)m_stage=Success; + if(d->m_stage==Request){ + d->m_stage=Error; + d->m_errtype="_internal"; + d->m_errstr="Ooops: still in Request phase at end of response handling."; + } //remaining high level errors are handled by the generated code return rspdata; } void WTransaction::webTimeout() { - if(m_httpid<0)return; + if(d->m_stage!=Request)return; // qDebug("web timeout"); - m_stage=Error; - m_errtype="_timeout"; + d->m_stage=Error; + d->m_errtype="_timeout"; emit webFinished(); } -void WTransaction::webReady(int i,bool e) +void WTransaction::webReady() { - if(i!=m_httpid)return; - if(m_log)m_log->setInfo(QString("finished request %1").arg(i)); - if(e){ - m_stage=Error; - m_errtype="_web"; - } + if(d->m_stage!=Request)return; + if(d->m_log)d->m_log->setInfo(QString("finished request")); + d->m_stage=Success; + d->m_errtype=""; + emit webFinished(); +} + +void WTransaction::webError() +{ + if(d->m_stage!=Request)return; + if(d->m_log)d->m_log->setInfo(QString("error in request")); + d->m_stage=Error; + d->m_errtype="_web"; emit webFinished(); } QString WTransaction::errorString()const { - return QCoreApplication::translate("php::",m_errstr.toUtf8(),0,QCoreApplication::UnicodeUTF8); + return QCoreApplication::translate("php::",d->m_errstr.toUtf8(),0,QCoreApplication::UnicodeUTF8); } +WTransaction::Stage WTransaction::stage()const{return d->m_stage;} +bool WTransaction::hasError()const{return d->m_stage==Error;} +QString WTransaction::errorType()const{return d->m_errtype;} +QString WTransaction::interface()const{return d->m_iface;} + -WTransaction::WTLog::WTLog(WTransaction*p,const QString&s) +WTransaction::Log::Log(WTransaction*p,const QString&s) { parent=p; - parent->m_log=this; + parent->d->m_log=this; trn=s; - WInterface*in=WInterface::instance(p->m_iface); + WInterface*in=WInterface::instance(p->d->m_iface); if(in)lvl=in->logLevel(); else lvl=WInterface::LogOnError; if(lvl>WInterface::LogNone) qDebug("Running transaction %s",s.toAscii().data()); } -WTransaction::WTLog::~WTLog() +WTransaction::Log::~Log() { - parent->m_log=0; + parent->d->m_log=0; } -void WTransaction::WTLog::setRequ(const QString&h,const QString&d,int i) +void WTransaction::Log::setRequ(const QString&h,const QString&d) { if(lvl<=WInterface::LogInfo)return; - QByteArray r="RequestID="+QString::number(i).toAscii() - +"\n--Header--\n"+h.trimmed().toAscii() + QByteArray r="Request" + "\n--Header--\n"+h.trimmed().toAscii() +"\n--Body--\n"+d.trimmed().toAscii()+"\n--End--"; if(lvl==WInterface::LogDetailed) qDebug("Transaction %s request: %s",trn.toAscii().data(),r.data()); @@ -212,11 +252,11 @@ void WTransaction::WTLog::setRequ(const QString&h,const QString&d,int i) req=r; } -void WTransaction::WTLog::setResp(const QString&h,const QString&d,int i) +void WTransaction::Log::setResp(const QString&h,const QString&d) { if(lvl<=WInterface::LogInfo)return; - QByteArray r="RequestID="+QString::number(i).toAscii() - +"\n--Header--\n"+h.trimmed().toAscii() + QByteArray r="Response" + "\n--Header--\n"+h.trimmed().toAscii() +"\n--Body--\n"+d.trimmed().toAscii()+"\n--End--"; if(lvl==WInterface::LogDetailed) qDebug("Transaction %s response: %s",trn.toAscii().data(),r.data()); @@ -225,13 +265,13 @@ void WTransaction::WTLog::setResp(const QString&h,const QString&d,int i) rsp=r; } -void WTransaction::WTLog::setInfo(const QString&s) +void WTransaction::Log::setInfo(const QString&s) { if(lvl>=WInterface::LogInfo) qDebug("Transaction %s info: %s",trn.toAscii().data(),s.toAscii().data()); } -void WTransaction::WTLog::setError(const QString&s) +void WTransaction::Log::setError(const QString&s) { //bail out if no logging if(lvl\n"; for(int i=0;im_errstr=\"interface not found\";d->m_stage=Error;log.setError(d->m_errstr);return;}\n"; //encode input scd+=trnInput(trn); scd+="\tdoc.appendChild(root);\n"; @@ -224,14 +225,14 @@ QString WocQtClientTransaction::trnOutput(const WocTransaction&trn) code+="\tdoc=QDomDocument();\n"; code+="\tQString emsg;int eln,ecl;\n"; code+="\tif(!doc.setContent(rba,&emsg,&eln,&ecl)){\n"; - code+="\t\tm_stage=Error;m_errtype=\"_iface\";m_errstr=QString(QCoreApplication::translate(\"WobTransaction\",\"XML result parser error line %1 col %2: %3\")).arg(eln).arg(ecl).arg(emsg);\n\t\tlog.setError(m_errstr);\n\t\treturn;\n\t}\n"; + code+="\t\td->m_stage=Error;d->m_errtype=\"_iface\";d->m_errstr=QString(QCoreApplication::translate(\"WobTransaction\",\"XML result parser error line %1 col %2: %3\")).arg(eln).arg(ecl).arg(emsg);\n\t\tlog.setError(d->m_errstr);\n\t\treturn;\n\t}\n"; code+="\troot=doc.documentElement();\n"; //decide where to go, error handling - code+="\tif(m_wobstatus!=\"ok\"){\n\t\tm_stage=Error;m_errtype=\"_server\";m_errstr=\"unknown server error\";\n"; + code+="\tif(d->m_wobstatus!=\"ok\"){\n\t\td->m_stage=Error;d->m_errtype=\"_server\";d->m_errstr=\"unknown server error\";\n"; code+="\t\tQString terr=root.text().trimmed();\n"; - code+="\t\tif(terr==\"\"){\n\t\t\tlog.setError(m_errstr);\n\t\t\treturn;\n\t\t}\n"; - code+="\t\tm_errtype=root.attribute(\"type\",\"_server\");\n"; - code+="\t\tm_errstr=terr;\n\t\tlog.setError(m_errstr);\n\t\treturn;\n\t}\n"; + code+="\t\tif(terr==\"\"){\n\t\t\tlog.setError(d->m_errstr);\n\t\t\treturn;\n\t\t}\n"; + code+="\t\td->m_errtype=root.attribute(\"type\",\"_server\");\n"; + code+="\t\td->m_errstr=terr;\n\t\tlog.setError(d->m_errstr);\n\t\treturn;\n\t}\n"; code+="\tQList nl;\n"; //parse parameters for(int i=0;im_stage=Error;d->m_errtype=e.component();d->m_errstr=e.error();log.setError(d->m_errstr);}\n"; }else if(trn.isIntType(t)){ code+="\t\tout_"+sl[i]+".append(nl.at(i).toElement().text().toInt());\n"; }else if(trn.isBoolType(t)){ @@ -262,7 +263,7 @@ QString WocQtClientTransaction::trnOutput(const WocTransaction&trn) }else{ code+="\tif(nl.size()>0){\n"; if(trn.isObjectType(t)){ - code+="\t\ttry{out_"+sl[i]+"="+qtobjtype(trn,sl[i],WocQtOut::Out)+"(nl.at(0).toElement());}catch(WException e){m_stage=Error;m_errtype=e.component();m_errstr=e.error();log.setError(m_errstr);}\n"; + code+="\t\ttry{out_"+sl[i]+"="+qtobjtype(trn,sl[i],WocQtOut::Out)+"(nl.at(0).toElement());}catch(WException e){d->m_stage=Error;d->m_errtype=e.component();d->m_errstr=e.error();log.setError(d->m_errstr);}\n"; }else if(trn.isBlobType(t)){ code+="\t\tout_"+sl[i]+"=QByteArray::fromBase64(nl.at(0).toElement().text().toAscii());\n"; }else{//can only be string -- 1.7.2.5