Search code examples
c++httpclientblockchainjson-rpceos

Why does JsonCpp http client fail on a 201 response code?


Using the json-rpc-cpp library, I am creating an EOS Wallet using wallet RPC.

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;

It is creating the wallet successfully, but after that I am getting the following exception.

unknown file: Failure
C++ exception with description "Exception -32603 : INTERNAL_ERROR: : "PW5JcEu7jTXd7XUYLWkPuCUbr1pqBhusqRFfhSVToqUNcDuZ3oeYK"" thrown in the test body.

I found that HttpClient receives a 201 response code. I have no idea how to avoid that exception. Does anyone have any idea?


Solution

  • The issue is caused by a bug in the HttpClient::SendRPCMessage() implementation.

    Internally, HttpClient uses libcurl for its HTTP handling, and at the very end of the SendRPCMessage() implementation is the following check if curl_easy_perform() is successful:

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

    As you can see, SendRPCMessage() throws an exception for ANY HTTP response code other than 200. But per the HTTP standard, ALL 2xx response codes indicate success, not just 200. In this case, response code 201 means:

    10.2.2 201 Created

    The request has been fulfilled and resulted in a new resource being created. The newly created resource can be referenced by the URI(s) returned in the entity of the response, with the most specific URI for the resource given by a Location header field. The response SHOULD include an entity containing a list of resource characteristics and location(s) from which the user or user agent can choose the one most appropriate. The entity format is specified by the media type given in the Content-Type header field. The origin server MUST create the resource before returning the 201 status code. If the action cannot be carried out immediately, the server SHOULD respond with 202 (Accepted) response instead.

    A 201 response MAY contain an ETag response header field indicating the current value of the entity tag for the requested variant just created, see section 14.19.

    This is clearly a logic error in the implementation of SendRPCMessage(). The check of the http_code should be more like this instead:

    if ((http_code / 100) != 2)
    

    This will treat all 2xx response codes as success.

    I have filed a bug report with json-rpc-cpp's author:

    #278 HttpClient::SendRPCMessage() throws ERROR_RPC_INTERNAL for successful HTTP responses