C++之——curl发送xml到https地址问题总结

前提

所遇问题为调用webservice接口地址是https类型引发,程序C++。没有用gsoap生成代码来开发客户端,因为考虑到维护不方便,采用http封装发送

【问题一】*(难度系数)

描述:调用地址为https,直接发送会报验证证书失败。
说明:查阅资料总结很多情况作为客户端是不需要加载证书去验证的,如果是双向验证的才需要生成客户端证书进行验证,这里没有用到。我这边是单向的,所以直接设置为不验证证书和主机就行
解决:调整代码,调整curl发送报文时不验证证书:

	curl_easy_setopt(curl,CURLOPT_NOSIGNAL,1);
	curl_easy_setopt(curl,CURLOPT_USE_SSL,1);
	curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,0); //设定为不验证证书
	curl_easy_setopt(curl,CURLOPT_SSL_VERIFYHOST,0);

`

【问题二】**

描述:发送报文后,返回报错:500,服务器内部错误,具体是报:no SOAPAction header。如下图:
这里写图片描述

解决方法:在发送报文头加上SOAPAction属性
_headers = curl_slist_append(_headers,“SOAPAction: “””);
注意:报文头添加属性是不需要进行换行,直接追加就行。
即在代码中要这样写:

	std::string strConnect = "Connection: close";
	std::string strUserAgent = "User-Agent: gSOAP/2.7";
	std::string strConnectionType = "Content-Type: text/html; charset=UTF-8;";
	std::string strSoapAction = "SOAPAction: \"\"";

而不是:

	std::string strConnect = "Connection: close\r\n";
	std::string strUserAgent = "User-Agent: gSOAP/2.7\r\n";
	std::string strConnectionType = "Content-Type: text/html; charset=UTF-8;\r\n";
	std::string strSoapAction = "SOAPAction: \"\"\r\n";

如果是上面加了\r\n的写法,即便是调试发现报文头里还是有SOAPAction属性的,但是不会起作用!!!(这个与我代码对报文头处理有关,具体怎么写不确定可以尝试打印下格式,再调整)

【问题三】**

描述:发送报文后会报错:
org.xml.sax.SAXParseException:lineNumber:1;columnNumber: 1;Content is not allowed in prolog.如下图:
这里写图片描述

解决:网上找了资料发现是认为是发送报文的开始

 <?xml version="1.0" encoding="GBK"?>

  • 前有空格,建议用notepad++打开修改编码为utf-8无BOM格式。尝试后无效。
  • 抓包分析对比报文格式,发现原因可能是自定义报文头有换行或者空格造成,类似于问题二那种错误写法,修改正确即可
【问题四】****

描述:发送报文后报错:org.xml.sax.SAXException: SimpleDeserializer encountered a child element, which is NOT expected, in something it was trying to deserialize.如下图:

这里写图片描述

过程:网上查找资料说是与不能反序列化有关,而且给出的方法基本都是java解决方案,如果有java的可以尝试下,而我用的是c++,然后尝试打通网络(这是公司环境无法直接用工具测试,无奈配置了隧道才可以)用soupui直接发送,查看报文格式
解决:最后对比发现程序发送报文与用工具直接发送报文内容一致,唯一不同的是工具发送会将报文用

<![CDATA[  XXXXX  ]]>

抱起来,哦不,包起来(XXX为报文内容)。最后修改代码拼接报文格式,也将报文包起来,尝试发送,问题解决!

提示

如果有类似我上述工作的操作,建议先采用curl命令直接发送报文,避免来回修改代码编码等等工作的繁琐。同时如果也需要curl发送不验证安全证书的话,需要加上-k参数,参考如下:

echo '<?xml version= "1.0" encoding="GBK"?>XX报文XX'|curl -k -X POST -H 'SOAPAction:\"\" Accept-Encoding: gzip,deflate User-Agent: gSOAP/2.7 Content-type:text/xml' -d @- https://111.111.111.111:8888/services/ABC?wsdl

如果环境无法直接执行curl命令。可以参考我的另一篇文章:
https://blog.csdn.net/Cow_cz/article/details/81128920

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
C++ 中,使用 libcurl发送 HTTP 请求是一种常见的网络通信操作。libcurl 是一个功能强大的库,支持多种协议如 HTTP、HTTPS、FTP等。以下是一个简单的例子,展示如何使用 libcurl 发送 GET 或 POST 请求: ```cpp #include <curl/curl.h> size_t write_callback(char *data, size_t size, size_t nmemb, std::string* userp) { (*userp).append(data, size * nmemb); return size * nmemb; } void send_http_request(const char* url, const char* request_type, const char* data = nullptr) { CURL* curl = curl_easy_init(); if (curl) { std::string response; curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); // 设置回调函数接收响应 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); if (request_type == "POST") { curl_easy_setopt(curl, CURLOPT_POST, 1); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data); // 如果需要设置请求头,可以添加下面这行 // curl_easy_setopt(curl, CURLOPT_HTTPHEADER, ...); } CURLcode res = curl_easy_perform(curl); if (res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } else { printf("Response: %s\n", response.c_str()); } curl_easy_cleanup(curl); } } ``` 在这个示例里,`send_http_request` 函数接受 URL、请求类型(GET or POST)、以及可选的数据。对于 POST 请求,还需要设置 `CURLOPT_POSTFIELDS` 来传递数据。 使用这个基础框架,你可以根据实际需求调整参数和请求内容。例如,如果你想发送 JSON 数据,可以先将其编码成字符串作为 POST 数据。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值