RESTful API, C++restSDK, JSON in C++ - c++

I am trying to use THIS RESTful API: https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md
To do this, I am using THIS C++ SDK: https://github.com/Microsoft/cpprestsdk
The Binance API returns everything as JSON, which is where I think my issue lies.
My code is here: https://pastebin.com/SeBAxvA0
I think the error is here in this function (commented as well in pastebin):
void print_test(json::value const & value){
if(!value.is_null()){
//I am doing something wrong here I'm pretty sure.
auto response = value[L"responseData"];
//"responseData" is probably not what should be here I think?
auto results = response[L"serverTime"];
wcout << results.as_integer() << endl;
}
}
Basically, I am trying to just test out this API by doing a simple GET method for the server time from the Binance API. According to the Binance documentation:
Check server time
GET /api/v1/time
Test connectivity to the Rest API and get the current server time.
Weight: 1
Parameters: NONE
Response:
{
"serverTime": 1499827319559
}
So I would like to do a GET request for that JSON, and then have my C++ program output the value of serverTime. When I try to run my code as is, I get an error saying:
error: no viable overloaded operator[] for type
'const json::value'
auto response = value[L"responseData"];
However, I am following along with an example from the C++restSDK found here:
http://mariusbancila.ro/blog/2013/08/02/cpp-rest-sdk-in-visual-studio-2013/
I think my issue has something to do with the two lines under the comment I made on line 45 in my pastebin. Presumably, I am assigning the wrong values to one or both of the variables under that line. I know this is a pretty specific help request, but does anyone know what I'm doing wrong and how to get the value of serverTime to display?

I solved this issue on my own after much digging :)
Error was in this function and it is now fixed with this code:
void print_test(json::value const & value){
if(!value.is_null()){
json::value test = value;
cout << test["serverTime"] << endl;
}
}

Related

How to store back the nested response data in protobuf?

I'm using GRPC to remote call the database and store the data in the response format given by the .proto file. My program is based on CPP programming:
// similar .proto file
message FinalResponse
{
repeated IntermediateResponse finals = 1;
}
message IntermediateResponse
{
string name = 1;
InitialResponse foo = 2;
}
enum InitialResponse
{
COUNTRY_UNKNOWN = 0;
COUNTRY_INDIA = 1;
}
For my case, the request message is empty(no field) so didn't displayed here. I went through the protocol buffer documentation and tried this:
// firstly called the database and stored the intermediateResponse in a vector<pair<string, string>> data
//pseudo-code below:
FinalResponse result;
for cur_data in data:
{
IntermediateResponse *interResp = result.add_finals();
interResp->set_name(cur_data.first);
interResp->set_foo(static_cast<InitialResponse>(cur_data.second));
}
When I'm executing this, there is no syntax/build error but grpc status is saying we didn't get any response back:
ERROR - (12) No message returned for unary request
I want to clarify that service was running from the server side and client is able to detect that service as well, I'm suspecting that maybe the returned data through database is not properly stored in the response message and so GRPC is deducing that we didn't get back any data. Please suggest some work around for this?
Looks like it was the server side issue probably, now with the same changes, it is able to store the response properly.
Maybe server went down for some time and returned error.

Camunda- Acessing to a specific json element

I would like to obtain in a response of http-connector, only the “number” element, but I cannot obtain it.
I’m trying to have an inline Javascript with the following statement:
S(response).prop(“status”).prop(“number”).numberValue();
but it shows an error: SPIN/JACKSON-JSON-01004 Unable to find ‘status’
What it’s wrong in the statement?
Rest response to parse:
{
“status”: {
“number”: 200,
“type”: “OK”,
“description”: “Status OK”
}
}
There is no obvious issue with your expression. I would debug further to see if response indeed contanis the Json string you posted. The error shows that response exists, but the content differs.
This working example I just created may help you:
https://github.com/rob2universe/camunda-http-connector-example
If this does not help, you could share more info, e.g. the process model, server log, service you are calling...

How to specify the database in an ArangoDb AQL query?

