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

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?

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

201 basically means that your request was processed successfully. As this source explains:
201 CREATED The request has been fulfilled and has resulted in one or more new resources being created.
The primary resource created by the request is identified by either a
Location header field in the response or, if no Location field is
received, by the effective request URI.
The 201 response payload typically describes and links to the
resource(s) created. See Section 7.2 of RFC7231 for a discussion of
the meaning and purpose of validator header fields, such as ETag and
Last-Modified, in a 201 response.
The exception must be thrown when any further processing is applied to the response data.
I can't tell what exactly causes this without more information.

Related

azure:storage:storage_exception m_http_status_code = 0 when using invalid credentials

In the following c++ code snippet a storage_exception is thrown when invalid credentials are used to create the cloud_storage_account object which is expected, what's not expected is that the caught storage exception doesn't contain any useful information (http_status_code = 0).
What is the expected result in this situation (http status of 0 or 403)?
I haven't found in the documentation what's to be expected here.
try {
azure::storage::storage_credentials storageCredentials
= azure::storage::storage_credentials(azureAccountName, azureAccountKey);
azure::storage::cloud_storage_account storageAccount
= azure::storage::cloud_storage_account(storageCredentials, useHTTPS);
if (true == storageAccount.is_initialized()) {
blobClient = storageAccount.create_cloud_blob_client();
azure::storage::cloud_blob_container blobContainer = blobClient.get_container_reference(L"ContainerName");
blobContainer.exists();
}
}
catch (azure::storage::storage_exception & storageException) {
web::http::status_code statusCode = storageException.result().http_status_code();
}
Output in VS debugger:
No http status code
Answering this as Microsoft have finally replied to my question here.
If a nonexistent storage account is provided, then the endpoint is
invalid and DNS record cannot be found. What will happen is up to
the underlying HTTP client, usually timeout. The HTTP status code in
exception would be undefined, since the HTTP connection isn't
established at all.
If the shared key is not a valid base64-encoded string,
std::runtime_error will be thrown.
If the shared key is a valid base64-encoded string but the key is
incorrect (e.g. revoked), HTTP status code 403 will be returned.
Network issue, this is pretty much the same as case 1.

Unable to handle responses using 'regex' http status codes in Siddhi

I was trying to handle/receive all the responses with the 2xx status codes with the 'regex' http response code '2\d+' but it was not handling it as expected.When I enter the http status code directly (for example '202') then it was handling the response. But I want 'regex' to handle it.
#source(type='http-response', sink.id='Response',http.status.code='2\\d+', #map(type='json',#attributes(success = 'status')))
#sink(type='log')
define stream ResponseStream(success string);
Here is the response am getting when i use regex code.
[2019-11-26 07:16:42,705] ERROR
{org.wso2.extension.siddhi.io.http.source.HttpResponseMessageListener}
- No source of type 'http-response' that matches with the status code '202' has been defined. Hence dropping the response message.
Kindly help me to handle this using regex codes.
In your Siddhi query you have given status code as '2\\d+'. Please change it to '2\d+'

Postman Error: Value is not a valid byteString

I am trying to invoke a POST web service via Postman and I am getting the following error.
Error while sending request: Failed to execute setRequestHeader on
XMLHttpRequest: Value is not a valid ByteString.
Request Headers
X-PW-AccessToken:{{api_token}}
X-PW-Application:developer_api
X-PW-UserEmail:{{api_email}}
Content-Type:application/json
Request Body
{
"page_size": 25
}
Can anyone tell me why I am getting this error, and how can I get rid of this?
I think Http protocol's header can only post ByteString (what is ByteString? I think it is ASCII).
So if you have other char, for example, 汉字. if you put '汉字' add to Http Header the error 'Value is not a valid ByteString' happen!
Solove: You can use the encodeURI function to encode the String in the client, and then, You can use URLdecode.decode()(java) to decode the header information in the server.

Should RESTful 'PATCH' operation return something?

I am struggling what is the best practice for PATCH method.
I see couple of possibilities:
Return HTTP status code 200 OK with updated object.
Return HTTP status code 204 No Content.
What would be the best one?
The specification states:
The 204 response code is used because the response does not carry a
message body (which a response with the 200 code would have). Note
that other success codes could be used as well.
Which just means you may decide to return a body or not, the response codes should then be 200 or 204 respectively. Neither is better or worse than the other. You may find that it is practical to just return the changed content, so the client does not have to make a new request to get the new content.
Note: using the PATCH is quite tricky, as you must define a mime-type for applying change-sets to your resource. This may not be what you want. More often than not, PATCH can be solved by just creating a new resource that should have been a resource anyway.

Status code for "already exist"

Similar to HTTP status code 500-Internal Server Error,200-OK,201 Created etc... Is there any code for "Already Existing" to be giver as response from server, While trying to create a new object (if the object with same values exists) ??
If your client sends an If-None-Match-header like described here:
The meaning of "If-None-Match: *" is that the method MUST NOT be
performed if the representation selected by the origin server [...]
exists, and SHOULD be performed if the representation does not exist
Then if the same resource exists, you can respond with a 412 Precondition Failed:
if "*" is given and any current entity exists for that resource, then the
server MUST NOT perform the requested method, unless required to do
so because the resource's modification date fails to match that
supplied in an If-Modified-Since header field in the request.
[...] the server MUST respond with
a status of 412 (Precondition Failed).
Instead of * (which means "if anything exists") you can also use an Etag, which basically is a checksum of the entity that is calculated by the server. You can detect identical entities by identical Etags.