PHP处理Protobuf响应调用mergeFromString报Unexpected wire type错误求助
问题原因
- 核心原因是CURL配置项
CURLOPT_HEADER设置为true,该配置会让curl_exec()返回的结果同时包含HTTP响应头+响应体两部分内容,而mergeFromString()方法要求传入的参数必须是纯Protobuf序列化后的二进制响应体,混入响应头后自然会触发解析格式错误。 - 你打印出的
$curlResponse开头有乱码字符,就是HTTP响应头的二进制内容被当成字符串输出的表现,和你预期的纯Protobuf结构不符。 - 补充说明:你在proto文件中只定义了编号为2的字段不属于错误原因,Protobuf本身兼容忽略未定义的字段,这也是Protoman用相同proto可以正常解析的原因(Protoman会自动剥离HTTP响应头,只拿响应体做Protobuf解析)。
解决方法
方案1:直接修改CURL配置(推荐)
将CURLOPT_HEADER改为false,这样curl_exec()只会返回纯响应体内容,直接传入mergeFromString()即可正常解析:
$handle = curl_init($url); $curl_options = [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $body, CURLOPT_HEADER => false, // 修改该配置项即可 CURLOPT_VERBOSE => true ]; curl_setopt_array($handle, $curl_options); $curlResponse = curl_exec($handle); $responseMessage = new MyMessage(); $responseMessage->mergeFromString($curlResponse); curl_close($handle);
方案2:手动拆分响应头和响应体
如果你确实需要保留响应头用于其他逻辑,可以利用HTTP协议中响应头和响应体用\r\n\r\n分隔的规则手动拆分,取后半部分的响应体做解析即可:
$curlResponse = curl_exec($handle); // 拆分响应头和响应体,最多拆分2段避免响应体中出现分隔符被误拆分 list($headerContent, $responseBody) = explode("\r\n\r\n", $curlResponse, 2); $responseMessage = new MyMessage(); $responseMessage->mergeFromString($responseBody); curl_close($handle);
内容的提问来源于stack exchange,提问作者eniel.rod
相关产品推荐
相关产品推荐

