Good day
Intro:
My application requires getting the external IP address and matching it with an internally acquired address, thus allowing the application to proceed.
For this, I am using a QNetworkAccessManager and QNetworkReply for this purpose.
My code was built using this example as a reference.
What I have tried:
Acquiring an external IP can be done by getting a JSon object from the ipify API.
I confirmed this by:
curl "https://api.ipify.org?format=json"
which in turn responds with my current IP address in the format:
{"ip":"255.255.255.255"}
which is a JSonObject. Using this, I created the code below.
Problem:
The problem is quite simple, I get no response. The post
request is executed but simply no response (or finished
) signal is ever triggered.
POST
->GET
request
I have changed the code for a get
request as this solved this no response issue, found on this thread.
I did this by specifying the whole url with query parameters in the URL:
QNetworkRequest request(QUrl("https://api.ipify.org?format=json"));
including the header content type and size (as in the example below, finally calling the QNetworkAccessManager::get()
with:
replyExternalAddress = networkManager->get(request);
but this too gave no response.
I figured that it is something small that I am missing, but I simply cannot see it.
Advice?
Code for querying external IP:
// public callable method, starting network request
void APICommunicator::requestExternalAddress(){
qInfo(apicommunicator) << "Requesting external IP address from ipify.org";
// creates network request
// specifies "format=json"
QUrlQuery postData;
postData.addQueryItem("format", "json");
QByteArray encodedQuery = postData.toString(QUrl::FullyEncoded).toUtf8();
QNetworkRequest request(QUrl("https://api.ipify.org"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
request.setHeader(QNetworkRequest::ContentLengthHeader, QString::number(encodedQuery.size()));
// creates merged URL from URL and query items and sends a post:
// https://api.ipify.org?format=json
replyExternalAddress = networkManager->post(request, encodedQuery);
// Creates QMetaObject::Connection connection for finished signal from QNetworkReply
conExternalAddress = QObject::connect(replyExternalAddress, SIGNAL(finished()), this, SLOT(externalAddressResponse()));
// attach error listener to reply
addErrorListener(replyExternalAddress, conExternalAddress);
}
void APICommunicator::externalAddressResponse(){
qDebug(apicommunicator) << "External Address response recieved";
// disconnect signals
QObject::disconnect(conExternalAddress);
QObject::disconnect(conErrorListener);
// read all output from JSon object
QByteArray ba = replyExternalAddress->readAll();
// delete QNetworkReply
replyExternalAddress->deleteLater();
LogMessageHandler::writeToApiLog(QString("\n\nCALL EXTERNAL [" + replyExternalAddress->request().url().toString() + "]\n" + QString(ba)));
QJsonObject doc = QJsonDocument::fromJson(ba).object();
QString ip = doc.value("ip").toString();
QHostAddress address = QHostAddress();
if (ip.isEmpty()) {
qWarning(apicommunicator) << "External Address: no data received";
}
else {
address = QHostAddress(version);
}
// replies with address to external slot (in main application)
emit ExternalAddressReply(address);
}
The problem is that you are sending a
POST
request, whileipify.org
expects onlyGET
requests. You seem to have the misconception that you need to be sending aPOST
request in order to be able to send parameters (format=json
) along with your request, this is not true. In your code, you are sending the parameters asPOST
data, this is the same technique that is used when you submit a web form in your browser (because you are setting the content type header toapplication/x-www-form-urlencoded
).You absolutely don't need to mimic the request of a web browser sending a form in order to be able to talk to the API
ipify.org
provides.ipify.org
provides a much simpler interface; you just need to send your query string in your get request. Qt makes the job even easier by providing the classQUrlQuery
that provides a way to build url queries. Here is a working example: