How do I send data (via ajax post or get) from BeagleBone Black to a web server using BoneScript?
As I understand, XMLHttpRequest does not exist. Is there another approach?
I found the solution: In fact, I see this operation is not related to beaglebone. It relates to nodejs. So, the key is require('http') by node.
var http = require('http');
http.get('http://www.example.com', function(response) {
var response_data = '';
response.on('data', function(chunk) {
response_data += chunk;
})
.on('end', function() {
console.log(response_data);
})
.on('error', function(e) {
console.log('Error: ' + e.message);
});
});
OR if you want to do that simpler, you can use Requistify
npm install requestify
After installed you can use it like:
var requestify = require('requestify');
// GET Example
requestify.get('http://example.com').then(function(response) {
// Get the response body (JSON parsed - JSON response or jQuery object in case of XML response)
response.getBody();
// Get the response raw body
response.body;
});
// POST example
requestify.post('http://example.com', {
hello: 'world'
})
.then(function(response) {
// Get the response body
response.getBody();
});
Related
I'm attempting to post interactive messages to slack as a Bot User (using chat.postMessage, etc).
Although I am passing in the Bot Access Token (as received from the initial OAuth) I keep getting an error response stating "not_authed".
I get the same when I attempt auth.test.
I'm doing something like the following with "request" in node.js:
app.get("/testAuth/test", function(req,res){
console.log("in testAuth/test...sending test message to Slack");
var bToken = process.env.TESTBOT_ACCESS_TOKEN;
var slackMessageURL = "https://slack.com/api/auth.test";
var postOptions = {
uri: slackMessageURL,
method: "POST",
token: bToken
};
request(postOptions, (error, response, body) => {
if(error){
console.log("OOPPPPS....we hit an error in auth.test: " + error);
} else {
console.log("auth.test response: " + JSON.stringify(response));
}
});
res.send("Sent Test...check logs");
});
which results with:
auth.test response: {"statusCode":200,"body":"{\"ok\":false,\"error\":\"not_authed\"}",...
According to the Slack WebAPI docs, if I'm posting as the Bot, I should use the Bot's access token (as received from the initial oauth), but figure I'm either formatting my request incorrectly, or the token is not what Slack is expecting.
Ok, after talking with Slack support, it appears (at least) the WebAPIs I am calling don't yet support application/json. These do work with x-www-form-urlencoded.
Looking at this post
I was able to cobble together the following which auth'd successfully:
//up top
var request = require("request");
var querystring = require("querystring");
//...
app.get("/testAuth/test", function(req,res){
console.log("in testAuth/test...sending test message to Slack");
var bToken = process.env.TESTBOT_ACCESS_TOKEN;
var message = {
token: bToken
};
var messageString = querystring.stringify(message);
var messageLength = messageString.length;
var slackMessageURL = "https://slack.com/api/auth.test";
var postOptions = {
headers: {
"Content-length": messageLength,
"Content-type": "application/x-www-form-urlencoded"
},
uri: slackMessageURL,
body: messageString,
method: "POST"
};
request(postOptions, (error, response, body) => {
if(error){
console.log("OOPPPPS....we hit an error in auth.test: " + error);
} else {
console.log("auth.test response: " + JSON.stringify(response));
}
});
res.send("Sent Test...check logs");
});
taking straight from this post:
This code never executes.
var Promise = require("bluebird");
Promise.promisifyAll(require("restify"));
var restify = require("restify");
var http = require('http');
const PORT=7070;
function handleRequest(request, response){
response.end('It Works!! Path Hit: ' + request.url);
}
var server = http.createServer(handleRequest);
server.listen(PORT, function(){
console.log("Server listening on: http://localhost:%s", PORT);
});
var client = restify.createJsonClientAsync({
url: 'http://127.0.0.1:7070'
});
client.get("/foo").spread(function(req, res, obj) {
console.log(obj);
});
I only put together this simple example to prove it to myself after my production code didn't work. I can hit localhost:7070 with curl and I get the expected results.
In a nutshell: I need to execute 3 GET calls to a server before I can create a POST and hence my need for promises.
Anyone can shed some insight? I can't imagine this being simpler.
UPDATE
Apparently i did not read the question correctly, here is a working example of 2 gets using a promisified restify json client. you would just do another spread in the body of the second spread for your post.
var promise = require('bluebird');
var restify = require('restify');
promise.promisifyAll(restify.JsonClient.prototype);
var client = restify.createJsonClient({
url: 'http://localhost:8080',
version: '*'
});
client.getAsync('/api/resource/1').spread(function(req, res, obj) {
console.log('result 1', obj);
return client.getAsync('/api/resource/2').spread(function(req, res, obj) {
console.log('result 2', obj);
});
});
As I stated in my comments, I would not promisify restify itself. Instead I would use either a handler whose body executes promise code or a chain of handlers (which can also have promises in the body). restify should only receive the request and execute the handler.
I will use modified versions of the basic example from the restify page to illustrate each.
Promise in the message body using knex.js which returns a promise
var knex = require('knex')(connectionConfig);
var restify = require('restify');
function promisePost(req, res, next) {
// get 1
knex.select('*')
.from('table1')
.where('id', '=', req.body.table1_id)
.then(function(result1) {
// get 2
return knex.select('*')
.from('table2')
.where('id', '=', req.body.table2_id)
.then(function(result2) {
return knex('table3').insert({
table1_value: result1.value,
table2_value: result2.value
})
.then(function(result3) {
res.send(result3);
return next();
});
});
});
}
var server = restify.createServer();
server.use(restify.bodyParser());
server.post('/myroute', promisePost);
server.listen(8080, function() {
console.log('%s listening at %s', server.name, server.url);
});
now with chained handlers
var knex = require('knex')(connectionConfig);
var restify = require('restify');
function get1(req, res, next) {
knex.select('*').from('table1')
.where('id', '=', req.body.table1_id)
.then(function(result1) {
res.locals.result1 = result1;
return next();
});
}
function get2(req, res, next) {
knex.select('*').from('table2')
.where('id', '=', req.body.table2_id)
.then(function(result2) {
res.locals.result2 = result2;
return next();
});
}
function post(req, res, next) {
knex('table3').insert({
table1_value: res.locals.result1,
table2_value: res.locals.result2
})
.then(function(result3) {
res.send(result3);
return next();
});
}
var server = restify.createServer();
server.use(restify.bodyParser());
server.post('/myroute', get1, get2, post);
server.listen(8080, function() {
console.log('%s listening at %s', server.name, server.url);
});
i would like to use native ajax to make some calls inside my node.js server.
Is this secure ?? Can i do it without problems ???
Here's and example:
.... NODE
app.post('/postReceptor', function(req, res, next) {
var data1 = req.body['input1'];
var data2 = req.body['input2'];
var xhr;
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
xhr = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
try {
xhr = new ActiveXObject('Msxml2.XMLHTTP');
}
catch (e) {
try {
xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
catch (e) {}
}
}
xhr.open('GET', encodeURI('HTTP://WWW.WEBSITE.COM'), true);
xhr.send(null);
xhr.onreadystatechange = function() {
if(xhr.readyState === 4) { // done
if(xhr.status === 200) { // complete
res.render('renderPage', {
sendingData: xhr.responseText
});
}
}
};
});
This is to verify an external page some customer data sent by the client !
Thanks !
Doing AJAX calls is a concept that is originated from the client side and you are in the server so you don't have the XMLHttpRequest function available on Node.JS.
So to make a HTTP request from Node.JS, you could use http.request or use another library like request helping you to code without complexities, here is an example using the request library:
var request = require('request');
var URL = 'http://www.google.com';
request(URL, function(error, response, body) {
if (!error && response.statusCode === 200) {
console.log(body);
}
});
Thanks for the answers. I got the answer to the question using the library https://www.npmjs.com/package/xmlhttprequest
Risto Novik, this is a simple example and of course i have to validate the fields!
The data on the webpage is displayed dynamically and it seems that checking for every change in the html and extracting the data is a very daunting task and also needs me to use very unreliable XPaths. So I would want to be able to extract the data from the XHR packets.
I hope to be able to extract information from XHR packets as well as generate 'XHR' packets to be sent to the server.
The extracting information part is more important for me because the sending of information can be handled easily by automatically triggering html elements using casperjs.
I'm attaching a screenshot of what I mean.
The text in the response tab is the data I need to process afterwards. (This XHR response has been received from the server.)
This is not easily possible, because the resource.received event handler only provides meta data like url, headers or status, but not the actual data. The underlying phantomjs event handler acts the same way.
Stateless AJAX Request
If the ajax call is stateless, you may repeat the request
casper.on("resource.received", function(resource){
// somehow identify this request, here: if it contains ".json"
// it also also only does something when the stage is "end" otherwise this would be executed two times
if (resource.url.indexOf(".json") != -1 && resource.stage == "end") {
var data = casper.evaluate(function(url){
// synchronous GET request
return __utils__.sendAJAX(url, "GET");
}, resource.url);
// do something with data, you might need to JSON.parse(data)
}
});
casper.start(url); // your script
You may want to add the event listener to resource.requested. That way you don't need to way for the call to complete.
You can also do this right inside of the control flow like this (source: A: CasperJS waitForResource: how to get the resource i've waited for):
casper.start(url);
var res, resData;
casper.waitForResource(function check(resource){
res = resource;
return resource.url.indexOf(".json") != -1;
}, function then(){
resData = casper.evaluate(function(url){
// synchronous GET request
return __utils__.sendAJAX(url, "GET");
}, res.url);
// do something with the data here or in a later step
});
casper.run();
Stateful AJAX Request
If it is not stateless, you would need to replace the implementation of XMLHttpRequest. You will need to inject your own implementation of the onreadystatechange handler, collect the information in the page window object and later collect it in another evaluate call.
You may want to look at the XHR faker in sinon.js or use the following complete proxy for XMLHttpRequest (I modeled it after method 3 from How can I create a XMLHttpRequest wrapper/proxy?):
function replaceXHR(){
(function(window, debug){
function args(a){
var s = "";
for(var i = 0; i < a.length; i++) {
s += "\t\n[" + i + "] => " + a[i];
}
return s;
}
var _XMLHttpRequest = window.XMLHttpRequest;
window.XMLHttpRequest = function() {
this.xhr = new _XMLHttpRequest();
}
// proxy ALL methods/properties
var methods = [
"open",
"abort",
"setRequestHeader",
"send",
"addEventListener",
"removeEventListener",
"getResponseHeader",
"getAllResponseHeaders",
"dispatchEvent",
"overrideMimeType"
];
methods.forEach(function(method){
window.XMLHttpRequest.prototype[method] = function() {
if (debug) console.log("ARGUMENTS", method, args(arguments));
if (method == "open") {
this._url = arguments[1];
}
return this.xhr[method].apply(this.xhr, arguments);
}
});
// proxy change event handler
Object.defineProperty(window.XMLHttpRequest.prototype, "onreadystatechange", {
get: function(){
// this will probably never called
return this.xhr.onreadystatechange;
},
set: function(onreadystatechange){
var that = this.xhr;
var realThis = this;
that.onreadystatechange = function(){
// request is fully loaded
if (that.readyState == 4) {
if (debug) console.log("RESPONSE RECEIVED:", typeof that.responseText == "string" ? that.responseText.length : "none");
// there is a response and filter execution based on url
if (that.responseText && realThis._url.indexOf("whatever") != -1) {
window.myAwesomeResponse = that.responseText;
}
}
onreadystatechange.call(that);
};
}
});
var otherscalars = [
"onabort",
"onerror",
"onload",
"onloadstart",
"onloadend",
"onprogress",
"readyState",
"responseText",
"responseType",
"responseXML",
"status",
"statusText",
"upload",
"withCredentials",
"DONE",
"UNSENT",
"HEADERS_RECEIVED",
"LOADING",
"OPENED"
];
otherscalars.forEach(function(scalar){
Object.defineProperty(window.XMLHttpRequest.prototype, scalar, {
get: function(){
return this.xhr[scalar];
},
set: function(obj){
this.xhr[scalar] = obj;
}
});
});
})(window, false);
}
If you want to capture the AJAX calls from the very beginning, you need to add this to one of the first event handlers
casper.on("page.initialized", function(resource){
this.evaluate(replaceXHR);
});
or evaluate(replaceXHR) when you need it.
The control flow would look like this:
function replaceXHR(){ /* from above*/ }
casper.start(yourUrl, function(){
this.evaluate(replaceXHR);
});
function getAwesomeResponse(){
return this.evaluate(function(){
return window.myAwesomeResponse;
});
}
// stops waiting if window.myAwesomeResponse is something that evaluates to true
casper.waitFor(getAwesomeResponse, function then(){
var data = JSON.parse(getAwesomeResponse());
// Do something with data
});
casper.run();
As described above, I create a proxy for XMLHttpRequest so that every time it is used on the page, I can do something with it. The page that you scrape uses the xhr.onreadystatechange callback to receive data. The proxying is done by defining a specific setter function which writes the received data to window.myAwesomeResponse in the page context. The only thing you need to do is retrieving this text.
JSONP Request
Writing a proxy for JSONP is even easier, if you know the prefix (the function to call with the loaded JSON e.g. insert({"data":["Some", "JSON", "here"],"id":"asdasda")). You can overwrite insert in the page context
after the page is loaded
casper.start(url).then(function(){
this.evaluate(function(){
var oldInsert = insert;
insert = function(json){
window.myAwesomeResponse = json;
oldInsert.apply(window, arguments);
};
});
}).waitFor(getAwesomeResponse, function then(){
var data = JSON.parse(getAwesomeResponse());
// Do something with data
}).run();
or before the request is received (if the function is registered just before the request is invoked)
casper.on("resource.requested", function(resource){
// filter on the correct call
if (resource.url.indexOf(".jsonp") != -1) {
this.evaluate(function(){
var oldInsert = insert;
insert = function(json){
window.myAwesomeResponse = json;
oldInsert.apply(window, arguments);
};
});
}
}).run();
casper.start(url).waitFor(getAwesomeResponse, function then(){
var data = JSON.parse(getAwesomeResponse());
// Do something with data
}).run();
I may be late into the party, but the answer may help someone like me who would fall into this problem later in future.
I had to start with PhantomJS, then moved to CasperJS but finally settled with SlimerJS. Slimer is based on Phantom, is compatible with Casper, and can send you back the response body using the same onResponseReceived method, in "response.body" part.
Reference: https://docs.slimerjs.org/current/api/webpage.html#webpage-onresourcereceived
#Artjom's answer's doesn't work for me in the recent Chrome and CasperJS versions.
Based on #Artjom's answer and based on gilly3's answer on how to replace XMLHttpRequest, I have composed a new solution that should work in most/all versions of the different browsers. Works for me.
SlimerJS cannot work on newer version of FireFox, therefore no good for me.
Here is the the generic code to add a listner to load of XHR (not dependent on CasperJS):
var addXHRListener = function (XHROnStateChange) {
var XHROnLoad = function () {
if (this.readyState == 4) {
XHROnStateChange(this)
}
}
var open_original = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function (method, url, async, unk1, unk2) {
this.requestUrl = url
open_original.apply(this, arguments);
};
var xhrSend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function () {
var xhr = this;
if (xhr.addEventListener) {
xhr.removeEventListener("readystatechange", XHROnLoad);
xhr.addEventListener("readystatechange", XHROnLoad, false);
} else {
function readyStateChange() {
if (handler) {
if (handler.handleEvent) {
handler.handleEvent.apply(xhr, arguments);
} else {
handler.apply(xhr, arguments);
}
}
XHROnLoad.apply(xhr, arguments);
setReadyStateChange();
}
function setReadyStateChange() {
setTimeout(function () {
if (xhr.onreadystatechange != readyStateChange) {
handler = xhr.onreadystatechange;
xhr.onreadystatechange = readyStateChange;
}
}, 1);
}
var handler;
setReadyStateChange();
}
xhrSend.apply(xhr, arguments);
};
}
Here is CasperJS code to emit a custom event on load of XHR:
casper.on("page.initialized", function (resource) {
var emitXHRLoad = function (xhr) {
window.callPhantom({eventName: 'xhr.load', eventData: xhr})
}
this.evaluate(addXHRListener, emitXHRLoad);
});
casper.on('remote.callback', function (data) {
casper.emit(data.eventName, data.eventData)
});
Here is a code to listen to "xhr.load" event and get the XHR response body:
casper.on('xhr.load', function (xhr) {
console.log('xhr load', xhr.requestUrl)
console.log('xhr load', xhr.responseText)
});
Additionally, you can also directly download the content and manipulate it later.
Here is the example of the script I am using to retrieve a JSON and save it locally :
var casper = require('casper').create({
pageSettings: {
webSecurityEnabled: false
}
});
var url = 'https://twitter.com/users/username_available?username=whatever';
casper.start('about:blank', function() {
this.download(url, "hop.json");
});
casper.run(function() {
this.echo('Done.').exit();
});
My node app posts an object (consisting of data collected in a form on the client) to Salesforce via their API. On receiving a success or error message, I would like to send it to the client-side, then display it. Socket.io seemed like the tool for this in my simple node/express3 app, but beyond the simple demo I'm not able to get data to pass between my server and my client.
My relevant server side code:
var express = require('express');
var port = 5432;
var app = module.exports = express();
var server = require('http').createServer(app);
var nforce = require('nforce');
var org = nforce.createConnection({
clientId: 'MY_CLIENT_ID',
clientSecret: 'MY_CLIENT_SECRET',
redirectUri: 'http://localhost:5432/oauth/_callback'
});
var io = require('socket.io').listen(server);
// here I authenticate with Salesforce, this works fine
app.post('/salesforce', function(req, res){
var lead = nforce.createSObject('Lead');
// here I construct the lead object, which also works fine
org.insert(lead, oauth, function(err, res) {
if (err === null) {
console.log(res);
leadSuccessMessage(res);
}
else {
console.log(err);
var error = {
errorCode: err.errorCode,
statusCode: err.statusCode,
messageBody: err.messageBody
};
console.log(error);
leadErrorMessage(error);
}
});
}
function leadSuccessMessage(res) {
var resp = res;
console.log('called success message from server');
io.sockets.on('connection', function (socket) {
socket.emit('sfRes', resp);
socket.on('thanks', function (data) {
console.log(data);
});
});
}
function leadErrorMessage(error) {
var err = error;
console.log('called error message from server');
io.sockets.on('connection', function (socket) {
console.log("socket is: " + socket);
socket.emit('sfRes', err);
socket.on('thanks', function (data) {
console.log(data);
});
});
}
And my relevant client side scripts:
<script src="/socket.io/socket.io.js"></script>
<script>
current.page = document.URL;
console.log("current page is: " + current.page);
var socket = io.connect(current.page);
socket.on('sfRes', function (data) {
console.log("client received: " + data);
fst.showLeadStatus(data);
socket.emit('thanks', {message: "received server feedback"});
});
</script>
When I post the form containing valid data using a spicy little AJAX call:
postToSF: function(){
$('#submitLead').on('click', function(e){
e.preventDefault();
var formData = $('#lead_form').serialize();
$.ajax({
type: 'POST',
url: '/salesforce',
data: formData,
success: function(){
fst.log('success!');
},
error: function(xhr, ajaxOptions, thrownError){
console.error(xhr.status); // 0
console.error(thrownError);
}
});
});
}
All I get are tears, and these in the server-side console:
// the result of `console.log(res)`
{ id: '00Qa000001FZfhKEAT', success: true, errors: [] }
// and proof that `leadSuccessMessage()` got called
called success message from server
Instead of calling this function from a client-side object as it's supposed to:
showLeadStatus: function(response){
if (response.success) {
fst.log("showing lead status as: " + response);
$('#leadStatus').addClass('success').removeClass('error').fadeIn().delay(4000).fadeOut();
}
else {
fst.log("showing lead status as: " + response);
$('#leadStatus').text(response.messageBody).addClass('error').removeClass('success').fadeIn().delay('4000').fadeOut();
}
$('#startOver').click();
}
Which works fine if I call it in the console passing it the data the server is supposed to be socketing over:
// this works, gosh darn it
fst.showLeadStatus({ id: '00Qa000001FZfhKEAT', success: true, errors: [] });
The Salesforce post error case doesn't surface anything to the client either. And there are no errors in the client or server console to contend with.
I'm stumped. Please help!
I would do something like this -
var mysocket = null;
var io = require('socket.io').listen(server);
io.sockets.on('connection', function (socket) {
mysocket = socket;
socket.on('thanks', function (data) {
console.log(data);
});
});
app.post('/salesforce', function(req, res){
....
....
})
function leadSuccessMessage(res) {
var resp = res;
console.log('called success message from server');
if(mysocket)
mysocket.emit('sfRes', resp);
}
function leadErrorMessage(error) {
var err = error;
console.log('called error message from server');
if(mysocket)
mysocket.emit('sfRes', err);
}