PDA

View Full Version : POST request to a web service



QPlace
5th November 2008, 06:07
I have a web service in ASP.Net, getManagers, that accepts one parameter, UserName and returns a list of strings to a client.

I am trying to build the POST request from QT and I will appreciate any comments or suggestions on this subject

Here is what I do:
QHttpRequestHeader header("POST", "/StoreManager/getManagers.asmx");
header.setValue("Host", "localhost:1048");
header.setValue("charset", "utf-8");
header.setContentType("application/soap+xml");

m_http.setHost("http://localhost:1048");
m_http.request(header, "UserName=QPlace");

connect((QObject*)(&m_http), SIGNAL(requestFinished ( int id, bool error )), this, SLOT(ThisReqestIsCompleted ( int id, bool error )));


First problem is that ThisReqestIsCompleted is never called. But I am unsure if I am doing the call to the service correctly. All comments and suggestions are greatly appreciated

defender
5th November 2008, 12:18
I have a web service in ASP.Net, getManagers, that accepts one parameter, UserName and returns a list of strings to a client.

I am trying to build the POST request from QT and I will appreciate any comments or suggestions on this subject

Here is what I do:
QHttpRequestHeader header("POST", "/StoreManager/getManagers.asmx");
header.setValue("Host", "localhost:1048");
header.setValue("charset", "utf-8");
header.setContentType("application/soap+xml");

m_http.setHost("http://localhost:1048");
m_http.request(header, "UserName=QPlace");

connect((QObject*)(&m_http), SIGNAL(requestFinished ( int id, bool error )), this, SLOT(ThisReqestIsCompleted ( int id, bool error )));


First problem is that ThisReqestIsCompleted is never called. But I am unsure if I am doing the call to the service correctly. All comments and suggestions are greatly appreciated
Query is incorrect in terms of HTTP proto. let's look at peace of code that sending file to server:

QByteArray boundary = QByteArray::number(reinterpret_cast<long long>(this));
QByteArray begin_data="--"+boundary+"\r\nContent-Disposition: form-data; name=\"";
begin_data+=conf->get_config_for("FILE_INPUT_NAME");
begin_data+="\"; filename=\"test.txt\"\r\n\r\n";
QByteArray content_data;
content_data=read->readAll();
content_data+="\r\n";
QByteArray passwd_data = "--"+boundary+"\r\nContent-Disposition: form-data; name=\"code\"\r\n\r\n";
passwd_data+=conf->get_config_for("ACCESS_CODE");
QByteArray end_data="\r\n--"+boundary+"--\r\n";
QByteArray data = begin_data+content_data+passwd_data+end_data;

QHttpRequestHeader header("POST",conf->get_config_for("HOST_UPLOAD_PATH"));
header.setValue("Host",conf->get_config_for("HOST_NAME"));
header.setValue("Content-type","multipart/form-data; boundary="+boundary);
header.setValue("Content-Transfer-Encoding","binary");

if(conf->get_config_for("PROXY_HOST").size()!=0) {
http->setProxy(conf->get_config_for("PROXY_HOST"),
conf->get_config_for("PROXY_PORT").toInt(),
conf->get_config_for("PROXY_AUTH_USERNAME"),
conf->get_config_for("PROXY_AUTH_PASSWORD"));
}

http->setHost(conf->get_config_for("HOST_NAME"));
current_request=http->request(header,data);
req_finish.lock();

and finish signal handler:

void http_daemon::request_signal(int r_numb,bool err) {
log<<"Req fihish recvd:"<<r_numb<<" with err state:"<<err<<"\n";
log<<QString(http->readAll())<<"\n";

if(current_request==r_numb) {
// This req is waiting for req. Unlock main send thread!
req_finish.unlock();
}
}

Mutex req_finish used to block send function(thread) (first pease of code) until req is finished. (or some data, in your case QHttp object, would been destroyed after function exit)

PS
From QHttp docs:

The class works asynchronously, so there are no blocking functions. If an operation cannot be executed immediately, the function will still return straight away and the operation will be scheduled for later execution. The results of scheduled operations are reported via signals. This approach depends on the event loop being in operation.

QPlace
5th November 2008, 17:51
Thank you for your answer. I am not sure that I agree with it relative to my implementation. May be you can take a look at it (code below)

class RemoteManagers : public QObject
{
Q_OBJECT
private:
QHttp m_http;
private slots:
void OnrequestFinished ( int id, bool error );
public:
void GetManagers();
};


class CMainView : public QMainWindow
{
Q_OBJECT
private:
RemoteManagers m_remotemanagers;
private slots:
void OnGetManagers();
void OnManagersReceived (QStringList lst);
};


int main(int argc, char *argv[])
{
QApplication a(argc, argv);
CMainView w;
w.show();
return a.exec();
}


void CMainView::OnGetManagers()
{
m_remotemanagers.GetManagers();
}


void RemoteManagers::GetManagers()
{
QHttpRequestHeader* myheader = new QHttpRequestHeader("POST", "/MyWebsite/GetManagers.asmx");
QHttpRequestHeader& header = *myheader;
header.setValue("Host", "http://localhost:1048");
header.setValue("charset", "utf-8");
header.setContentType("application/x-www-form-urlencoded");
header.setContentLength(13);
header.setValue("Connection", "Keep-Alive");
header.setValue("Referer", "Referer=http://localhost:1048/MyWebsite/GetManagers.asmx?op=Portfolios");

m_http.setHost("http://localhost:1048");
m_http.request(header, "UserName=test");

connect((QObject*)(&m_http), SIGNAL(requestFinished ( int id, bool error )), this, SLOTOnrequestFinished( int id, bool error )));
}


So, I think that I am already handling the event loop correctly because of the following:
1. This is a GUI application, so there is an event loop.
2. Class, that handles http POST request is a RemoteManagers class that is instantiated in CMainView class.
3. I copied values for header settings from the actual request to the webservice that I capture in the debug mode for webservice when request comes from the browser.

m_http.request does not even reach the Web Server (I am running it in the debug mode, and when I access the service via the browser I am hitting a breakpoint...).

Any input is greatly appreciated

defender
6th November 2008, 08:05
Try to connect slot to signal before QHttp::request() called.