9

I'm trying to send a JSON query to a web service and I continue to get internal server errors as a response to the query.

Here is what I'm trying to send:

POST /api/1.7/webservice.asmx HTTP/1.1
Host: www.superService.com
User-Agent: My app name v0.1
X-Custom-User-Agent: My app name v0.1
Content-Type: application/json
Content-Length:81

{"method":"AuthenticatePlain","loginName":"username@domain.com","password":"mypass"}

This is supposed to be sent to https://www.superService.com/api/1.7/ssapi.asmx

In preparing the QNetworkRequest, what method is used to insert the line

POST /api/1.7/webservice.asmx HTTP/1.1?

Is the complete header contained in the QNetworkRequest object?
Should the JSON data be in the QNetworkRequest object or is that added to the post as the second argument in the QNetworkAccessManager::post() method?

Here is my current code in the on_btnLogin_clicked() slot:

connect(m_qnam, SIGNAL(finished(QNetworkReply*)),
                 this, SLOT(handleNetworkData(QNetworkReply*)));
    connect(m_qnam,SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),
                 this, SLOT(handleSSLErrors(QNetworkReply*)));

    QString baseString = "";
    baseString.append(QString("POST /api/1.7/webservice.asmx HTTP/1.1\r\n").toUtf8());  
    baseString.append(QString("www.superService.com\r\n").toUtf8());
    baseString.append(QString("User-Agent: My app name v0.1\r\n").toUtf8());
    baseString.append(QString("X-Custom-User-Agent: My app name v0.1\r\n").toUtf8());
    baseString.append(QString("Content-Type: application/json\r\n").toUtf8());

    QString jsonString = QString("{");
    jsonString.append("\"method\":");
    jsonString.append("\"AuthenticatePlain\"");
    jsonString.append(",\"loginName\":");
    jsonString.append("\"username@domain.com\"");
    jsonString.append(",\"password\":");
    jsonString.append("\"mypass\"");
    jsonString.append("}");

    QByteArray json = jsonString.toUtf8();

    baseString.append(QString("Content-Length:").toUtf8());
    baseString.append(QString::number(json.length()));
    baseString.append("\r\n").toUtf8();
    baseString.append(QString("\r\n").toUtf8());
    baseString.append(json);

    request = QNetworkRequest(QUrl("https://www.superService.com/api/1.7/ssapi.asmx"));
    request.setRawHeader()


    qDebug() << "Base String: "<< baseString;


    m_qnam->post(request,baseString.toUtf8());
AAEM
  • 1,837
  • 2
  • 18
  • 26
DarwinIcesurfer
  • 1,073
  • 4
  • 25
  • 42

1 Answers1

17

This is not the right way to write your HTTP request. The following piece of code is more correct :

connect(m_qnam, SIGNAL(finished(QNetworkReply*)), this, SLOT(handleNetworkData(QNetworkReply*)));
connect(m_qnam,SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)), this, SLOT(handleSSLErrors(QNetworkReply*)));

// Build your JSON string as usual
QByteArray jsonString = "{\"method\":\"AuthenticatePlain\",\"loginName\":\"username@domain.com\",\"password\":\"mypass\"}";

// For your "Content-Length" header
QByteArray postDataSize = QByteArray::number(jsonString.size());

// Time for building your request
QUrl serviceURL("https://www.superService.com/api/1.7/ssapi.asmx");
QNetworkRequest request(serviceURL);

// Add the headers specifying their names and their values with the following method : void QNetworkRequest::setRawHeader(const QByteArray & headerName, const QByteArray & headerValue);
request.setRawHeader("User-Agent", "My app name v0.1");
request.setRawHeader("X-Custom-User-Agent", "My app name v0.1");
request.setRawHeader("Content-Type", "application/json");
request.setRawHeader("Content-Length", postDataSize);

// Use QNetworkReply * QNetworkAccessManager::post(const QNetworkRequest & request, const QByteArray & data); to send your request. Qt will rearrange everything correctly.
QNetworkReply * reply = m_qnam->post(request, jsonString);
air-dex
  • 4,130
  • 2
  • 25
  • 25
  • Thanks for the quick response! Is the line _italic_POST /api/1.7/webservice.asmx HTTP/1.1 _italic_ redundant, or how would that be inserted into request? – DarwinIcesurfer Sep 19 '12 at 02:44
  • 2
    It is redundant. */api/1.7/webservice.asmx* is specified with the `serviceURL` and *POST* with the `QNetworkAccessManager::post();` method. **You do not have to write the "low level" HTTP request. Qt will do that for you**. Do not hesitate to read some tutorials about this, I think that it will be very useful to you. – air-dex Sep 19 '12 at 08:21
  • My json string was incorrect too. I needed to pass "method", "parameters", and "id". I was missing the "parameters" object and the "id" object. A good summary of json here[link](http://en.wikipedia.org/wiki/JSON-RPC#Version_1.0) – DarwinIcesurfer Sep 20 '12 at 04:35
  • I think it is strange that you get the reply but do not connect it. Instead you connect it to the network access manager, which is bad practice if multiple clients are using it. – Zimano Jul 02 '18 at 13:52
  • @Zimano The answer consists in detailing how to build a request, not how to use a QNAM. However, `originatingObject` should be added in order to ensure that the request sender is the right one. But it is not the purpose here. – air-dex Jul 03 '18 at 03:28