How to post JSON to a URL using the Servoy Framework - frameworks

The Servoy Framework does not support standard methods of calling a URL (eg: AJAX, JQuery, etc.). How does one go about posting a JSON object to a URL?

The Servoy JavaScript framework relies on the http plugin (included as aprt of Servoy) to make HTTP Posts.
Here is some sample code of how to post JSON to an API using Servoy. I have also included some basic error handling. Refer to the code comments for explanations of what the code is doing:
var sURL = 'http://www.example.com/myapipath/';
var oJSON = {"employees":[
{"firstName":"John", "lastName":"Doe"},
{"firstName":"Anna", "lastName":"Smith"},
{"firstName":"Peter", "lastName":"Jones"}
]};
var sClient = plugins.http.createNewHttpClient(); // HTTP plugin object
var sPoster = sClient.createPostRequest(sURL); // Post request object
sPoster.addHeader('content-type','application/json'); // required for JSON to be parsed as JSON
sPoster.setBodyContent(JSON.stringify(oJSON));
application.output('Executing HTTP POST request and waiting for response from '+sURL, LOGGINGLEVEL.INFO);
var sResponse = null;
var sResponseData = "";
var nHttpStatusCode = 0;
var sCaughtException = '';
try {
nHttpStatusCode = (sResponse = sPoster.executeRequest()).getStatusCode(); // POST JSON request to API
}
catch (e) {
// This handles the case when the domain called does not exist or the server is down, etc.
// in this case there will be no HTTP status code returned so we must handle this differently
// to prevent the Servoy application from crashing
sCaughtException = e['rhinoException'].getMessage();
if (-1 != sCaughtException.indexOf('TypeError: Cannot call method "getStatusCode"')) {
application.output('WARNING: Could not determine HTTP status code. The server might be down or its URL might be invalid.', LOGGINGLEVEL.WARNING);
}
else {
application.output('WARNING: caught unknown HTTP POST exception: '+sCaughtException, LOGGINGLEVEL.WARNING);
}
}
// SUCCESS!:
if (200 == nHttpStatusCode) { // HTTP Ready Status
sResponseData = sResponse.getResponseBody(); // Get the server's response text
application.output('Successful, response received from server:',LOGGINGLEVEL.INFO);
application.output(sResponseData, LOGGINGLEVEL.INFO);
// put your code to handle a successful response from the server here
}
else {
// insert your code to handle various standard HTTP error codes (404 page not found, 403 Forbidden, etc.)
}

Related

I wana have my application to fetch a html web page but i keep getting -400 whatever i try monkey c / garmin connect

even this exemple i found on the site of garmin has the same problem
https://developer.garmin.com/connect-iq/core-topics/https/
import Toybox.System;
import Toybox.Communications;
import Toybox.Lang;
class JsonTransaction {
// set up the response callback function
function onReceive(responseCode as Number, data as Dictionary?) as Void {
if (responseCode == 200) {
System.println("Request Successful"); // print success
} else {
System.println("Response: " + responseCode); // print response code
}
}
function makeRequest() as Void {
var url = "https://www.garmin.com"; // set the url
var params = { // set the parameters
"definedParams" => "123456789abcdefg"
};
var options = { // set the options
:method => Communications.HTTP_REQUEST_METHOD_GET, // set HTTP method
:headers => { // set headers
"Content-Type" => Communications.REQUEST_CONTENT_TYPE_URL_ENCODED},
// set response type
:responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_URL_ENCODED
};
var responseCallback = method(:onReceive); // set responseCallback to
// onReceive() method
// Make the Communications.makeWebRequest() call
Communications.makeWebRequest(url, params, options, method(:onReceive));
}
}
can some one please tel me what i am doing wrong
The return code -400 means "Response body data is invalid for the request type." according to the SDK specification.
You are requesting a response type of Communications.HTTP_RESPONSE_CONTENT_TYPE_URL_ENCODED but in your question you state that you are expecting HTML to be returned, which almost certainly can't be parsed as URL encoded form parameters.
The SDK does not seem to support HTML response types. Even if you omit the expected response type, the server will probably still send "application/html" and the SDK states that "If the Content-Type header from the response is not one of the known HTTP_RESPONSE_CONTENT_TYPE_* types, an error will occur", so I guess you're out of luck.
Maybe you can try to request HTTP_RESPONSE_CONTENT_TYPE_TEXT_PLAIN in order to get the server to return text instead of HTML, which you then could use somehow?

How to handle api failure in gupshup bot http call

