Easy way to Post HTTPS JSON data (header+body) using Node.js - json

After reading multiple internet posts related to "JSON POST commands" in NodeJS I'm now totally lost! Have tried to create an easy script to send data to a device Restful API interface using https. Without any luck...
JSON string needs to contain: a Header incl. (Basic)Auth Token & Body
content something similar like:
'{"address":address,"address6":"","comment":"","duids":[],"hostnames":[],"interface":""};
Hoping that someone has a good example available or can point me into right direction again.

You can use in-built module https to make a REST API call, the request signature is as follows:
https.request(url[, options][, callback])
In your case, you can try following code:
var options = {
host: 'host-name',
port: 443,
path: 'api-path',
method: 'POST',
// authentication headers
headers: {
'Authorization': 'Basic ' + new Buffer(username + ':' + passw).toString('base64')
}
};
const req = https.request(options, (res) => {
console.log('statusCode:', res.statusCode);
console.log('headers:', res.headers);
res.on('data', (d) => {
process.stdout.write(d);
});
});

I had the exact same issue just few days ago, and I've ended up creating a super tiny module called json-post.
const jsonPOST = require('json-post');
// or import jsonPOST from 'json-post'
jsonPOST(
'https://whatever:5000/seriously',
// your JSON data as object
{hello: 'world'},
// optionally any extra needed header
{'Authorization': 'Basic ' +
new Buffer(username + ':' + passw).toString('base64')}
).then(
console.info,
console.error
);
The dance is similar to the one shown in the previous reply but it's simplified in various ways. It works well for GitHub OAuth and others services too.

I always use request library whenever I need to do HTTP request in nodejs.
var request = require('request');
request({
method: 'POST',
uri: 'http://myuri.com',
headers: {
'Content-Type' : 'application/json',
'AnotherHeader' : 'anotherValue'
},
json: myjsonobj
}, (err, response, body) => {
// handler here
})
there are other ways of making the request as well like request.post() refer here

Related

How do I fix this JSON parsing issue?

I send data with fetch() in HTML to an express API, this is how it comes out in the req.body (I use body-parser)
{
'{"address":"a","town":"NYC","details":"a","appr":': { '"Car1"': '' }
}
it's all "stringy", as the only way I know to "parse it" to send it, is to send it with JSON.stringify. But, upon getting the info, it's "unparseable", JSON.parse errors with "unexpected string in JSON at position 62"
I send it like:
body: JSON.stringify({
address: address,
town: town,
details: details,
appr: apr,
}),
I've tried everything I know how to do to attempt to "make it a JSON" again, but nothing has worked.
1 - Don't forget to add header to fetch
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json' // => this is important
},
body: JSON.stringify(data)
});
2 - Don't forget to add this on express
app.use(bodyParser.json())
Note: If you are using Express v4.16.0 or newer you can use built-in middleware. Thanks to #Dov Rine
app.use(express.json());
3 - req.body will be available as object after this. You should not use JSON.parse(req.body) because body-parser does this for you.
let address = req.body.address;

Angular failed post request with error 500

I am developing an ionic app that makes a rest call to a backend to send an email, when I make the rest call I get the following error, what can be due to (the rest call in postman works, I use chrome with the cors disabled)
Error:
POST http://172.16.50.92/send 500 (Internal Server Error)
Code Angular:
const params = {
'type': 'mail',
'attributes[to_recipients]': mail,
'attributes[body]': body,
'attributes[subject]': subject,
'attributes[attachments]': attachments
};
endpoint = url + '/send';
var headers_object = new HttpHeaders();
headers_object.append('contentType', 'application/json');
headers_object.append('Authorization', `Basic ${window.btoa(username + ':' + password)}`);
return this.http.post(endpoint, params, [headers_object]);
return this.http.post(endpoint, params, [headers_object]);
You put your headers into an array. But the signature is supposed to be
post(url: string, body: any, options: { headers: HttpHeaders })
for your usecase.
Please change to below and try again.
return this.http.post(endpoint, params, { headers: headers_object });

send post from webpage to Node.js server ...do not use 'fetch'...?

