3

I need to make an HTTP POST request to a server from my Qt application.

The POST request would contain a list of named values, i.e. key/value pairs. They will be mostly alphanumeric strings, but can contain special characters such as quotes, spaces, etc.

What is the canonical way of doing this type of POST request in Qt?

sashoalm
  • 75,001
  • 122
  • 434
  • 781

3 Answers3

9

The current answer works for Qt 4. Syntax has changed for Qt 5 and would look like this:

QUrlQuery params;

params.addQueryItem("key1", "value1");
params.addQueryItem("key2", "value2");

QUrl resource("http://server.com/form.php");
QNetworkAccessManager* manager = new QNetworkAccessManager(this);

connect(manager, SIGNAL(finished(QNetworkReply*)), this, 
SLOT(handleEndOfRequest(QNetworkReply*)));

QNetworkRequest request(resource);
//Force Content-Type header
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");

manager->post(request, params.query(QUrl::FullyEncoded).toUtf8());

Some background information: http://doc.qt.io/qt-5/qurl-obsolete.html

Making Qt-version-aware code is described here: How do you port QUrl addQueryItem to Qt5's QUrlQuery?

ftw
  • 136
  • 1
  • 4
4
QUrl params;

params.addQueryItem("key1", "value1");
params.addQueryItem("key2", "value2");

QUrl resource("http://server.com/form.php");
QNetworkAccessManager* manager = new QNetworkAccessManager(this);

connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(handleEndOfRequest(QNetworkReply*)));

QNetworkRequest request(resource);
//Force Content-Type header
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");

manager->post(request, params.encodedQuery());

This code assumes that your current object is a QObject (passed as a parent for QNeworkAccessManager and slots declaration)

sashoalm
  • 75,001
  • 122
  • 434
  • 781
epsilon
  • 2,849
  • 16
  • 23
  • Does `QNetworkAccessManager* manager` need to be allocated on the heap? Can I just put it on the stack instead? – sashoalm Aug 26 '13 at 08:18
  • `finished` signal will happen asynchronously, so maybe at this time you will have your manager out of scope, and then destroyed if you allocate it on the stack. All depends on where you declare your manager in fact. – epsilon Aug 26 '13 at 08:21
  • Hm, I'm getting an error at `manager->post(resource, params.encodedQuery());`, seems that `post()` requires a `QNetworkRequest` instead. Changing to `manager->post(QNetworkRequest(resource), params.encodedQuery());` fixes it. – sashoalm Aug 26 '13 at 08:26
  • @sashoalm Do not forget the cleanup the QNetworkReply on the handleEndOfRequest slot! Otherwise you have a memory leak. – Kurt Pattyn Aug 26 '13 at 08:27
  • Totally correct @sashoalm, I make an edit to correct this forgetting – epsilon Aug 26 '13 at 08:28
  • @KurtPattyn: you are right for deleting concern, but documentation preconize to use `deleteLater()` [http://qt-project.org/doc/qt-4.8/qnetworkaccessmanager.html#finished](http://qt-project.org/doc/qt-4.8/qnetworkaccessmanager.html#finished) – epsilon Aug 26 '13 at 08:30
  • @jbh Of course the correct function is deleteLater(); I could have been more clear – Kurt Pattyn Aug 26 '13 at 08:31
  • @jbh OK, it's working now, and I'm testing it with netcat. One thing - I noticed it has `Content-Type: application/octet-stream`. Is this the correct setting? – sashoalm Aug 26 '13 at 08:33
  • Is seems normal because Qt considers parameters as an byte streams (`params.encodedQuery` returns a `QByteArray`). But normally for HTTP POST request on forms, your browser set a `Content-Type` of `application/x-www-form-urlencoded`. I edit my post to show you an example ;) – epsilon Aug 26 '13 at 08:37
0

You can use QNetworkAccessManager together with QNetworkRequest to post http requests.
If you want to send key/value pairs, consider using JSON.

Kurt Pattyn
  • 2,758
  • 2
  • 30
  • 42