Using jsonp in nodejs and origin ajax - javascript

I'm trying to know how jsonp work, so I wrote a demo working on nodejs, without jQuery. But, it was not working.
Bellow was my code:
views/index.jade
doctype html
html
head
title Demo of jsonp
body
#result
script.
var xhr = new XMLHttpRequest();
var url = '/getjsonp?callback=abc'
function abc (data) {
alert('aaa')
document.getElementById('result').innerHTML = data.name;
}
xhr.open('GET', url);
xhr.send();
server.js
var express = require('express');
var bodyParser = require('body-parser');
var path = require('path');
var app = express();
var data = { name: 'jacket', company: 'fdd' };
app.set('views', path.join(__dirname, 'views/'));
app.set('view engine', 'jade');
app.use(bodyParser.urlencoded({ extended: false }))
app.get('/', function (req, res, next) {
res.render('index');
});
app.get('/getjsonp', function (req, res, next) {
var callback = req.query.callback;
res.writeHead(200, { 'Content-Type': 'application/javascript' });
res.end(callback + '(' + JSON.stringify(data) + ')');
});
app.listen(3000);
And here is the response:
abc({"name":"jacket","company":"fdd"})
As my expect, I define a method abc() in index.jade, then request '/getjsonp?callback=abc' by async ajax, it'll response a javascript which will execute the method: abc().
But it was not working like that, I dont know anywhere was wrong, hope you can tell me if you know.
Thanks!

I believe that everything is working here, it's just that in the client, you'll need to retrieve the data sent back from the server using:
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
eval(xhr.responseText);
}
};
hope this helps :)
NOTE: eval will make a string like "abc({a: 'a'})" to running the function abc with a parameter with 1 argument (which is the object {a: 'a'}

And I found another way to make it work without ajax:
<script>
function abc (data) {
alert('aaa')
document.getElementById('result').innerHTML = data.name;
}
</script>
<script type="text/javascript" src="/getjsonp?callback=abc"></script>

Related

Sending GET with parameters to HTTP server

I'm trying out the code basics and want to write some basic client-server app.
I have an HTML page where user inputs two numbers (num1 and num2) then it passes to JS which passes it to HTTP server written with NodeJS. On the server the numbers should be added and returned to the HTML page. But the server returns this error:
ReferenceError: num1 is not defined
What is wrong with the code?
Here is the JS code:
function myFunction(num1, num2) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
num1 = Math.floor(num1);
num2 = Math.floor(num2);
document.getElementById("result").innerHTML = this.responseText;
}
};
xhttp.open("GET", "http://localhost:8080?num1=2&num2=3", true);
xhttp.send();
}
And here is the NodeJS code:
var http = require('http');
http.createServer(function (req, res) {
var resnum = 2 + req.params(num1) + req.params(num2);
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(resnum);
res.end();
}).listen(8080);
You have to use the url module https://nodejs.org/api/http.html#http_message_url
var http = require('http');
var url = require('url');
http.createServer(function (req, res) {
var params = url.parse(req.url, true).query;
var resnum = 2 + params.num1 + params.num2; //or 2 + parseInt(params.num1) + parseInt(params.num2)
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(resnum);
res.end();
}).listen(8080);
If you want a concise code like yours you need to use some module like Express framework.
var express = require('express')
var app = express()
app.get('/', function (req, res) {
const resnum = 2 + parseInt(req.query.num1) + parseInt(req.query.num2);
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(resnum.toString())
})
app.listen(8080)
When you are using 'http' module only, the only thing you have to work with is req.url. You could try hard and get the parameters by breaking down the url but you would have a lengthy code:
var http = require('http');
http.createServer(function (req, res) {
const step1 = req.url.split('?')[1] //step1 = num1=2&num2=3
const step2 = step1.split('&') // step2 = [num1=2,num2=3]
let result = {};
step2.forEach((val) => { //break down strings further and put into result object
const value = val.split('=')
result[value[0]] = value[1]
})
var resnum = 2 + parseInt(result.num1) + parseInt(result.num2);
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(resnum.toString());
}).listen(8080);
Some notes:
You get that error because num1 is a variable argument to a
function. However we don't have a variable num1 declared.
Parameters come as strings so unless you parse them into integers,
you will have string concatenation and 223 as a result
res.write and res.end need a
string input so you need to parse back to string after calculations.

jQuery getJSON fails with 404 error

