JSONP call with server-side language as Javascript - javascript

I've been trying to use JSONP to get a JSON object from a server via a client-side call (on a different port). However, because my server is implemented in javascript using Node.js and Express, I haven't been able to find much on JSONP with Javascript on the server as most sites I found used php for server-side code.
I believe the issue is with how I set up the url with respect to the callback, which I'm a bit fuzzy on cause it's new to me.
On the server:
//Setting up server stuff
var express = require('express'),
app = express.createServer();
app.use(express.logger());
//Making a connection to the mongoDB to get the data that I want to display in the JSON object
new Db('prism',
new Server("127.0.0.1", 27017, {auto_reconnect: false}), {}).open(function(err, db) {
app.get('/getData', function(req, res) {
console.log('JSONPCALLBACK CALLED WITH RETURNDATA PASSED IN; SERVER SIDE');
if (typeof callback == 'function') {
console.log('callback is defined');
callback(returnData);
}
else {
console.log('callback is not defined');
}
}
});
And on the client:
$.ajaxSetup({ cache : false });
$.getJSON('http://127.0.0.1:1337/getData&callback=?', function(rtndata) {
console.log('SUCCESS');
console.log(rtndata);
});
embedded by the standard tags.
But I get the error:
GET http://127.0.0.1:1337/getData&callback=jQuery16108897686484269798_1311007334273?_=1311007334342 404 (Not Found)
The server is on port 1337 while the client is run through MAMP on localhost:8888. I'm not sure if its even a localhost related issue as I've been trying to get this setup running for a few days now.
I believe the issue has something to do with not writing this line, which is in php, into my server-side Javascript. Most of the JSONP examples I found had something like this. But I'm not sure.
if ($GET['callback'] != '')
$json = $GET['callback']."( $json )";
return $json;
Any help would be greatly appreciated. I apologize ahead of times for being super verbose.
Bests,
Cong

I think you have two problems. First is the 404. Completely separate from getting the client-side jQuery code to work, you need to make sure that you can issue a regular browser request (i.e. paste in that URL) and get back what you expect. I haven't used express, so it's hard for me to comment on why you'd be getting that, except to say that I don't see 1337 anywhere in your server-side code, just what appears to be the port number 27017.
The second problem is that you don't actually want to execute the callback on the server, just build the JSON response including the callback (string) prefixed to it.
So instead of this ...
if (typeof callback == 'function') {
console.log('callback is defined');
callback(returnData);
}
else {
console.log('callback is not defined');
}
try this:
if (callback) {
console.log('callback is defined');
res.write(callback + '(' + JSON.stringify(returnData) + ')');
}
else {
console.log('callback is not defined');
}
Hope this helps!

From http://api.jquery.com/jQuery.getJSON/ there is an example that includes 2 '?' in the URL.
you only have one, so try
$.getJSON('http://127.0.0.1:1337/getData?callback=?', function(rtndata) {
and see if that gets rid of your 404
then look #jimbojw suggestion for returning a proper jsonp formated responce.

Use this:
var express = require("express");
var server = express.createServer();
server.enable("jsonp callback");
server.get("/foo", function(req, res) {
// this is important - you must use Response.json()
res.json("hello");
});
jsonp with node.js express

Related

Neither Node.js PUT or POST routes are presenting the data that is being received

I tried this with a number of different modules and methods.
Even by proving the other modules do work as expected in Node by building a separate test project and testing each module individually.
Posting FROM Node's hosted router to a remote API (not TO Node's hosted API)
This problem is not one of SENDING data to an API. It must IMO a problem in the receiving API's not giving up the data it IS receiving for some reason.
I've proven the PUT or POST calls are sending the data by sending the call to http://httpbin/org. That site shows me I'm sending what I expect to be sending.
Here is how I'm sending. I can even see in the receiving API that that API is certainly getting called successfully.
-- sending -- ((Again. This shows my node.http attempt. But I get the same problem using requestjs, requestifyjs, needlejs))
router.get('/', function (req, res, next) {
var hst = req.headers.host.split(':');
var lookbackURL = 'https://' + req.headers.host + req.baseUrl;
lookbackURL = 'http"httpbin.org/put';
var dat = {
what: 'ever'
, try: 'again'
};
var bdy = JSON.stringify(dat);
var options = {
host: hst[0], port: hst[1], path: req.baseUrl, method: 'PUT'
, headers: { 'Content-Type': 'application/json' }
};
var r = nodeHttp.request(options); r.write(bdy); r.end();
res.sendStatus(200);
});
-- receiving --
router.put('/', function (req, res, next) {
console.log('r', req);
});
No matter what module or method I use, in all cases, the receiving req object doesn't contain the what or try data.
BUT in my test project the data is there as I expect it to be, in all cases.
Doing the same console.log(req); in the test project, reqestjs, requestjs, needlejs, node.http all show a proper body object.
But in this problem there isn't a body object in req.
And sending this put/post to http://httpbin.org I can see the body object is being sent.
Any ideas?
Issue found. And it was something no one on here could have gotten for the code I posted.
For reasons I will not go into I have to take body-parser out this application. This also means app.use() won't have a parser given to it.
And that means I have to deal with getting the data on my own. So I've added a req.on('data') listener to read the chunk from the call to the API.
router.put('/', function (req, res, next) {
var data = '';
req.on('data', function (chunk) {
data += chunk;
.....
});
.....
I also decided to do this as a PUT using Requestify.
This just goes to show how easy it is to become complacent and forget how things really work; the assumption of body-parser (or other things) always being there for instance. Or what it is really doing for you.
NEXT I have to figure out how to get a value out of the `req.on('data) back to the method PUTting to the API. Any tips? Appreciated.

How do I use client side JavaScript to find and return data from MongoDB and a Node.js server with no framework?

I have read all the questions on SO that I could find. They all use Express, Mongoose or they leave something out. I understand that Node.js is the server. I understand the MongoDB require is the driver the Node.js server uses to open a connection to the MongoDB. Then, on the server, I can do (from the documentation):
var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
var ObjectId = require('mongodb').ObjectID;
var url = 'mongodb://localhost:27017/test';
var findRestaurants = function(db, callback) {
var cursor =db.collection('restaurants').find( );
cursor.each(function(err, doc) {
assert.equal(err, null);
if (doc != null) {
console.dir(doc);
} else {
callback();
}
});
};
// Connect to the db
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
findRestaurants(db, function() { //I don't want to do this as soon as the server starts
db.close();
});
});
//if I put findRestaurant here,
function findRestaurant(data){
}
How do I call it from the client?
I do not want to find data as soon as I start the server. I realize those are examples, but what I cannot find is a way where the client requests some data and where the Node.js server returns it.
I have seen close examples using jQuery, Angular on the client, and then Express, Mongoose, Meteor, , etc.
All I want to understand is how I make this request from the client's browser. I can do that with XMLhttpRequest(), so I can put that part together, I believe. But, any example is appreciated.
But what is waiting on the Node.js side of things (how do I set up my function to be called once the server is listening)?
How do I create a function on the server side, maybe "GetRestaurants" and have that return the data it gets using find()?
I cannot find this information, this simple, anywhere. Is it too complicated to do the example without a framework?
I do not wish to copy and paste from something using Express, etc. without understanding what's going on. Most explanations never say, this goes on the Node.js side. This is client. I know I am expected to do my own research, but I am not putting it together, too used to RDBMSes, IIS, Apache, PHP, and so on.
I believe I have a fundamental misunderstanding of what's going on in the paradigm.
Please. No REST API creation, no frameworks of any kind on Node.js other than using the MongoDB library (unless there is an absolute requirement), not even jQuery, Angular, Jade, or anything else for the client side, straight up JavaScript on all sides.
I have seen questions like this,
How to display data from MongoDB to the frontend via Node.js without using a framework
But they do not show what I am asking. They do it all at once, as soon as the database connects. What if I want to do a delete or insert or find? There are many SO questions like this, but I have not hit the one that shows what I am looking for.
This should give the guidance. Once you go to a browser and type http://localhost:5155 the callback function (request, response) { will be called and the request to db will be made. Make sure you get response and then start working on the client side code:
const http = require('http');
const MongoClient = require('mongodb').MongoClient;
const assert = require('assert');
const url = 'mongodb://localhost:27017/test';
const server = http.createServer(function (request, response) {
getData(function (data) {
response.end(data);
});
});
function getData(callback) {
// Connect to the db
MongoClient.connect(url, function (err, db) {
assert.equal(null, err);
findRestaurants(db, function (data) {
db.close();
callback(data);
});
});
const findRestaurants = function (db, callback) {
const cursor = db.collection('restaurants').find();
const data = [];
cursor.each(function (err, doc) {
assert.equal(err, null);
data.push(doc);
if (doc === null) {
callback(data);
}
});
};
}
server.listen(5155);

any way to send a function with socket.io?

guys.
I want to send a function to browser with socket.io, but failed to do it.
On server side, I response a function with emit, but I get a undefined on browser.
Is there any way to get a function from server with socketio?
there is my code.
// server.js
var static = require('node-static');
var http = require('http');
var file = new(static.Server)();
var app = http.createServer(function(req, res) {
file.serve(req, res);
}).listen(8000);
io = require('socket.io').listen(app);
io.sockets.on('connection', function(socket) {
socket.on('schedule', function() {
console.log('SCHEDULE TASK');
socket.emit('schedule', function() { console.log('hello world'); });
});
});
// client.js
var socket = io.connect('http://localhost:8000');
socket.on('schedule', function(fn) {
fn();
});
socket.emit('schedule');
You cannot send an actual function. You could send a string of Javascript and then you could turn that into a function in the client.
But, I'd suggest you really ought to rethink what you're trying to do here. Generally, the client already has the code it needs (from the script tags that it downloaded) and you send the client data which it then passes to the code it already has or data that it uses to make decisions about which code that it already has to call.
If you show us the real world problem you're trying to solve, we can likely suggest a much better solution than sending a string of Javascript code to the client.
If you really wanted to send a function, you would have to turn it into a string first, send the string, then use the string to turn it back into a function in the client by using a Function object or eval() or creating your own dynamic script tag with inline source.
You can only send strings via socket.io, not functions. That being said, I suggest you to send function names instead.
//server.js
socket.emit('schedule', 'helloworld');
//client.js
function helloworld(){
console.log('hello world');
}
socket.on('schedule',function(name){
window[name](); //hello world
});

Using the PUT method with Express.js

I'm trying to implement update functionality to an Express.js app, and I'd like to use a PUT request to send the new data, but I keep getting errors using PUT. From everything I've read, it's just a matter of using app.put, but that isn't working. I've got the following in my routes file:
send = function(req, res) {
req.send(res.locals.content);
};
app.put('/api/:company', function(res,req) {
res.send('this is an update');
}, send);
When I use postman to make a PUT request, I get a "cannot PUT /api/petshop" as an error. I don't understand why I can't PUT, or what's going wrong.
You may be lacking the actual update function. You have the put path returning the result back to the client but missing the part when you tell the database to update the data.
If you're using MongoDB and ExpressJS, you could write something like this :
app.put('/api/:company', function (req, res) {
var company = req.company;
company = _.extend(company, req.body);
company.save(function(err) {
if (err) {
return res.send('/company', {
errors: err.errors,
company: company
});
} else {
res.jsonp(company);
}
})
});
This mean stack project may help you as it covers this CRUD functionality which I just used here swapping their articles for your companies. same same.
Your callback function has the arguments in the wrong order.
Change the order of callback to function(req, res).
Don't use function(res, req).
Also if you want to redirect in put or delete (to get adress), you can't use normal res.redirect('/path'), you should use res.redirect(303, '/path') instead. (source)
If not, you'll get Cannot PUT error.
Have you been checking out your headers information?
Because header should be header['content-type'] = 'application/json'; then only you will get the update object in server side (node-express), otherwise if you have content type plain 'text/htm' like that you will get empty req.body in your node app.

Basic Ajax send/receive with node.js

So I'm trying to make a very basic node.js server that with take in a request for a string, randomly select one from an array and return the selected string. Unfortunately I'm running into a few problems.
Here's the front end:
function newGame()
{
guessCnt=0;
guess="";
server();
displayHash();
displayGuessStr();
displayGuessCnt();
}
function server()
{
xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET","server.js", true);
xmlhttp.send();
string=xmlhttp.responseText;
}
This should send the request to server.js:
var http = require('http');
var choices=["hello world", "goodbye world"];
console.log("server initialized");
http.createServer(function(request, response)
{
console.log("request recieved");
var string = choices[Math.floor(Math.random()*choices.length)];
console.log("string '" + string + "' chosen");
response.on(string);
console.log("string sent");
}).listen(8001);
So clearly there are several things going wrong here:
I get the feeling the way I am "connecting" these two files isn't correct both in the xmlhttp.open method and in using response.on to send the string back to the front end.
I'm a little confused with how I call this page on localhost. The front end is named index.html and the sever posts to 8001. What address should I be go to on localhost in order to access the initial html page after I have initialized server.js? Should I change it to .listen(index.html) or something like that?
are there other obvious problems with how I am implementing this (using .responsetext etc.)
(sorry for the long multi-question post but the various tutorials and the node.js source all assume that the user already has an understanding of these things.)
Your request should be to the server, NOT the server.js file which instantiates it. So, the request should look something like this: xmlhttp.open("GET","http://localhost:8001/", true); Also, you are trying to serve the front-end (index.html) AND serve AJAX requests at the same URI. To accomplish this, you are going to have to introduce logic to your server.js that will differentiate between your AJAX requests and a normal http access request. To do this, you'll want to either introduce GET/POST data (i.e. call http://localhost:8001/?getstring=true) or use a different path for your AJAX requests (i.e. call http://localhost:8001/getstring). On the server end then, you'll need to examine the request object to determine what to write on the response. For the latter option, you need to use the 'url' module to parse the request.
You are correctly calling listen() but incorrectly writing the response. First of all, if you wish to serve index.html when navigating to http://localhost:8001/, you need to write the contents of the file to the response using response.write() or response.end(). First, you need to include fs=require('fs') to get access to the filesystem. Then, you need to actually serve the file.
XMLHttpRequest needs a callback function specified if you use it asynchronously (third parameter = true, as you have done) AND want to do something with the response. The way you have it now, string will be undefined (or perhaps null), because that line will execute before the AJAX request is complete (i.e. the responseText is still empty). If you use it synchronously (third parameter = false), you can write inline code as you have done. This is not recommended as it locks the browser during the request. Asynchronous operation is usually used with the onreadystatechange function, which can handle the response once it is complete. You need to learn the basics of XMLHttpRequest. Start here.
Here is a simple implementation that incorporates all of the above:
server.js:
var http = require('http'),
fs = require('fs'),
url = require('url'),
choices = ["hello world", "goodbye world"];
http.createServer(function(request, response){
var path = url.parse(request.url).pathname;
if(path=="/getstring"){
console.log("request recieved");
var string = choices[Math.floor(Math.random()*choices.length)];
console.log("string '" + string + "' chosen");
response.writeHead(200, {"Content-Type": "text/plain"});
response.end(string);
console.log("string sent");
}else{
fs.readFile('./index.html', function(err, file) {
if(err) {
// write an error response or nothing here
return;
}
response.writeHead(200, { 'Content-Type': 'text/html' });
response.end(file, "utf-8");
});
}
}).listen(8001);
console.log("server initialized");
frontend (part of index.html):
function newGame()
{
guessCnt=0;
guess="";
server();
displayHash();
displayGuessStr();
displayGuessCnt();
}
function server()
{
xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET","http://localhost:8001/getstring", true);
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){
string=xmlhttp.responseText;
}
}
xmlhttp.send();
}
You will need to be comfortable with AJAX. Use the mozilla learning center to learn about XMLHttpRequest. After you can use the basic XHR object, you will most likely want to use a good AJAX library instead of manually writing cross-browser AJAX requests (for example, in IE you'll need to use an ActiveXObject instead of XHR). The AJAX in jQuery is excellent, but if you don't need everything else jQuery offers, find a good AJAX library here: http://microjs.com/. You will also need to get comfy with the node.js docs, found here. Search http://google.com for some good node.js server and static file server tutorials. http://nodetuts.com is a good place to start.
UPDATE: I have changed response.sendHeader() to the new response.writeHead() in the code above !!!
Express makes this kind of stuff really intuitive. The syntax looks like below :
var app = require('express').createServer();
app.get("/string", function(req, res) {
var strings = ["rad", "bla", "ska"]
var n = Math.floor(Math.random() * strings.length)
res.send(strings[n])
})
app.listen(8001)
https://expressjs.com
If you're using jQuery on the client side you can do something like this:
$.get("/string", function(string) {
alert(string)
})
I was facing following error with code (nodejs 0.10.13), provided by ampersand:
origin is not allowed by access-control-allow-origin
Issue was resolved changing
response.writeHead(200, {"Content-Type": "text/plain"});
to
response.writeHead(200, {
'Content-Type': 'text/html',
'Access-Control-Allow-Origin' : '*'});
Here is a fully functional example of what you are trying to accomplish. I created the example inside of hyperdev rather than jsFiddle so that you could see the server-side and client-side code.
View Code:
https://hyperdev.com/#!/project/destiny-authorization
View Working Application: https://destiny-authorization.hyperdev.space/
This code creates a handler for a get request that returns a random string:
app.get("/string", function(req, res) {
var strings = ["string1", "string2", "string3"]
var n = Math.floor(Math.random() * strings.length)
res.send(strings[n])
});
This jQuery code then makes the ajax request and receives the random string from the server.
$.get("/string", function(string) {
$('#txtString').val(string);
});
Note that this example is based on code from Jamund Ferguson's answer so if you find this useful be sure to upvote him as well. I just thought this example would help you to see how everything fits together.

Categories

Resources