C++使用POCO发起POST请求状态200但receiveResponse抛Poco::Net::NoMessageException
异常触发原因
- 核心协议不匹配:你请求的目标地址是HTTPS协议,但代码中使用了仅支持HTTP的
Poco::Net::HTTPClientSession发起请求,没有完成TLS握手流程,服务端直接断开连接,导致无法读取响应报文,触发NoMessageException。你之前打印的200 OK是Poco::Net::HTTPResponse对象的默认初始化值,并非服务端真实返回的状态。 - 调用逻辑错误:你在执行
session.receiveResponse(response)之前就调用了response.getStatus()、response.getReason()方法,receiveResponse才是负责从网络连接中读取响应头、填充response对象的接口,提前访问只会拿到默认值,也不会提前触发响应读取逻辑。
解决方案
按以下步骤修改代码即可解决问题:
- 替换HTTP会话类为HTTPS专用类,同时初始化NetSSL库上下文(使用HTTPS必须依赖Poco的NetSSL模块,编译时要链接对应的库)
- 调整响应信息打印的顺序,放在
receiveResponse调用之后 - 请求体写入完成后调用
flush()确保数据全部发送到网络
修正后代码示例:
// 需要引入HTTPS相关头文件 #include <Poco/Net/HTTPSClientSession.h> #include <Poco/Net/SSLManager.h> #include <Poco/Net/AcceptCertificateHandler.h> #include <Poco/SharedPtr.h> // 初始化SSL上下文(程序启动时执行一次即可) Poco::SharedPtr<Poco::Net::InvalidCertificateHandler> pCertHandler = new Poco::Net::AcceptCertificateHandler(false); Poco::Net::Context::Ptr pContext = new Poco::Net::Context(Poco::Net::Context::TLS_CLIENT_USE, "", "", "rootcert.pem"); Poco::Net::SSLManager::instance().initializeClient(0, pCertHandler, pContext); //Uri for fake tests Poco::URI uri("https://fakestoreapi.com/products"); // 替换为HTTPSClientSession Poco::Net::HTTPSClientSession session(uri.getHost(), uri.getPort()); session.setKeepAlive(true); session.setTimeout(Poco::Timespan(20,0)); std::string path(uri.getPathAndQuery()); if(path.empty()) path = "/"; Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_POST, path, Poco::Net::HTTPMessage::HTTP_1_1); request.setContentType("application/json"); Poco::JSON::Object jsonObj; std::stringstream strStream; //Dummy data jsonObj.set("title", "Test product"); jsonObj.set("price", "1520"); jsonObj.set("category", "electronics"); jsonObj.stringify(strStream); request.setContentLength(strStream.str().size()); std::ostream& os = session.sendRequest(request); os << strStream.str(); os.flush(); // 确保请求体全部发送 Poco::Net::HTTPResponse response; // 先调用receiveResponse填充响应对象 std::istream& inputStream = session.receiveResponse(response); // 再打印响应信息 std::cout << "Response status = " << response.getStatus() << std::endl; std::cout << "Response Reason = " << response.getReason() << std::endl; std::cout << response.getContentLength() << std::endl; Poco::StreamCopier::copyStream(inputStream, std::cout);
注:示例中使用AcceptCertificateHandler是为了方便测试,生产环境请替换为合法的证书校验逻辑,避免安全风险。
内容的提问来源于stack exchange,提问作者MHerreraJ
相关产品推荐
相关产品推荐