The URL that the getJSON request is sent to definitely exists, but the request fails with a 404 error. The URL just hosts a JSON object: here. I've also tried using the same request but replacing the destination with a local JSON file hosted in the same directory, which also fails with a 404 error. I'm guessing this
means that the error is either with my getJSON request, or with my node.js server configuration.
This is the function that makes the getJSON call:
function loginFunction(){
//check browser support
if(typeof(Storage) !== "undefined"){
//store dat shit
sessionStorage.setItem("username", document.getElementById('username').value);
sessionStorage.setItem("password", document.getElementById('password').value);
$(document).ready(function(){
$.getJSON(createUsernameURL(), function(data){
console.log(data);
var responseUsername = data.username;
document.getElementById("unresult").innerHTML = responseUsername;
var responsePassword = data.password;
document.getElementById("pwresult").innerHTML = responsePassword;
});
});
}else{
document.getElementById("pwresult").innerHTML = "your browser is out of date";
}
And this is the config file for my node.js server:
const http = require('http');
const express = require('express');
const app = express();
app.listen(3000,function(){
console.log(__dirname)
});
app.get('/', (req,res) => {
res.sendFile(__dirname + '/index.html');
});
app.use("/static", express.static(__dirname + '/static'));
The createUsernameURL() function just appends a couple pieces of user-entered information to a base URL, but even hard-coding the exact database link mentioned above gives the same issues.

How do you send a post via XMLhttprequest to my own Node server in vanilla javascript?

I am trying to send data to node via a XMLhttprequest. The data looks like this (/q/zmw:95632.1.99999.json). My connection to Node is correct, however, I was getting an empty object so I set the headers to Content-Type application/json and then stringified the data. However Node gives me a Unexpected token " error. I presume it is because of the string, however, if I don't stringify the data then it errors out because of the "/" in the data. How do i properly send the data using pure Javascript. I want to stay away from axios and jquery because I want to become more proficient in vanilla javascript. I will make the final call to the api in node by assembling the url prefix and suffix.
Here is my code:
function getCityForecast(e){
//User selects option data from an early JSONP request.
var id = document.getElementById('cities');
var getValue = id.options[id.selectedIndex].value;
//Assembles the suffix for http request that I will do in Node.
var suffix = getValue + ".json";
var string = JSON.stringify(suffix);
console.log(suffix);
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://localhost:3000/", true);
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.send(string);
}
Node.js code:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var path = require('path');
var request = require('request');
var http = require('http');
// ****************** Middle Ware *******************
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(express.static(__dirname + '/public'));
app.post('/', function(req, res){
console.log('working');
console.log(req.body);
});
app.listen(3000, function() { console.log('listening')});
I figured it out my mistake and this was my problem. I was trying to send a string instead of an object. So it wasn't proper JSON like this:
var string = JSON.stringify(suffix);
To remedy the situation I added:
var newObj = JSON.stringify({link : suffix});
This allowed my post to be successful because I was now sending an object hence the word Javascript Object Notation.
This is working for me, at the moment. The REST API I'm hitting requires a token. Yours might not, or it might be looking for some other custom header. Read the API's documentation. Note, you might need a polyfill/shim for cross browser-ness (promises). I'm doing GET, but this works for POST, too. You may need to pass an object. If you're passing credentials to get a token, don't forget window.btoa. Call it like:
httpReq('GET', device.address, path, device.token).then(function(data) {
//console.log(data);
updateInstrument(deviceId,path,data);
}, function(status) {
console.log(status);
});
function httpReq(method, host, path, token) {
if(method === "DELETE" || method === "GET"|| method === "POST" || method === "PUT" ){
var address = 'https://' + host + path;
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open(method, address, true);
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader ("X-auth-token", token);
//xhr.setRequestHeader ("Content-Type", "application/x-www-form-urlencoded");
xhr.onload = function() {
var status = xhr.status;
if (status == 200 || status == 201 || status == 202) {
resolve(xhr.response);
}
// this is where we catch 404s and alert what guage or resource failed to respond
else {
reject(status);
}
};
xhr.send();
});
} else {
console.log('invalid method');
}
};

How to debug failing xmlhttprequest