I am making a http call from the gupshup IDE bot as below.
function MessageHandler(context, event) {
if(event.message. == "postdata") {
var url = "https://abcserver.com/sm/postData";
var header = {"token":"ca916a68d94","Content-Type": "application/x-www-form-urlencoded"};
var param = "userName=John&phoneNumber=1123111111";
context.simplehttp.makePost(url,param,header);
}
function HttpResponseHandler(context, event) {
var result= JSON.parse(event.getresp);
if(result=="success")
context.sendResponse("We have successfully stored your data");
}
I need a way to handle the failure i.e if the url (https://abcserver.com/sm/postData) is not reachable then I don't get any callback, HttpResponseHandler is not called in this case and the bot stops abruptly. I need a way to know that the corresponding api request has failed.I tried using try catch but it doesn't work.
Any link to the correct documentation or code example is welcome.

Server Returns Bad Request 400 On REST POST CALL, even though uri is correct

I am trying to add an option label and option value to an optionset field(new_contractserving) found on an entity called new_servingtime. Not sure if I am doing this correctly, but the server throws a 400 Bad request, what's the issue?!
var entity = {
"new_contractserving": String(OptionValue),
"new_contractserving#OData.Community.Display.V1.FormattedValue": String(OptionText)
};
var reqJSON = new XMLHttpRequest();
reqJSON.open("POST", url + "/api/data/v8.2/new_servingtimes", false);
reqJSON.setRequestHeader("OData-MaxVersion", "4.0");
reqJSON.setRequestHeader("OData-Version", "4.0");
reqJSON.setRequestHeader("Accept", "application/json");
reqJSON.setRequestHeader("Content-Type", "application/json; charset=utf-8");
reqJSON.onreadystatechange = function () {
if (this.readyState === 4) {
reqJSON.onreadystatechange = null;
if (this.status === 204) {
var uri = this.getResponseHeader("OData-EntityId");
var regExp = /\(([^)]+)\)/;
var matches = regExp.exec(uri);
var newEntityId = matches[1];
} else {
Xrm.Utility.alertDialog(this.statusText + ": Third Request!");
return;
}
}
};
reqJSON.send(entity);
HTTP 400 means bad data. If it was "URI not found" it would have been a HTTP 404
HTTP 400 on a POST usually means, your request (requestbody) failed some validation on the server side or it did not confine to the format which server is expecting
You should be using InsertOptionValue Action to add new option to the existing picklist attribute in an entity.
CRM REST Builder is the best choice to compose such requests & test.
The request you have written can be used to set attribute value in a record, but still it’s incomplete. Read this blog to understand how you can execute webapi action.

Fiddler: Cannot set the Response Code in

We are using the Fiddler customRules.js script to handle our API testing (external APIs from other companies when they do not have Test Servers for us) where we send a response file back to the requestor if one is present, otherwise we build the response. This is working fine, but I cannot set the HTTP Status code.
When we generate the response, in some cases we want to be able to specify the HTTP Status to what the external API might send.
static function OnBeforeResponse(oSession: Session) {
if (m_Hide304s && oSession.responseCode == 304) {
oSession["ui-hide"] = "true";
}
// Set Header values for later
var HeaderContentType = 'text/xml;charset=utf-8';
var HeaderServer = 'Apache-Coyote/1.1';
var HttpStatus = 200;
... // This is the removed code that determines text or file to return
// At the end of our process to determine to send a file or error we try to send an error value in this case. For simplicity, I am just hard assigning it without using a variable as we normally would.
oSession.responseCode = 500;
oSession.oResponse.headers.HTTPResponseCode = 500;
oSession.oResponse.headers.HTTPResponseStatus = "500 SERVER ERROR";
oSession.ResponseHeaders.SetStatus(500, 'Server Error'); // This also does not work
// However this does work to add the file contents into the response when the file exists.
var ResponseFile = new ActiveXObject("Scripting.FileSystemObject");
if (ResponseFile.FileExists(ReturnFileName)) {
oSession["x-replywithfile"] = ReturnFileName;
// Error message returned as the ReturnBody was not populated and Response File not found
} else {
oSession.utilSetResponseBody(ErrorMessage);
}
return;
}
Finally tracked it down. The problem is that I am often returning a file when returning an error using the oSession["x-replywithfile"]. However, this always makes the status an 200 OK, even if I try to change the status after the oSession["x-replywithfile"] setting.
oSession["x-replywithfile"] = ReturnFileName;
oSession.responseCode = 500;
This will still always return a 200 OK.
Changing to the following will work.
var FileContents = ReadFile(ReturnFileName);
oSession.utilSetResponseBody(FileContents);
oSession.responseCode = 500;

Adding API key to header for WCF service to check

I am implementing an api key for a basic web service I have. I am using an implementation found here: https://blogs.msdn.microsoft.com/rjacobs/2010/06/14/how-to-do-api-key-verification-for-rest-services-in-net-4/
I know I have it all implemented and setup correctly on the service side but I am not sure how to pass the API key from my client. When I debug the web service upon request I don't get anything returned for my HttpRequestMessage query string. Here is code:
Web service auth manager:
public string GetAPIKey(OperationContext oc)
{
// get the request
var request = oc.RequestContext.RequestMessage;
// get HTTP request message
var requestProp = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];
// get the actual query string
NameValueCollection queryParams = HttpUtility.ParseQueryString(requestProp.QueryString);
// return APIKey if there, NameValueCollection returns null if not present
return queryParams[APIKEY];
}
Client consumption (the part that matters):
using (WebClient client = new WebClient())
{
client.Headers.Add("Content-Type", "application/json");
client.Headers.Add("APIKey","my_generated_key");
client.Encoding = Encoding.UTF8;
Console.WriteLine(client.UploadString("http://my_local_host/my.svc/myCall", "POST", data));
}
During debug, the web service is always getting empty queryParams in the NameValueCollection because the query string is empty. How do I add to that query string during the request made from the client?
Solved. The solution was to not try to pull from the HttpRequestMessageProprty.QueryString but to just pull from the headers.
Code:
public string GetAPIKey(OperationContext oc)
{
// get the request
var request = oc.RequestContext.RequestMessage;
// get HTTP request message
var requestProp = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];
// get the actual query string
NameValueCollection queryParams = requestProp.Headers;
// return APIKey if there, NameValueCollection returns null if not present
return queryParams["APIKey"];
}