Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Poco::Net::HTTPClientSession json data Content-Type not received

So I am developing a server side Nodejs/expressjs app and a clientside c++/Poco app. I've managed to create a session between where the server is hosted and client. However, any time i try to send my JSON payload, express.js shows req.body as empty.

Google didn't reveal much besides that Content-Type was likely not being transmitted correctly and it appears so. I do set it explicitly but apparently i'm missing a step.

client-side

void upload(std::list<std::string>& args) {
    if (args.size() == 0 || args.front() == "--help") {
        help("upload");
        return;
    }

    std::string repo = args.front();
    args.pop_front();

    std::string name, language;
    auto depends = getDepends(name, language);

    // start making the poco json object here
    Poco::JSON::Object obj;
    obj.set("name", name);
    obj.set("url", repo);

    Poco::URI uri("http://url-of-my-server:50001/make_repo");
    std::string path(uri.getPathAndQuery());


    if (path.empty()) path = "/";

    HTTPClientSession session(uri.getHost(), uri.getPort());
    HTTPRequest request(HTTPRequest::HTTP_POST, path, HTTPMessage::HTTP_1_1);
    HTTPResponse response;

    std::ostream& o = session.sendRequest(request);

    std::cout << response.getStatus() << " " << response.getReason() << std::endl;

    session.setKeepAlive(true);
    request.setContentType("application/json");  // definately set Content-Type right?
    obj.stringify(std::cout);                    // can confirm it is spitting out the valid json here
    obj.stringify(o);                            // place the json in the request stream

    std::istream& s = session.receiveResponse(response);

    // do stuff with returned data
}

server:

var express = require('express');
var app = express();
var bodyParser = require('body-parser');

var database = require('./database.js');  // one of my files
var connection = database.connection;
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());

var port = 50001;   // explicitly set port because environment port kept forcing port 3000

// just a callback to make sure i'm connected to my sql server
connection.query('SELECT 1',function(err, rows) {
    if(err) {
        console.error("Could not connect to the database.");
    } else {
        console.log('connected to database: ' + connection.threadId);
    }

    app.get('/', function(req, res){
        res.send('hello world');
    });

    // this is the route I invoke, (and it is definately invoked)
    app.post('/make_repo', function(req, res, next) {

        console.log(req.headers); // this always returns '{ connection: 'Close', host: 'url-of-my-server:50001' }
        console.log(req.body); // this always returns '{}'

    });

    var listener = app.listen(port, function() {
        console.log("port: " + listener.address().port);
    });

});

It appears that this is on Poco's end because I can transmit test data from postman and it reports just fine. I also setKeepAlive to true on Poco and that appears to be ignored as well. Has anyone used Poco enough to help?

like image 967
FatalCatharsis Avatar asked Mar 07 '26 21:03

FatalCatharsis


1 Answers

Got a little confused by the stateful stream style of communication. It is http and technically still a stateless connection. All of the information about the request, EXCEPT THE BODY, must be done before you send the initial request.

HTTPClientSession session(uri.getHost(), uri.getPort());
HTTPRequest request(HTTPRequest::HTTP_POST, path, HTTPMessage::HTTP_1_1);
HTTPResponse response;

std::stringstream ss;
obj.stringify(ss);
request.setKeepAlive(true);
request.setContentLength(ss.str().size());
request.setContentType("application/json");  // definately set Content-Type right?

std::ostream& o = session.sendRequest(request);
obj.stringify(o);             // can confirm it is spitting out the valid 

std::cout << response.getStatus() << " " << response.getReason() << std::endl;

Also, needed to set the contentLength which I'd tried before but wasn't working due to the content-type not being sent properly. After the content length and type were set right, the server received correctly without a hitch.

like image 74
FatalCatharsis Avatar answered Mar 09 '26 10:03

FatalCatharsis



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!