I am using the following javascript on a webpage to send information to a Node.js server upon a "click" on an image. This is using a 'POST' request.
<script>
function rerouter(_sent) {
var _people = <%- JSON.stringify(member_list) %>;
//convert the passed ('member_list') array into a JSON string...
var _attend = <%- JSON.stringify(online) %>;
//convert the passed ('online') array into a JSON string...
var splits = _sent.id.split("_"); //"split" on "underscore ('_')"
if (_people.indexOf(splits[1]) != -1) {
//**SEND INFO TO SERVER...
var available = _attend[_people.indexOf(splits[1])];
var response = fetch("members/pages/:" + splits[1] + "/presence/:" + available, {
method: 'POST',
headers: {
'Content-Type': 'text/plain;charset=utf-8'
}
});
//**
} //'_people' array contains the member name ('splits[1]')...
}
</script>
And here I handle the request in my Node.js server code:
var bodyParser = require('body-parser')
// create application/json parser
var jsonParser = bodyParser.json()
// create application/x-www-form-urlencoded parser
var urlencodedParser = bodyParser.urlencoded({ extended: false })
app.post('/members/pages/:membername/presence/:online', urlencodedParser, function (req, res) {
console.log("I RECEIVED FROM CLIENT THE FOLLOWING:")
console.log(req.params)
console.log(req.body)
res.redirect('/_landing');
})
Here is my console output:
I RECEIVED FROM CLIENT THE FOLLOWING:
{ membername: ':Nica', online: ':Yes' }
{}
As can be seen from my output, the POST route does seem to be functional, somewhat. However my 'redirect' command does NOT execute...the webpage does not change to the '_landing' page as it should...I think it may be because I am using 'fetch' to send the POST request...??? Can somebody verify if that is the cause (or another issue is the cause) and how I might be able to correct the issue?
In addition why does my 'params' include the colons (":") when I log to the console...is that standard? I would not think it would include the colons in the log, only the actual data.
Basically it seems my POST is almost working...but not exactly. Any suggestions would be greatly appreciated. I thank you in advance.
UPDATE: I have made some changes and my POST seems to be working fine now. In my frontend webpage I use the following to make the HTTP POST request:
<script>
function rerouter(_sent) {
var _people = <%- JSON.stringify(member_list) %>;
//convert the passed ('member_list') array into a JSON string...
var _attend = <%- JSON.stringify(online) %>;
//convert the passed ('online') array into a JSON string...
var splits = _sent.id.split("_"); //"split" on "underscore ('_')"
if (_people.indexOf(splits[1]) != -1) {
//**SEND INFO TO SERVER...
var available = _attend[_people.indexOf(splits[1])];
fetch('/members/pages/callup', {
method: 'post',
headers: {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json'
},
body: JSON.stringify({name: splits[1], presence: available, str: 'Some string: &=&'})
})
//**
} //'_people' array contains the member name ('splits[1]')...
}
</script>
...And modified my route handler in my Node.js script:
// create application/json parser
var jsonParser = bodyParser.json()
app.post('/members/pages/callup', jsonParser, function (req, res) {
console.log("I RECEIVED FROM CLIENT THE FOLLOWING:")
console.log(req.body)
res.redirect('/_landing');
})
This is functional...to receive the data sent from the frontend webpage.
The only remaining problem is why does the 'redirect' not fire...??? I still have a feeling that by using a 'fetch' that somehow this is interfering with the page redirection...? A fetch would normally be used to wait for a response from the server, in my case I am not interested in that functionality I just want to send data one-way from frontend to backend...and then redirect the frontend page. I cannot think of any other reason why the redirect does not fire...?
Make extented:true instead of false as,
var urlencodedParser = bodyParser.urlencoded({ extended: true }) and move this line above of the below statement,
var jsonParser = bodyParser.json() and check if it works.
And finally change your headers here from,
headers: {
'Content-Type': 'text/plain;charset=utf-8'
}
To,
headers: {
'Content-Type': 'application/json'
}
Hope this will resolve the issue.

Google Scripts API - autoUpdateForwarding Not Applying

