Node-red - Posting data to influxdb via http - json

Im trying to post data to an Influxdb via Node-red.
Via CURL i can post this:
curl -i -XPOST 'http://localhost:8086/write?db=waterlevel' --data-binary 'vattenstand,lake=siljan,region=dalarna value=160.80'
and it puts data to InfluxDb.
When I try to post via Node-red and an HTTP request I get the error:
{"error":"unable to parse '{\"url\":\"http://192.168.1.116:8086/write?db=waterlevel\",\"method\":\"POST\",\"body\":\"vattenstand,lake=siljan,region=dalarna value=160.80\",}': missing tag value"}
I use this code in a function in Node-red and pass it to the HTTP request:
var dataString = 'vattenstand,lake=siljan,region=dalarna value=160.80';
msg.payload = {
'url': 'http://192.168.1.116:8086/write?db=waterlevel',
'method': 'POST',
'body': dataString,
};
msg.headers = {
Accept: "application/json"
};
return msg;

The sidebar help for the node details the msg properties you should be setting to configure the node.
You are passing in URL, method and body as properties of msg.payload. That is not correct.
They should be set as msg.url, msg.method for the first two, and msg.payload should be the body of the request.
In this instance, you have already configured the node with a URL and method directly, so there's no need to pass them in with the message. In fact, as you have configured the URL in the node you will find you cannot override it with msg.url. if you want to set the URL with each message, you must leave the node's URL field blank in the editor.
You may also need to set the content-type header.
Assuming you are happy to leave the URL and method hard coded in the node, you function should be something like:
msg.payload = 'vattenstand,lake=siljan,region=dalarna value=160.80';
msg.headers = {
Accept: "application/json"
};
msg.headers['Content-type'] = 'application/x-www-form-urlencoded';
return msg;

Why don't you use the spezial influxdb node?
https://flows.nodered.org/node/node-red-contrib-influxdb
Advantage: The http header need not be created. You can reuse the defined connection for other data.

Related

I can't resolve error with API POST function

