PDA

View Full Version : Issues with HTTP REST Interface



rhb327
11th April 2017, 16:09
Working on code to use a REST interfact to exchange information to a cloud service. My issue is that this service makes two replies to a JSON post:

URL1: Simple success message <<< This is the same URL that JSON is posted too
ULR2: Detailed message

This is how I would post to URL1...not showing JSON:


QUrl serviceUrl = QUrl("URL1");
QNetworkRequest request(serviceUrl);
QNetworkAccessManager *networkManager = new QNetworkAccessManager(this);
connect(networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(on_post_answer(QNetworkReply*)));
networkManager->post(request, doc.toJson());

I get the simple success message here:


void MainWindow::on_post_answer(QNetworkReply *reply) {
QString msg;
QByteArray resp;
QNetworkReply::NetworkError error_type;

error_type = reply->error();
if (error_type == QNetworkReply::NoError) {
resp = reply->readAll();
msg = "Success - Response: " + resp;
}
else {
msg = "Error - Response: " + reply->errorString();
}
QMessageBox::information(this, "", msg);


All of that works as expected. But how can I listen on another URL for a response? I've tried the following:


Send a HTTP get to URL2 after URL1 post is complete...returns error
Send a HTTP post to URL2 with "" as data packet after URL2 post is complete...returns error


Is there a way to simply listen on URL2 using QNetworkAcessManager and have a signal fire if anything appears on URL2?

Thanks!

rhb327
12th April 2017, 01:27
Trying something more like this...i get the listen success message but onNewConnection() never triggers.



EchoServer::EchoServer(quint16 port, bool debug, QObject *parent) : QObject(parent),
m_pWebSocketServer(new QWebSocketServer(QStringLiteral("Echo Server"),
QWebSocketServer::NonSecureMode, this)),
m_debug(debug)
{
if (m_pWebSocketServer->listen(QHostAddress("http://127.0.0.1"), port)) {
//if (m_pWebSocketServer->listen(QHostAddress::Any, port)) {
if (m_debug)
qDebug() << "Echoserver listening on port" << port;
connect(m_pWebSocketServer, SIGNAL(newConnection()), this, SLOT(onNewConnection()));

jefftee
12th April 2017, 03:12
Is there a way to simply listen on URL2 using QNetworkAcessManager and have a signal fire if anything appears on URL2?
You have two signals you can use, QNetworkAccessManager::finished and QNetworkReply::finished, but neither "listen" on a particular URL. They are emitted when a request that *you* make finishes so that you can see the response, HTTP status codes, etc but it's not really listening on a URL, it's simply when the HTTP request you make has finished.

I've never seen what you are describing before, where one post results in two different responses and I don't think that's technically possible. Is the 2nd URL you are mentioning a web hook or something like that? If so, that's not a response from your post request and you won't see it in the response to your HTTP request.

If it's not a web hook or something like that, please indicate which RESTful web service you are using and I'll be happy to see more info about what you're describing.

rhb327
12th April 2017, 16:46
Agree, it's an odd architecture. It's a private cloud but basically I'm working on a desktop Qt simulator to learn about it. This simulator will eventually be an embedded device also using Qt. My understanding is my simulator coordinates with custom gateway software that sits between my program and AWS IoT (MQTT).

This gateway seems to POST to 127.0.0.1:5000/v1/iot as I can pick up a response using flask in python. This is the "URL2" response. My intent was to get the URL2 response directly in my simulator where I do successfully post to URL1 and receive a response. For an alternate, I could just have the python flask http server dump response in a file and have my Qt app read from there but I was still after the higher level of integration.

The documentation refers to URL2 as a REST endpoint (not sure that's a web hook).

Here's an example response I get in python/flask:


{u'requestType': u'getlinkqrcode', u'statusCode': u'200', u'response': {u'qrCode': u'WI7TXY', u'expiresIn': 3599, u'qrImagePath': u'/Users/yada/yada-1.7.3\\WI7TXY.PNG'}, u'requestId': u'333333'}
127.0.0.1 - - [12/Apr/2017 10:39:09] "POST /v1/iotresponse HTTP/1.1" 200 -

I think this means the gateway software is POSTing to my flask server so if I had Qt listening for this POST I could get this information.

Thanks for considering this oddball post!

jefftee
12th April 2017, 17:04
If the result of your HTTP POST is twofold: 1) A normal HTTP response that has the success/failure and data returned as a result and separately 2) the server does an HTTP post to a 2nd URL. You'll need to handle #1 as you are now, by connecting the QNetworkAccessManager::finished signal to a slot, but for #2, you'll essentially have to write a little web server that listens on 127.0.0.1 and port 5000, etc.

What still doesn't make sense to me is that 127.0.0.1 is a special address for the localhost and is not a routeable IP address... There should be no way for a server external to your local host that can connect to 127.0.0.1:5000, so something isn't quite making sense... If you had said that the server does an HTTP POST to your public IP address on a specific port, that would make sense to me, but it doesn't because you're saying it's a POST to 127.0.0.1.

Sorry I can't be of more help!

rhb327
13th April 2017, 23:46
Thanks for inputs...was I on the right track to "essentially have to write a little web server that listens on 127.0.0.1 and port 5000" with my EchoServer (post #2)? Are you able to point me to a simple web server example?

Thanks,
-Rich

jefftee
14th April 2017, 03:50
If you want to consume this HTTP POST from the server to 127.0.0.1 on port 5000, then you can do either as you suggested: 1) write a simple server using QTcpServer to consume the response or 2) Use your favorite web language and use apache or lighthttpd to just take the response and shove it into a database.

As far as web server examples, I seem to recall one of the Qt supplied samples might be a mini-webserver, but I'm sure that you can probably find an example from Google. I'd search, but just making a quick visit to the forum tonight... :)

Edit: I noticed your start at a mini-server uses web sockets... I have not really done anything with web sockets, but I believe it's specialized and not a general TCP socket method. I believe you'll have to write a good old QTcpServer that listens on 127.0.0.1 port 5000 and read the data from the socket, which will include the headers and payload, etc.