Status code for "already exist" - web-services

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.

Related

Bad Certificate in soap response using UploadCertificate in AdvanceSecurity

I'm using the UploadCertificate message present in Onvif security service (AdvancedSecurity) https://www.onvif.org/specs/srv/security/ONVIF-Security-Service-Spec.pdf
Sniffing messages with wireshark, I noticed a "bad Request" response.
My code is
_tas__UploadCertificate tas__UploadCertificate_tmp;
_tas__UploadCertificateResponse tas__UploadCertificateResponse_tmp;
tas__UploadCertificate_tmp.Certificate.__ptr = certificate;
tas__UploadCertificate_tmp.Certificate.id = tas__CreatePKCS10CSRResponse_tmp.PKCS10CSR.id;
tas__UploadCertificate_tmp.Certificate.__size = tas__CreatePKCS10CSRResponse_tmp.PKCS10CSR.__size;
AddUsernameTokenDigest(deviceKeyStoreBindingProxy, NULL, GetUser(), GetPwd(), deltaT);
deviceKeyStoreBindingProxy->UploadCertificate(&tas__UploadCertificate_tmp, tas__UploadCertificateResponse_tmp)
in soap specification (link above) :
"If the device cannot process one of the uploaded certificates, it shall produce a BadCertificate fault and neither
store the uploaded certificates nor private key in the keystore. The BadCertificate fault shall not be produced
based on the mere fact that the device’s current time lies outside the interval defined by the notBefore and
notAfter fields as specified by [RFC 5280], Sect. 4.1."
But in section 4.1 I don't see any useful information.
my question is:
where is the field notBefore and notAfter? Any suggestion how to fix my code?

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;

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?
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.

Dialogflow webhook set parameter value

My intent sends a webhook as part of slot filling if a parameter is missing from the user query. My webhook then uses logic to estimate the value of the parameter. How can I return this parameter as part of the WebhookResponse object? I am using the C# client library in an ASP.NET Core app.
My code is:
string fulfillmentText;
WebhookRequest request = null;
using (var reader = new StreamReader(Request.Body))
{
request = jsonParser.Parse<WebhookRequest>(reader);
}
//If Parameter-1 has no value
if (request.QueryResult.Fields["Parameter-1].StringValue.Length == 0)
{
fulfillmentText = "I have guessed the value of Parameter-1";
//I apply some logic that is unimportant to this question
//For the sake of simplicity, say I estimate the value of Parameter-1 to be "foobar"
//I want to be able to give the parameter this value like this:
parameter["Parameter-1"] = "foobar"
}
UPDATE
So, I have pretty much got it all working using Prisoner's method. I will retry sid8491's at some point too. My intent is trying to obtain a user's address. I have required custom entities to retrieve the street number, street name, suburb and state.
Without creating any contexts myself, the following context is automatically generated by Dialogflow: projects/telebot-pianomoves-v1/agent/sessions/2b42cbc8-2418-4231-e4c0-bd3a175f2ea8/contexts/1320fe35-4329-4176-b136-9221dfaddd4e_id_dialog_context. I receive this context in my webhook, and can then CHANGE the value of a parameter. Let's assume $Suburb_Entity had no value in the webhook request and my code then returned the above context with the a new value for Suburb_Entity. My code successfully changes the Suburb_Entity from "" to aspendale as can be seen by the webhook response json:
Now the odd thing is, although I changed the Suburb_Entity to an actual value in the outputContext of my webhook response, the actual parameter $Suburb_Entity only changes to the new value of Suburb_Entity from the outputContext on the NEXT detect intent request. So, keeping in mind the fact that I returned the new Suburb_Entity in the outputContext of the webhook response, this is the detect intent response I get - noting that $Suburb_Entity is yet to be changed:
On the next detect intent request, the webhook request parameter Suburb_Entity is set to aspendale and $Suburb_Entity also equals aspendale. The important thing about this, is $Suburb_Entity only changed to the outputContext parameter value on the NEXT detect intent request, of which would have triggered another webhook. $Suburb_Entity did not change during the same detect intent request as when I modified the outputContext parameter Suburb_Entity, but in the next. This leads me to believe that somehow, $Suburb_Entity inherits parameter values from this automatically generated context. The issue here, is that when my webhook responds with the outputContext paramter Suburb_Entity equalling aspendale, $Suburb_Entity does not change to this value until the next request. This means that if all the other parameters have values set, but $Suburb_Entity is yet to have changed value, then allRequiredParamsSet == false. If I return the Suburb_Entity in the outputContext, I want it to immediately change the value of $Suburb_Entity without requiring another detect intent request so that allRequiredParamsSet == true in such a circumstance. I tried setting the default value by doing this (it didn't work):
An alternative of course would be a way for me to force allRequiredParamsSet = true. I save the parameter values from this the context parameter, not the actual response. So I don't need $Suburb_Entity, I just want the intent to think that it has a value.
Cheers
When you use a webhook for "slot filling", the intention is that you return the prompts you want to ask the user for and continue to use the same Intent to handle the responses. You're not expected to create values yourself.
If you want to "fill in" some answers that are used in the static "response" section of the Dialogflow Intent, or if you just want to record the answers so you can use them later, you can set the parameters of a Context. In the response string, you can refer to this value as #context-name.parameter-name.
Update
I don't know the internal mechanics of slot filling, but it doesn't surprise me that setting a value in the internal context for the input parameters doesn't "register" until the next round of handling the Intent.
The webhook for slot filling isn't intended to create values - it is intended to handle values and create prompts for the user to respond to. Intents are generally about processing user inputs and webhooks about handling them.
My workaround suggested that if you want this for output, you use the context for output.
There are multiple steps for get it done:
First give an event in intent
Check your condition in webhook
If your condition is satisfied, invoke the intent by calling the event from webhook which you have defined in step 1
Pass the paylaod (in json format) along with event calling, give parameters in the payload
In the intent, give default value of parameter as #eventName.parameterName
Hope it helps.

Loopback 'err' Object

I am using a loopback remote method to parse data that I get from a REST endpoint . I am trying to understand the 'err' object that is passed to the callback . The second parameter is the response object - whatever I get from the response and the third is the context object - that contains the status code apart from the request object. When is the 'err' object set by loopback ? Suppose I get a non 200 code from the REST endpoint - err is still null. I check the status code from the context object and then set err on my own.
Can you provide an example of your remote method implementation?
Remote methods don't receive an error object so I'm thinking I'm not quite understanding your question and I would need a bit more information to be helpful.
Remote method strongloop docs here: https://docs.strongloop.com/display/public/LB/Remote+methods