I am trying to post data via an API interface.
I have checked the JSON of the data with JSON formatter and tested the API post in ReqBin and they work fine but when I execute it in App Script I get the same error, seemingly ignoring the attributes I put in the options variable.
Error is
{"code":"not_acceptable","message":"I can only talk JSON. Please set 'Accept' and 'Content-Type' to 'application/json' in your http request header."}
Note: I have tried sending just the data as the payload without json.stringify'ing it as it is formatted as JSON to start with.
In all cases it executes, but comes back 406
Is there another way to add 'Accept':"application/json" into the header??
My Code
function exportNation()
{
// Make a POST request with a JSON payload.
var data = {
"person":
{
"email":"mikenizzckelisaweiner#tv.com",
"last_name":"Bozzrovowski",
"first_name":"Edwzzard",
"tags":"Imported Data,Volunteer,Sign Request"
}
};
var options = {
"method":"POST",
"Content-Type":"application/json",
'Accept':"application/json",
'muteHttpExceptions':true,
'payload':JSON.stringify(data)
};
var response = UrlFetchApp.fetch('https://xyz.xyz.com/api/v1/people?
access_token=5604da84fXXXXXXXXXXXXXXXX42da1ea',options );
}
Any help would be greatly appreciated!
Additional HTTP headers need to be sent as a headers object.
See: https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app#advanced-parameters
var options = {
"method":"POST",
"contentType":"application/json",
"headers": {'Accept':"application/json"},

How can i pass an object and a string to webservice using post request using angularjs

Am very new to angularjs and i need to post data to a web service, the service accepts two parameters, one is List of object and the other is securityToken,
Here is my code,
$scope.saveCompany=function(){
// alert("Save Company!!!");
var Companies={
Code: 'testMartin',
Name: 'company1',
CompanyType : 'Tenant',
email : 'test#yaoo.com',
Fax : 4235353,
ParentID : 1
};
$http({
url:'http://localhost/masters/smstools.svc/json/SaveComapnies',
dataType: 'json',
method: 'POST',
data: $.param(Companies),
headers: {
"Content-Type": "text/json",
}
}).success(function(response){
alert ("Success");
}).error(function(error){
alert ("Save company!");
});
how can i pass the security token with the companies object as a separate paramenter. my service accepts the parameters like this,
public List<CompanyProfile> Save(List<CompanyProfile> CompanyList,string securityToken)
Since this is a rest call you only have 3 places were you can pass parameters data:
With Post and it will be part of the body, it seems this is what is your first parameter is occupying now.
With Get and you add the parameter to the URL /json/SaveComapnies/mySecParam or by queryString like /json/SaveComapnies?sec=mySecParam but this is not secure nor recommended for security settings.
With header from angular Post:
**headers: {
"Content-Type": "text/json",
"mySecVar": "mySecParamValue"
}**
Server side version:
public List<CompanyProfile> Save(List<CompanyProfile> CompanyList){
WebOperationContext current = WebOperationContext.Current;
WebHeaderCollection headers = current.IncomingRequest.Headers;
if (headers["mySecVar"] != null){
// do something
}
}
You can read more about it here:
How to read HTTP request headers in a WCF web service?
Can you share more information in your Backend?
If it is actually a REST Backend I would rather use an angular $resource
https://docs.angularjs.org/api/ngResource
If you want to pass json object and string as post Parameter you should stick to the $http docs
https://docs.angularjs.org/api/ng/service/$http
In the post example you can pass both params in:
$http.post('/yourEndpoint', {jsonObj:yourCompaniesObj, secKey:yourSecretToken})....(sucess etc)
Typing from my cell - if you need more code examples just tell

Playframework handling post request

In my routes:
POST /forms/FormValidator1/validateForm controllers.FormValidator1.validateForm(jsonForm:String)
There is a controller method defined for that route:
def validateForm(jsonForm:String) = Action { ...
Then I try to send POST request by chrome POSTMAN plugin (see pic above).
I use:
url: http://localhost:9000/forms/FormValidator1/validateForm
headers: Content Type: application/json
json data: {name: "me", surname: "my"}
So, sending this POST request I can not reach controller's method by mentioned route / url. Why?
UPDATE:
Interestly enough: after I got it working on my laptop (see my answer below) then push it on gitHub and pull it to another machine it starts working differently. Now it complains than Bad Request is [Invalid XML] nevertheless I use "application/json" header and did not change any line of code after commit. I wonder maybe it is a bug.
It seems I got it.
Here:
https://groups.google.com/forum/#!topic/play-framework/XH3ulCys_co
And here:
https://groups.google.com/forum/#!msg/play-framework/M97vBcvvL58/216pTqm22HcJ
There is wrong and correct way explained:
Doesn't work: curl -d "name=sam" http://localhost:9000/test
Works: curl -d "" http://localhost:9000/test?name=sam
This is the way how POST params are passing..in play. (second link is explanation WHY):
Sometimes you have to make compromises. In Play 1 you could bind your
action parameters from any parameter extracted from the URL path,
query string or even the request body. It was highly productive but
you had no way to control the way the form was uploaded. I mean, if a
user uploads a big file you needed to load the entire request in
memory to be able to handle it.
In Play 2 you can control the request body submission. You can reject
it early if something is wrong with the user, you can process big
files or streams without filling your memory with more than one HTTP
chunk… You gain a high control of what happens and it can help you to
scale you service. But, the other side of the coin is that when a
request is routed, Play 2 only uses the request header to make its
decision: the request body is not available yet, hence the inability
to directly bind an action parameter from a parameter extracted from
the request body.
UPDATE:
Interestly enough: after I got it working on my laptop then push it on gitHub and pull it to another machine it starts working differently. Now it complains than Bad Request is [Invalid XML] nevertheless I use "application/json" header and did not change any line of code after commit.
UPDATE 2
So I fixed it like this:
On angular side (we even can comment dataType and headers):
var data = $scope.fields
$http({
url: '/forms/FormValidator1/validateForm',
method: "POST",
//dataType: "json",
data: data,
//headers: {'Content-Type': 'application/json'}
}).success(function (data, status, headers, config) {
console.log("good")
}).error(function (data, status, headers, config) {
console.log("something wrong")
});
On playFramework side: (use BodyParser)
def validateForm = Action { request =>
val body: AnyContent = request.body
val jsonBody: Option[JsValue] = body.asJson
// Expecting text body
jsonBody.map { jsValue =>
val name = (jsValue \ "name")
val surname = (jsValue \ "surname")
....
}
Routes (don't define parameters at all !):
POST /forms/FormValidator1/validateForm controllers.FormValidator1.validateForm

NodeJS : Validating request type (checking for JSON or HTML)

I would like to check if the type that is requested by my client is JSON or HTML, as I want my route to satisfy both human and machine needs.
I have read the Express 3 documentation at:
http://expressjs.com/api.html
And there are two methods req.accepts() and req.is(), used like this:
req.accepts('json')
or
req.accepts('html')
Since these are not working as they should, I tried using:
var requestType = req.get('content-type');
or
var requestType = req.get('Content-Type');
requestType is always undefined...
Using the suggestion at this thread:
Express.js checking request type with .is() doesn't work
does not work either. what am I doing wrong?
Edit 1: I have checked for correct client HTML negotiation. Here are my two different request headers (taken from the debugger inspector):
HTML : Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
JSON : Accept: application/json, text/javascript, */*; q=0.01
Solution (thanks to Bret):
Turns out I was specifying the Accept headers wrong, and the */* was the issue. Here is the code that works!
//server (now works)
var acceptsHTML = req.accepts('html');
var acceptsJSON = req.accepts('json');
if(acceptsHTML) //will be null if the client does not accept html
{}
I am using JSTREE, a jQuery plugin that uses jQuery Ajax calls underneath). The parameters passed to the Ajax call are in the "ajax" field, and I have replaced the "accepts" parameter with a complete "headers" object. Now it works, and should solve the problem when you are using plain jQuery if it should ever occur.
//client
.jstree({
// List of active plugins
"plugins" : [
"themes","json_data","ui","crrm","cookies","dnd","search","types","hotkeys","contextmenu"
],
"json_data" : {
"ajax" : {
// the URL to fetch the data
"url" : function(n) {
var url = n.attr ? IDMapper.convertIdToPath(n.attr("id")) : "<%= locals.request.protocol + "://" + locals.request.get('host') + locals.request.url %>";
return url;
},
headers : {
Accept : "application/json; charset=utf-8",
"Content-Type": "application/json; charset=utf-8"
}
}
}
})
var requestType = req.get('Content-Type'); definitely works if a content-type was actually specified in the request (I just re-verified this a minute ago). If no content-type is defined, it will be undefined. Keep in mind that typically only POST and PUT requests will specify a content type. Other requests (like GET) will often specify a list of accepted types, but that's obviously not the same thing.
EDIT:
Okay, I understand your question better now. You're talking about the Accept: header, not content-type.
Here's what's happening: notice the */*;q=0.8 at the end of listed accept types? That essentially says "I'll accept anything." Therefore, req.accepts('json') is always going to return "json" because technically it's an accepted content type.
I think what you want is to see if application/json is explicitly listed, and if so, respond in json, otherwise respond in html. This can be done a couple of ways:
// a normal loop could also be used in place of array.some()
if(req.accepted.some(function(type) {return type.value === 'application/json';}){
//respond json
} else {
//respond in html
}
or using a simple regular expression:
if(/application\/json;/.test(req.get('accept'))) {
//respond json
} else {
//respond in html
}
According to the documentation, this the proper solution
req.accepts(['html', 'json']) === 'json'
Hope it helps!
Please define "not working as they should", because they do for me.
In other words:
// server.js
console.log('Accepts JSON?', req.accepts('json') !== undefined);
// client sends 'Accept: application/json ...', result is:
Accepts JSON? true
// client sends 'Accept: something/else', result is:
Accepts JSON? false
The Content-Type header as sent by a client isn't used for content negotiation, but to declare the content type for any body data (like with a POST request). Which is the reason why req.is() isn't the correct method to call in your case, because that checks Content-Type.
To throw my hat in the ring, I wanted easily readable routes without having .json suffixes everywhere or having to have each route hide these details in the handler.
router.get("/foo", HTML_ACCEPTED, (req, res) => res.send("<html><h1>baz</h1><p>qux</p></html>"))
router.get("/foo", JSON_ACCEPTED, (req, res) => res.json({foo: "bar"}))
Here's how those middlewares work.
function HTML_ACCEPTED (req, res, next) { return req.accepts("html") ? next() : next("route") }
function JSON_ACCEPTED (req, res, next) { return req.accepts("json") ? next() : next("route") }
Personally I think this is quite readable (and therefore maintainable).
$ curl localhost:5000/foo --header "Accept: text/html"
<html><h1>baz</h1><p>qux</p></html>
$ curl localhost:5000/foo --header "Accept: application/json"
{"foo":"bar"}
Notes:
I recommend putting the HTML routes before the JSON routes because some browsers will accept HTML or JSON, so they'll get whichever route is listed first. I'd expect API users to be capable of understanding and setting the Accept header, but I wouldn't expect that of browser users, so browsers get preference.
The last paragraph in ExpressJS Guide talks about next('route'). In short, next() skips to the next middleware in the same route while next('route') bails out of this route and tries the next one.
Here's the reference on req.accepts.

how to return json format from ODATA?

I know ODATA can return json but not sure if I have to use an attribute or interface to do so.
I want it to do just like http://odata.netflix.com/Catalog/Titles?$format=JSON but my odata service doesn't return JSON. When I call it like www.foo.com/service?$format=json, it just returns XML.
What do I need to do to return json with ODATA?
Download and install Fiddler.
http://www.fiddler2.com/fiddler2/
Once installed, open it, click on the "Request Builder" tab located in the right side of Fiddler.
Insert this URL:
http://test.com/feed2/ODataService.svc/results
Note that you DO NOT NEED THE ?$format=JSON
In the "Request Headers" section, insert the following line:
accept: application/json
Hit the Big "Execute" button at the top right of Fiddler.
You'll see the results of the request added to the list on the left side of Fiddler.
Double click on the request. The right side of Fiddler will change to the "Inspectors" tab where you can see the results of your request.
Also, since you are working with Json, you probably want to download and install the Json viewer plugin for Fiddler:
http://jsonviewer.codeplex.com/
Newer versions of WCF Data Services support JSON by default and you must have
Accept: application/json;odata=verbose
in the request header.
Accept: application/json
is no longer sufficient. More info here.
No-one seems to be answering your question very cleanly here!
From an HTML page you can use the following Javascript / JQuery code to have a WCF Data Service return data in JSON format;
<script src="Scripts/jquery-1.4.1.min.js" type="text/javascript"></script>
<script language="javascript" type="text/javascript">
var sURL = "http://YourService.svc/Books(10)";
function testJSONfetch() {
$.ajax({
type: "GET",
contentType: "application/json; charset=utf-8",
datatype: "json",
url: sURL,
error: bad,
success: good,
beforeSend: function (XMLHttpRequest) {
//Specifying this header ensures that the results will be returned as JSON.
XMLHttpRequest.setRequestHeader("Accept", "application/json");
}
});
}
function good(response)
{
}
function bad(response)
{
}
</script>
You need to add “Accept: application/json” into the request header section.
Check out this link
If you're using the ODATA provider from Data Services you can easily return ODATA as JSON by specifying it in the URL as in the sample you gave - http://odata.netflix.com/Catalog/Titles?$format=JSON
To do this use the JSONp and URL-controlled format support for ADO.NET Data Services download from MSDN http://code.msdn.microsoft.com/DataServicesJSONP and add the JSONPSupportBehavior decorator to your DataService class like below.
[JSONPSupportBehavior]
public class MyDataService : DataService<MyContextType>
{
...
"...but I get "The webpage cannot be found" using http://test.com/feed2/ODataService.svc/results?$format=JSON ..."
you dont need the $format=JSON in the Uri.
Just use "http://test.com/feed2/ODataService.svc/results"
(with Accept: application/json in the request header)
Late answer, but I've been spending the last hour trying to figure out how to curl OData APIs and return the result as json. The following code fetches the document in json and writes it to a file:
-o myfile.html -H "Accept: application/json" http://example.com/api/data?$filter=name eq 'whatever'
... just use lower case letters:
"format=json"
It's not pretty but this is how I forced JSON output without using $format in the request string:
Request r = new Request(Method.GET, "http://XXXXXXX.svc//Login"
+ "&UserId=" + "'" + "user" + "'"
+ "&Password=" + "'" + "password" + "'");
ClientInfo ci = r.getClientInfo();
ArrayList<Preference<MediaType>> accepted = new ArrayList<Preference<MediaType>>();
accepted.add(new Preference<MediaType>(MediaType.APPLICATION_JSON));
ci.setAcceptedMediaTypes(accepted);
Client client = new Client(Protocol.HTTP);
Response response = client.handle(r);
Representation output = response.getEntity();