I am trying to retrieve data from a database on my server to use client-side. It is failing without appearing to actually throw any errors and I can't figure out how to debug it.
My server is written in node.js/express with a MongoDB database and looks like:
var express = require('express');
var fs = require('fs');
var Sample = function() {
var self = this;
self.setupVariables = function() {
self.ipaddress = process.env.OPENSHIFT_NODEJS_IP;
self.port = process.env.OPENSHIFT_NODEJS_PORT || 8080;
if(process.env.OPENSHIFT_MONGODB_DB_PASSWORD){
connection_string = process.env.OPENSHIFT_MONGODB_DB_USERNAME + ":" +
process.env.OPENSHIFT_MONGODB_DB_PASSWORD + "#" +
process.env.OPENSHIFT_MONGODB_DB_HOST + ':' +
process.env.OPENSHIFT_MONGODB_DB_PORT + '/' +
process.env.OPENSHIFT_APP_NAME;
}
console.log(connection_string)
};
self.createRoutes = function() {
self.routes = { };
self.routes['/'] = function(req, res) {
res.setHeader('Content-Type', 'text/html');
res.send(self.cache_get('index.html') );
};
self.routes['/testdata'] = function(req, res) {
console.log('Got request for testdata')
res.setHeader('Content-Type', 'application/json');
MongoClient.connect('mongodb://'+connection_string, function(err, db) {
if(err) throw err;
var collection = db.collection('TestData').find().limit(10).toArray(function(err, docs) {
if(err) throw err;
res.send(docs);
db.close();
})
})
}
};
self.initializeServer = function() {
self.createRoutes();
self.app = express();
['js'].forEach( function(dir) {
self.app.use('/'+dir, express.static(__dirname+'/'+dir));
})
// Add handlers for the app (from the routes).
self.app.get(function(req, res, next) {
console.log('Got request:', req); // used to debug
next();
});
for (var r in self.routes) {
self.app.get(r, self.routes[r]);
}
};
self.initialize = function() {
self.setupVariables();
self.initializeServer();
};
self.start = function() {
self.app.listen(self.port, self.ipaddress)
});
};
var myapp = new Sample();
myapp.initialize();
myapp.start();
My client side (index.html) code is:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
<script>
// Get data from server
var xmlHttp = null;
xmlHttp = new XMLHttpRequest();
xmlHttp.open( "GET", "http://my.example.com/", true);
xmlHttp.send( "/testdata" );
xmlHttp.onreadystatechange=function() {
if (xmlHttp.readyState==4 && xmlHttp.status==200) {
var data = xmlHttp.responseText
window.onload = function() {
document.getElementById('p1').innerHTML = data
}
}
}
</script>
<p id="p1"></p>
</body>
</html>
My goal is to get data from the database to use on the html page. I am trying to do that by issuing an xmlhttprequest to get /testdata from the server. Then I thought the server should route that request to the appropriate function. But when I run this (well, the version with lots of other extraneous stuff that I deleted for this post), the request just sits there with xmlHttp.status=1.
Two options for answers:
1) What is wrong?
2) How do I even go about debugging this problem? The server is hosted remotely so I don't think I can use a tool like node-inspector.
I think you are misunderstanding how to use the XHR send(). It's for actually sending data, like in a POST, PUT or DELETE. You want to actually have /testdata as part of your URL in the open() call, and use just .send().

Node.js issue with calling json data

I have some issues with getting json data from a json file, first of all here is the error:
"NetworkError: 404 Not Found - http://localhost:8000/channels.json"
Here is the code for getting json data in my html file:
<div id="result"></div>
<script type="text/javascript">
// read episodes in channel
function ajaxRequest(){
if (window.XMLHttpRequest) // if Mozilla, Safari etc
return new XMLHttpRequest();
else
return false;
}
var mygetrequest=new ajaxRequest();
mygetrequest.onreadystatechange=function(){
if (mygetrequest.readyState==4){
if (mygetrequest.status==200 || window.location.href.indexOf("http")==-1){
var jsondata=eval("("+mygetrequest.responseText+")"); //retrieve result as an JavaScript object
var rssentries=jsondata.channels;
var output='<ul>';
for (var i=0; i<rssentries.length; i++){
output+='<li>';
output+=rssentries[i].channel_id+'</a><br>';
output+=''+rssentries[i].name+'';
output+='</li>';
}
output+='</ul>';
document.getElementById("result").innerHTML=output;
}else{
alert("An error has occured making the request");
}
}
}
mygetrequest.open("GET", "channels.json", true);
mygetrequest.send(null);
</script>
so the html works standing alone, but when i try to render it in my node server, i get error, code in my node server in express:
var express = require('express');
var http = require('http');
var app = express();
var server = module.exports = http.createServer(app);
server.listen(8000);
console.log("Express server listening on port 8000 in %s mode");
app.set('views', __dirname + '/views');
app.engine('html', require('ejs').renderFile);
app.get('/episodes', function(req, res){
res.render('episodes.html');
});
So i have to do the json data call in the server in order to avoid the error, there's no other way?
If u are rendering on the server, you can't use Ajax. Ajax only runs from within the browser, not on the server. On the server you have to read the file directly, pass it to the renderer, and render it inside of the template. For example:
var fs = require('fs');
app.get('/episodes', function(req, res){
fs.readFile('./public/channels.json', 'utf8', function (err, data) {
var channels = JSON.parse(data);
res.render('episodes.html', channels);
});
});
Inside your ejs template you'll have to render the channels directly into the page.
Another option to go along with what Max suggested is to use res.format() to return the specific content type you want.
http://expressjs.com/api.html#res.format
res.format({
text: function(){
res.send(...);
},
html: function(){
res.send(...);
},
json: function(){
fs.readFile('./public/channels.json', 'utf8', function (err, data) {
var channels = JSON.parse(data);
res.send(channels);
});
}
});

Categories