Extract from a NODE-RED string - javascript

I have my NODE-RED schemma:
following string result from my "Function" node my node:
msg.payload : string[63]
"{"random":{"date":"22:55","random":21},"time":{"time":"22:52"}}"
This is the code of my "Function Node":
msg.payload.random=context.global.randomandtime;
msg.payload.time=context.global.time;
return msg;
I need to put in "part of the string" (not all) like this =>{"date":"22:55","random":21} and show it in my browser like a webpage but not using html tags.
Like this:
22:55
21
Any help will be wellcome.
I have added template(Mustache) and I am traying to bring data to it,(Note:http response is already in schemme but not shown here)
I am traying to bring data here (template). But I get error.
The Mustache template body is:
This is the payload: {{#payload.randomandandtime.random}} !
But I have back this error back:
2017-5-18 16:18:00node: Mustachemsg : string[56]
"Unclosed section "payload.randomandandtime.random" at 59"
In browser I get
502 Bad Gateway: Registered endpoint failed to handle the request.
Even If I change it only payload.randomandandtime I get empty:
payload.randomandandtime
In browser & console:
Messsage received back: (empty)
This is the payload: !

Finally I solved in this way.
I make all in one Global varaible instead 2 global variables.
I passed it to mustache template and in Mustache I worked with context in order to get it.
General Scheme:
Then in recoverydata:
msg.payload = context.global.get("randomtime");
In My Mustache:
`{{#payload.random}}
Last random number request returned {{&payload.random}}, which was received
at {{&payload.randomtime.times}}{{/payload.random}}
{{/payload}}`
The resul of it is a Webservice not using HTML and this is:
url https://....../page
"Time last server time request received at 13:14 Last random number request returned 94, which was received at 13:14"

Related

API Connect - 500 error when including basic Javascript

I'm trying some basic API Connect tutorials on IBM's platform (running locally using loopback) and have got completely stuck at an early point.
I've built a basic API service with some in-memory data and setter / getter functions. I've then built a separate API which takes two GET parameters and uses one of my getter functions to perform a search based on two criteria. When I run it, I successfully get a response with the following JSON object:
[{"itemId":1,"charge":9,"itemSize":2,"id":2}]
I've then tried to add a piece of server logic that modifies the response data - at this point, I'm just trying to add an extra field. I've added a Javascript component in the Assemble view and included the following code (taken from a tutorial), which I thought should modify the message body returned by the API while still passing it through:
//APIC: get the payload
var json = apim.getvariable('message.body');
//console.error("json %s", JSON.stringify(json));
//same: code to inject new attribute
json.platform = 'Powered by IBM API Connect';
//APIC: set the payload
//message.body = json;
apim.setvariable('message.body', json);
Instead of getting an extra JSON parameter ("platform"), all I get is a 500 error when I call the service. I'm guessing that I'm doing something fundamentally wrong, but all the docs suggest these are the right variable names to use.
You can't access json.platform but at that point json variable is json type. Are you sure that you can add a property to a json type variable if your json object lacks of that property? I mean: What if you first parse the json variable of json type to a normal object, then add new property, and finally stringify to json type again for body assigning purposes?
var json = JSON.parse(apim.getvariable('message.body')); //convert to normal object
json.platform = 'Powered by IBM API Connect'; //add new property
apim.setvariable('message.body', JSON.stringify(json)); //convert to json again before setting as body value
You need to get the context in some determined format, and in this function do your logic. For example if your message is in json you need to do:
apim.readInputAsJSON(function (error, json) {
if (error)
{
// handle error
apim.error('MyError', 500, 'Internal Error', 'Some error message');
}
else
{
//APIC: get the payload
var json = apim.getvariable('message.body');
//console.error("json %s", JSON.stringify(json));
if(json){
//same: code to inject new attribute
json.platform = 'Powered by IBM API Connect';
//APIC: set the payload
//message.body = json;
apim.setvariable('message.body', json);
}
}
});
Reference:
IBM Reference
You have the message.body empty, put a invoke/proxy policy before your gateway/javascript policy for example.

Is it risky to parse JSON string from websockets?

I'm writing an Angular2 web application, and I want bidirectional communication with the server, so the perfect solution is with websockets.
Mozilla fundation teaches to use JSON.stringify(msg) to parse a string that represents a JSON message, both for sending and receiving data with websocket. This leads to some thoughts on injection. For example, suppose the following JSON document being transfered from the server to the client's machine:
{
message{
from: "paul",
text:"hello!",
date:"01/01/2017"
}
}
Now suppose paul changes his name to "paul\" and sends the following text:
,text: alert('xss'),something:"
then the following JSON received by the client would be:
{
message{
from: "paul\",
text:",text: alert('xss'),something:"",
date:"01/01/2017"
}
}
which is, in fact, the following JSON (just rearranged):
{
message{
from: "paul\",text:",
text: alert('xss'),
something:"",
date:"01/01/2017"
}
}
which could cause problems, depending on what is done with this JSON, I guess. Is there some way to prevent these things, or is the JSON.stringfy technique safe because when inserting data from the JSON into the DOM, the text attribute would be undefined because alert('xss') is not a string (or does not return anything)?
Also, see that if there's no problem with calling a function like alert(), we were able to set the something variable to anything we wanted, this is for sure risky.

How to parse node js response of mongodb data in angular?

I've an http server in node [not express]. On button click I've a get method, which then pulls documents from mongodb (using mongoose) and displays it on angular page.
on button click:
$http.get('/get').success(function(response){
console.log(response);
//logic to store JSON response of database and perform repeat to display each document returned on UI
});
In Node code where server is created using http.createServer instead of express:
if(req.url==="/get"){
res.writeHead(200,{'content-type':'text/plain'});
modelName.find({}, 'property1 prop2 prop3', function(err,docs){
res.write('response...: '+docs);
});
}
Here is my issue:
I'm able to send response from node js to angular js but how to parse it? If I don't add 'response...:' before docs then I get an error msg 'first argument should be a string or buffer'. On angular I get response like:->
response...:{_id:....1, prop1: 'a',prop2: 'b',prop3: 'c'},
{_id:....2, prop1: 'ab',prop2: 'bc',prop3: 'cd'}
I want to display documents as a tabular format
I don't know your exact setup, but I think you should transfer application/json instead of text/plain.
You cannot simply concatenate a string to docs, you need to return either only just docs (to transfer as an array) or write res.write({'response':docs}) (to transfer as an object).
Consider moving from $http to a resource service. In your resource service, you need to set isArray to false if you want to transfer as an object or to true if you transfer as an array: https://docs.angularjs.org/api/ngResource/service/$resource

SAPUI5 Create OData entity with dates - generates incorrect request payload that ends in CX_SXML_PARSE_ERROR

We are trying to create an entity that has date attributes via an odata service. Backend is an sap system. This entity has only 3 key attributes plus a bunch of other attributes. We have identified that dates in the keys are the root cause of the problem.
Keys:
Pernr type string,
begda type datetime
endda type datetime.
The code below, (which does not work), has been severely simplified when trying to troubleshoot the issue. At the moment, it reads an entity from an entity set and immediately tries to create one with exactly the same data.
Code:
var oODataModel = new sap.ui.model.odata.ODataModel("/sap/opu/odata/sap/Z_PERSONAL_DATA_SRV/");
//Test entity to be saved
var entity = null;
//Handler for read error
var handleReadE = function (oEvent){
alert("error");
};
//Handler for read success
var handleRead = function (oEvent){
//Get the data read from backend
entity = oEvent.results[0];
//Try to create a new entity with same data
oODataModel.create('/PersDataSet', entity, null, function(){
alert("Create successful");
},function(oError){
alert("Create failed", oError);
});
};
oODataModel.read("/PersDataSet", null, [], true, handleRead, handleReadE);
In the gateway error log, an xml parsing error appears. In this log, we can see the request data and it can be seen that the dates are transported with String types. These dates are defined in the service as DateTimes so the request is rejected.
Example:
<m:properties>
<d:Pernr m:type="Edm.String">00000001</d:Pernr>
<d:Endda m:type="Edm.String">9999-12-31T00:00:00</d:Endda>
<d:Begda m:type="Edm.String">1979-05-23T00:00:00</d:Begda>
When the entity is read, the backend does not send any type information. It sends like the following example:
<m:properties>
<d:Pernr>72010459</d:Pernr>
<d:Endda>9999-12-31T00:00:00</d:Endda>
<d:Begda>1876-07-21T00:00:00</d:Begda>
And, indeed, if we try to save the same info without the type=".." it works. So the problem are the incorrect types ODataModel.create adds to the xml.
My question is:
Can I tell ODataModel.create to not add this type info? It is not doing a good job inferring the types.
Can anyone share an example reading and writing dates through odata?
Thank you very much in advance.
the data returned from oODataModel.read is raw, before you post you need to parse it
var handleRead = function (oEvent){
//Get the data read from backend
entity = oEvent.results[0];
var newEntity = jQuery.extend({},entity);
delete newEntity.__metadata;
newEntity.Begda = new Date(entity.Begda);
newEntity.Endda = new Date(entity.Endda);
//Try to create a new entity with same data
oODataModel.create('/PersDataSet', newEntity, null, function(){
why not use json instead of xml?
Thanks all for the help.
We got this working accounting for the following:
The problem of the wrong types appended to the attributes comes from the read itself. The object returned by read has a __metadata attribute which describes the values. In this object the dates are set with type=edm.string, even when the service says they are DateTime. To me this is a bug of the .read function.
When trying to use the same object to save, create sees the __metatada on the entry and uses those values, producing type edm.string type for the dates. This caused the request to be rejected. Manually changing these __metadata.properties...type to Edm.DateTime makes it work.
In the end, we did the following:
Dates are parsed manually from the Odata response, creating a js Date
object from the strings in format "yyyy-mm-ddT00:00:00", to make it work with control bindings. When we want to save, the reverse is done.
The object to be created is a new object with
only the attributes we care (no __metadata)

webOS/Ares : read JSON from URL, assign to label

I've used the webOS Ares tool to create a relatively simple App. It displays an image and underneath the image are two labels. One is static, and the other label should be updated with new information by tapping the image.
When I tap the image, I wish to obtain a JSON object via a URL (http://jonathanstark.com/card/api/latest). The typcial JSON that is returned looks like this:
{"balance":{"amount":"0","amount_formatted":"$0.00","balance_id":"28087","created_at":"2011-08-09T12:17:02-0700","message":"My balance is $0.00 as of Aug 9th at 3:17pm EDT (America\/New_York)"}}
I want to parse the JSON's "amount_formatted" field and assign the result to the dynamic label (called cardBalance in main-chrome.js). I know that the JSON should return a single object, per the API.
If that goes well, I will create an additional label and convert/assign the "created_at" field to an additional label, but I want to walk before I run.
I'm having some trouble using AJAX to get the JSON, parse the JSON, and assign a string to one of the labels.
After I get this working, I plan to see if I can load this result on the application's load instead of first requiring the user to tap.
So far, this is my code in the main-assistant.js file. jCard is the image.
Code:
function MainAssistant(argFromPusher) {}
MainAssistant.prototype = {
setup: function() {
Ares.setupSceneAssistant(this);
},
cleanup: function() {
Ares.cleanupSceneAssistant(this);
},
giveCoffeeTap: function(inSender, event) {
window.location = "http://jonathanstark.com/card/#give-a-coffee";
},
jcardImageTap: function(inSender, event) {
//get "amount_formatted" in JSON from http://jonathanstark.com/card/api/latest
//and assign it to the "updatedBalance" label.
// I need to use Ajax.Request here.
Mojo.Log.info("Requesting latest card balance from Jonathan's Card");
var balanceRequest = new Ajax.Request("http://jonathanstark.com/card/api/latest", {
method: 'get',
evalJSON: 'false',
onSuccess: this.balanceRequestSuccess.bind(this),
onFailure: this.balanceRequestFailure.bind(this)
});
//After I can get the balance working, also get "created_at", parse it, and reformat it in the local time prefs.
},
//Test
balanceRequestSuccess: function(balanceResponse) {
//Chrome says that the page is returning X-JSON.
balanceJSON = balanceResponse.headerJSON;
var balanceAmtFromWeb = balanceJSON.getElementsByTagName("amount_formatted");
Mojo.Log.info(balanceAmtFromWeb[0]);
//The label I wish to update is named "updatedBalance" in main-chrome.js
updatedBalance.label = balanceAmtFromWeb[0];
},
balanceRequestFailure: function(balanceResponse) {
Mojo.Log.info("Failed to get the card balance: " + balanceResponse.getAllHeaders());
Mojo.Log.info(balanceResponse.responseText);
Mojo.Controller.errorDialog("Failed to load the latest card balance.");
},
//End test
btnGiveCoffeeTap: function(inSender, event) {
window.location = "http://jonathanstark.com/card/#give-a-coffee";
}
};
Here is a screenshot of the application running in the Chrome browser:
In the browser, I get some additional errors that weren't present in the Ares log viewer:
XMLHttpRequest cannot load http://jonathanstark.com/card/api/latest. Origin https://ares.palm.com is not allowed by Access-Control-Allow-Origin.
and
Refused to get unsafe header "X-JSON"
Any assistance is appreciated.
Ajax is the right tool for the job. Since webOS comes packaged with the Prototype library, try using it's Ajax.Request function to do the job. To see some examples of it, you can check out the source code to a webOS app I wrote, Plogger, that accesses Blogger on webOS using Ajax calls. In particular, the source for my post-list-assistant is probably the cleanest to look at to get the idea.
Ajax is pretty much the way you want to get data, even if it sometimes feels like overkill, since it's one of the few ways you can get asynchronous behavior in JavaScript. Otherwise you'd end up with code that hangs the interface while waiting on a response from a server (JavaScript is single threaded).

Categories

Resources