As Domain Admin for the company I work at we'd like to set the forwarding addresses of staff as they leave the company to ensure any important correspondence isn't missed.
I've used the Google Apps OAuth2 Library successfully so far, but come across a snag. The following code is meant to forward emails from the address apitest#example.com to newaddress#example.com .
function setupForwarding() {
var service = getOAuthService();
service.reset();
try {
if (service.hasAccess()) {
var header = {
Authorization: 'Bearer ' + service.getAccessToken(),
}
var url = "https://www.googleapis.com/gmail/v1/users/apitest#example.com/settings/autoForwarding";
var response = UrlFetchApp.fetch(url, {
headers: header,
method: 'put',
enabled: true,
emailAddress: 'newaddress#example.com',
disposition: 'trash'
});
Logger.log(response.getContentText());
}
} catch (e) {
Logger.log(e.message);
}
}
The access token provided appears to work with other queries provided by UrlFetchApp such as using it to return the currently authorised forwarding addresses recorded on the account (which does include newaddress#example.com) and doesn't report any access priviledge errors. The response returns only the following
{ "enabled" : false }
And does not apply any forwarding. Would someone be able to help me identify the problem? I feel I might be passing the parameters to the HTTP request incorrectly but I'm still learning my way around that system and no other questions I found seemed to help.
Ozzie
I worked this out and it was simpler than I thought; so sharing the answer here in case anyone has a similar issue.
var response = UrlFetchApp.fetch(url, {
headers: header,
method: 'put',
contentType : 'application/json',
payload: '{ "enabled" : "true" , "emailAddress" : "newaddress#example.com" , "disposition" : "trash" }'
});
Is the functional way to do this; the request was expecting a separate payload and declared content type both.

Change User-Agent for XMLHttpRequest in TVML app

I'm working on an Apple TV app using TVMLKit. My app's JavaScript code tries to send an HTTP request to a server using XMLHttpRequest. The server is expecting a specific user agent, so I tried this:
var request = new XMLHttpRequest();
request.open("GET", url, true);
request.setRequestHeader("User-Agent", "MyApp");
request.send();
The server receives a different User-Agent header:
User-Agent: <Projectname>/1 CFNetwork/758.1.6 Darwin/15.0.0
If I change the header name to something different, it shows up in the request headers. I guess Apple is replacing the User-Agent field right before sending the request. Is there a way to prevent this?
After spending two days on investigating this question I've came to solution with creating native GET and POST methods in swift end exposing them to javascript. This isn't best solution but still I want to share it. Maybe it could help someone.
Here how it works
First we need to install Alamofire library. We will use it for creating requests.
Readme on github has all instructions you need to install it
After installing Alamofire we need to import it in AppDelegate.swift
import Alamofire
Then we need to create function in app controller (AppDelegate.swift) that will expose methods to javascript
func appController(appController: TVApplicationController, evaluateAppJavaScriptInContext jsContext: JSContext)
{
let requests = [String : AnyObject]()
let get: #convention(block) (String, String, [String : String]?) -> Void = { (cId:String, url:String, headers:[String : String]?) in
Alamofire.request(.GET, url, headers: headers)
.responseString { response in
jsContext.evaluateScript("requests." + cId + "(" + response.result.value! + ")")
}
}
let post: #convention(block) (String, String, [String : AnyObject]?, [String : String]?) -> Void = { (cId:String, url:String, parameters:[String : AnyObject]?, headers:[String : String]?) in
Alamofire.request(.POST, url, parameters: parameters, headers: headers)
.responseString { response in
jsContext.evaluateScript("requests." + cId + "(" + response.result.value! + ")")
}
}
jsContext.setObject(requests, forKeyedSubscript: "requests");
jsContext.setObject(unsafeBitCast(get, AnyObject.self), forKeyedSubscript: "nativeGET");
jsContext.setObject(unsafeBitCast(post, AnyObject.self), forKeyedSubscript: "nativePOST");
}
Full code of AppDelegate.swift you can find here
All set! Now we have access to nativeGET and nativePOST functions from javascript.
The last thing is to make requests and retrieve responses. I haven't understand how to make callback executions in swift so I've used jsonp approach using runtime generated functions and passing their names to native functions.
Here how it looks in javascript
export function get(url, headers = {}) {
return new Promise((resolve) => {
const cId = `get${Date.now()}`;
requests[cId] = response => {
delete requests[cId];
resolve(response);
}
nativeGET(cId, url, headers);
});
}
export function post(url, parameters = {}, headers = {}) {
return new Promise((resolve) => {
const cId = `post${Date.now()}`;
requests[cId] = response => {
delete requests[cId];
resolve(response);
}
nativePOST(cId, url, parameters, headers);
});
}
The code above is written in ES6 and you'll need to include Promise polifill in your TVJS app.
Now we can make GET and POST requests applying any header we need
post('http://example.com/', {
login: 'xxx',
password: 'yyy'
}, {
'User-Agent': 'My custom User-Agent'
})