If have multiple databases defined on a particular ArangoDB server, how do I specify the database I'd like an AQL query to run against?
Running the query through the REST endpoint that includes the db name (substituted into [DBNAME] below) ie:
/_db/[DBNAME]/_api/cursor
doesn't seem to work. The error message says 'unknown path /_db/[DBNAME]/_api/cursor'
Is this something I have to specify in the query itself?
Also: The query I'm trying to run is:
FOR col in COLLECTIONS() RETURN col.name
Fwiw, I haven't found a way to set the "current" database through the REST API. Also, I'm accessing the REST API from C++ using fuerte.
Tom Regner deserves primary credit here for prompting the enquiry that produced this answer. I am posting my findings here as an answer to help others who might run into this.
I don't know if this is a fuerte bug, shortcoming or just an api caveat that wasn't clear to me... BUT...
In order for the '/_db/[DBNAME/' prefix in an endpoint (eg full endpoint '/_db/[DBNAME/_api/cursor') to be registered and used in the header of a ::arangodb::fuerte::Request, it is NOT sufficient (as of arangodb 3.5.3 and the fuerte version available at the time of this answer) to simply call:
std::unique_ptr<fuerte::Request> request;
const char *endpoint = "/_db/[DBNAME/_api/cursor";
request = fuerte::createRequest(fuerte::RestVerb::Post,endpoint);
// and adding any arguments to the request using a VPackBuilder...
// in this case the query (omitted)
To have the database name included as part of such a request, you must additionally call the following:
request->header.parseArangoPath(endpoint);
Failure to do so seems to result in an error about an 'unknown path'.
Note 1: Simply setting the database member variable, ie
request->header.database = "[DBNAME]";
does not work.
Note 2: that operations without the leading '/_db/[DBNAME]/' prefix, seem to work fine using the 'current' database. (which at least for me, seems to be stuck at '_system' since as far as I can tell, there doesn't seem to be an endpoint to change this via the HTTP REST Api.)
The docs aren't very helpful right now, so just incase someone is looking for a more complete example, then please consider the following code.
EventLoopService eventLoopService;
// adjust the connection for your environment!
std::shared_ptr<Connection> conn = ConnectionBuilder().endpoint("http://localhost:8529")
.authenticationType(AuthenticationType::Basic)
.user(?) // enter a user with access
.password(?) // enter the password
.connect(eventLoopService);
// create the request
std::unique_ptr<Request> request = createRequest(RestVerb::Post, ContentType::VPack);
// enter the database name (ensure the user has access)
request->header.database = ?;
// API endpoint to submit AQL queries
request->header.path = "/_api/cursor";
// Create a payload to be submitted to the API endpoint
VPackBuilder builder;
builder.openObject();
// here is your query
builder.add("query", VPackValue("for col in collections() return col.name"));
builder.close();
// add the payload to the request
request->addVPack(builder.slice());
// send the request (blocking)
std::unique_ptr<Response> response = conn->sendRequest(std::move(request));
// check the response code - it should be 201
unsigned int statusCode = response->statusCode();
// slice has the response data
VPackSlice slice = response->slices().front();
std::cout << slice.get("result").toJson() << std::endl;

Delphi / C++Builder 10.2.3 RESTRequest POST

Does anyone have experience with TRESTRequest components? I am trying to POST a JSON string in the request body.
If I do not use TOAuth2Authenticator, it return back a MISSING_CREDENTIALS error. When I try to use TOAuth2Authenticator linked to the TRESTClient, with an access_token, it gives me this error:
I did the same request with POSTMAN, it work fine. And also, it works fine with TIdHTTP as well. But not with TRESTRequest.
Please let me know if you have experience before I report it as a bug.
After some playing around, the answer should be as follows.
String StrBody="{\"Key\": \"A123\",\"Total\": 100.00,\"Deductions\": 100.00}";
SubmitAuthenticator->AccessToken = StrAccessToken;
SubmitRESTClient->BaseURL = "https://testsite.com";
SubmitRESTRequest->Method = Rest::Types::rmPOST;
SubmitRESTRequest->Params->Items[0]->Value = StrBody;
SubmitRESTRequest->Execute();

Python urllib3 Error Handling

I'm fairly new to Python and would like some guidance on how to deal with authentication errors with urrlib3 on Python 2.7. My current use case is using SNAPI to auto create ServiceNow tickets. To do this I have the following snippet of code to use my username/password and get a token to log in.
r = session.post(auth_url, json=login_data, verify=False)
web_token = r.text
This is working fine but I want a cleaner way of notifying myself if there is an error within the code. If the username/password is incorrect, I get this back from the SN web server.
{
"error": "Authentication failure"
}
Originally I was going to use a try/exception but it seems like that wouldn't work very well in this case since the code is working correctly, it's just not the input I was expecting. So my second thought was doing something along the lines of:
if r.text does not contain "error"
then continue on my doe
else send an email telling me the error code
Before writing the code for that, I wanted to see if this is the best method for this type of error handling or if I should be going down another route.
Thanks,
Eric
I spoke with a friend and he recommended the following method which seems to work very well and is a lot cleaner than doing an if/match statement.
try:
r = session.post(auth_url, json=login_data, verify=False)
web_token = r.text
r.raise_for_status()
except Exception as e:
print(e)