为啥 JsonCpp http 客户端在 201 响应代码上失败?
Posted
技术标签:
【中文标题】为啥 JsonCpp http 客户端在 201 响应代码上失败?【英文标题】:Why does JsonCpp http client fail on a 201 response code?为什么 JsonCpp http 客户端在 201 响应代码上失败? 【发布时间】:2019-08-14 09:34:28 【问题描述】:使用json-rpc-cpp 库,我正在使用wallet RPC 创建一个EOS 钱包。
HttpClient *temp = new HttpClient("http://127.0.0.1:30031/v1/wallet/create");
string res;
string str = "testwallet1";
temp->SendRPCMessage(str, res);
cout<<"res : "<<res<<endl;
它正在成功创建钱包,但之后我收到以下异常。
unknown file: Failure
C++ exception with description "Exception -32603 : INTERNAL_ERROR: : "PW5JcEu7jTXd7XUYLWkPuCUbr1pqBhusqRFfhSVToqUNcDuZ3oeYK"" thrown in the test body.
我发现HttpClient
收到了 201 响应代码。我不知道如何避免这种异常。有人知道吗?
【问题讨论】:
【参考方案1】:该问题是由 HttpClient::SendRPCMessage()
实现中的错误引起的。
在内部,HttpClient
使用 libcurl 进行 HTTP 处理,在SendRPCMessage()
实现的最后,检查curl_easy_perform()
是否成功:
long http_code = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
if (http_code != 200)
throw JsonRpcException(Errors::ERROR_RPC_INTERNAL_ERROR, result);
如您所见,SendRPCMessage()
为 ANY 200 以外的 HTTP 响应代码抛出异常。但 per the HTTP standard,ALL 2xx 响应代码表示成功,而不是只有 200。在这种情况下,response code 201 表示:
10.2.2 201 创建
请求已完成并导致创建新资源。 新创建的资源可以由响应实体中返回的 URI 引用,具有最具体的 URI对于 Location 标头字段给出的资源。响应应该包括一个实体,其中包含资源特征和位置列表,用户或用户代理可以从中选择最合适的一个。实体格式由 Content-Type 标头字段中给出的媒体类型指定。源服务器必须在返回 201 状态码之前创建资源。如果无法立即执行该操作,则服务器应该以 202 (Accepted) 响应来响应。
201 响应可能包含一个 ETag 响应头字段,指示刚刚创建的请求变体的实体标签的当前值,请参阅section 14.19。
这显然是SendRPCMessage()
的实现逻辑错误。 http_code
的检查应该更像这样:
if ((http_code / 100) != 2)
这会将所有 2xx 响应代码视为成功。
我已经向 json-rpc-cpp 的作者提交了一份错误报告:
#278 HttpClient::SendRPCMessage() throws ERROR_RPC_INTERNAL for successful HTTP responses
【讨论】:
【参考方案2】:201
基本表示你的请求处理成功了。正如this source 解释的那样:
201 CREATED 请求已完成,并导致创建一个或多个新资源。
请求创建的主要资源由以下任一标识 响应中的 Location 标头字段,或者,如果没有 Location 字段 通过有效的请求 URI 接收到。
201 响应负载通常描述并链接到 创建的资源。请参阅 RFC7231 的第 7.2 节以了解 验证器标头字段的含义和用途,例如 ETag 和 Last-Modified,在 201 响应中。
当对响应数据进行任何进一步处理时,必须抛出异常。 如果没有更多信息,我无法说出究竟是什么原因造成的。
【讨论】:
以上是关于为啥 JsonCpp http 客户端在 201 响应代码上失败?的主要内容,如果未能解决你的问题,请参考以下文章