Poco::Net::HTTPClientSession json 数据 Content-Type 未收到

Posted

技术标签:

【中文标题】Poco::Net::HTTPClientSession json 数据 Content-Type 未收到【英文标题】:Poco::Net::HTTPClientSession json data Content-Type not received 【发布时间】:2016-01-24 11:36:48 【问题描述】:

所以我正在开发一个服务器端 Nodejs/expressjs 应用程序和一个客户端 c++/Poco 应用程序。我设法在托管服务器的位置和客户端之间创建了一个会话。但是,每当我尝试发送 JSON 有效负载时,express.js 都会将 req.body 显示为空。

除了 Content-Type 可能没有正确传输而且看起来确实如此之外,Google 并没有透露太多信息。我确实明确设置了它,但显然我错过了一步。

客户端

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

服务器:

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);
    );

);

看来这已经到了 Poco 的尽头,因为我可以从邮递员那里传输测试数据并且它报告得很好。我还在 Poco 上将KeepAlive 设置为 true,这似乎也被忽略了。有没有人用过 Poco 来提供足够的帮助?

【问题讨论】:

【参考方案1】:

对有状态的流式通信有点困惑。它是 http 并且在技术上仍然是无状态连接。必须在发送初始请求之前完成有关请求的所有信息,除了正文。

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;

另外,需要设置我之前尝试过但由于内容类型未正确发送而无法正常工作的 contentLength。正确设置内容长度和类型后,服务器可以顺利接收。

【讨论】:

感谢您发布此问答 - 不明白为什么有人会在没有评论的情况下对其投反对票 - 对于 Poco 来说,示例已经足够少了,没有这种气馁。但是......最后一行可能如何工作?也就是说,response 似乎没有连接到任何东西 - 是否缺少代码? 哦,是的,实际上缺少一些行。 Prolly 为什么我被否决了。看看this gist,它展示了一个完整的例子。 是的 - 我意识到需要有一个 session.receiveResponse() 呼叫......但是 obj.stringify(ss) 仍然缺少一些东西 - 这些数据是如何进入请求的?最好使用经过全面测试的解决方案来编辑​​您的答案 @omatai - 该要点包含现在在生产代码中使用的内容(省略了敏感内容)。 stringstreams 的目的只是获取将放入缓冲区的 json 内容的长度。 obj.stringify 将 json 对象“obj”的内容粘贴到您设置内容长度的字符串流中。稍后,当您调用 session.sendRequest(request) 时,您将获得它将用于流式传输数据的实际 ostream。对 obj.stringify(o) 的调用是数据在请求中的结束方式。有时间我会编辑我的答案。

以上是关于Poco::Net::HTTPClientSession json 数据 Content-Type 未收到的主要内容,如果未能解决你的问题,请参考以下文章