I would like to develop a client server side with nodejs and javascript/jquery but I am stuck.
I have a big form, user submits and data are send to /getData url and that works perfectly. But my problem now it's when I want to get those data from /getData to my client side.
This is my client file:
var client = {};
client.start = function () {
client.getData();
};
client.cb_get = function () {
var data={};
if (this.readyState == 4 && this.status == 200) {
data= JSON.parse(this.responseText);
alert("We get the data" + JSON.stringify(data, null, 4));
client.chart(data);
} else {
alert("Sorry this page is not allow without processing any form");
}
};
client.get = function(req, cb) {
var xhr = new XMLHttpRequest();
xhr.open("GET", req, true);
xhr.onreadystatechange = cb;
xhr.send();
};
client.getData= function () {
var req="http://localhost:3000/getData";
client.get(req,client.cb_get);
};
client.chart= function (data) {
//Display data as charts using jquery in an other html page.
};
window.onload = setTimeout(client.start, 1);
HTMLElement.prototype.has_class = function (c)
{
return this.className.indexOf(c) >= 0;
};
But I have a 404 error all the time and I don't know why.
my server file :
var express = require('express')
bodyParser =require("body-parser");
routes= require('./router.js');
var app= express();
app.use(express.static(__dirname + '/'));
//Here we are configuring express to use body-parser as middle-ware.
app.use(bodyParser.urlencoded({ extended: false }));
//define our routes
app.get('/', routes.index); //open home page
app.get('/simulation', routes.simulation);
app.get('/chartData', routes.chartData);
app.post('/getData', routes.getData);
//In case of malicious attacks or mistyped URLs
app.all('*', function(req, res){
res.send(404);
})
var server = app.listen(3000, function () {
var host = server.address().address
var port = server.address().port
console.log('Example app listening at http://%s:%s', host, port)
})
my router file:
module.exports.index= function(req, res){
fs.readFile('index.html', function(err, page) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(page);
res.end();
});
};
module.exports.simulation= function(req, res){
fs.readFile('simulation.html', function(err, page) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(page);
res.end();
});
};
module.exports.chartData= function(req,res) {
fs.readFile('chartPage.html', function(err, page) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(page);
res.end();
});
};
module.exports.getData= function(req,res) {
var data= {};
data= req.body;
res.send(JSON.stringify(data, null, 4));
console.log(req.body);
};
So where I am wrong?
Moreover, when I submit, my /getdata page opens (normal due to action= /getData specified in my form tag) but I want to open directly my html page with charts. How can I do that?
Sorry guys for my long post, but I really need help.
Your ajax request does
xhr.open("GET", "http://localhost:3000/getData", true);
your route listens for
app.post('/getData', routes.getData);
notice how you send a GET request and listen for a POST request, it's not the same thing, so you end up in the 404 route instead.
You either have to change the ajax request, and send a POST request, or the route and listen for a GET request.
Related
I have this script with which I'm trying to POST, GET and DELETE some stuff.
When I try POST or GET, the right messages are logged, but when I try DELETE, I get the following error:
Cannot GET /del_user
The URL I'm using is http://127.0.0.1:8081/del_user
What can be wrong in here?
var express = require('express');
var app = express();
// This responds with "Hello World" on the homepage
app.get('/', function (req, res) {
console.log("Got a GET request for the homepage");
res.send('Hello GET');
})
// This responds a POST request for the homepage
app.post('/', function (req, res) {
console.log("Got a POST request for the homepage");
res.send('Hello POST');
})
// This responds a DELETE request for the /del_user page.
app.delete('/del_user', function (req, res) {
console.log("Got a DELETE request for /del_user");
res.send('Hello DELETE');
})
// This responds a GET request for the /list_user page.
app.get('/list_user', function (req, res) {
console.log("Got a GET request for /list_user");
res.send('Page Listing');
})
// This responds a GET request for abcd, abxcd, ab123cd, and so on
app.get('/ab*cd', function(req, res) {
console.log("Got a GET request for /ab*cd");
res.send('Page Pattern Match');
})
var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port)
})
I solved it by changing the app.delete to app.get and then placing the required remove statement inside the app.get. Something like this :-
app.get('/delete/:userId', (req, res) => {
Users.remove({ _id: req.params.userId }, (error, posts) => {
if (error) {
console.warn(error);
}
else {
data = posts
res.render("delete", {"data": data})
}
});
});
In your code you're binding the /del_user URL to the HTTP DELETE method.
So all you need to do is specify the DELETE method in your application or in Postman.
If you're not using it, it's an App in Google Chrome and you might want to download it, it makes your life a LOT easier ;)
Also, since the HTTP method is already declared to be DELETE, there is no need to specify it in the URL.
This is part of the RESTful working.
If you are using AJAX to try your code, you need to specify the method, which is delete.
$.ajax({
url: "http://127.0.0.1:8081/del_user",
type: "DELETE"
});
Inside my application code, for a specific set of APIs, I'm making a NodeJS request like following, which should return a image as the body. This same request works fine on Postman (and I can see the image).
module.exports = {
getThumbnail: function (thumbnailUrn, env, token, onsuccess){
request({
url: config.baseURL(env) + config.thumbail(thumbnailUrn),
method: "GET",
headers: {
'Authorization': 'Bearer ' + token,
}
}, function (error, response, body) {
// error check removed for simplicity...
onsuccess(body);
});
}
}
The above code run under my own security checks and adds the token header. It works fine (request calls return 200/OK).
Now on my app router I want to respond this as an image, but the output is not being interpreted as an image. Here is what I have:
var dm = require(/*the above code*/);
// express router
var express = require('express');
var router = express.Router();
router.get('/getThumbnail', function (req, res) {
var urn = req.query.urn;
dm.getThumbnail(urn, req.session.env, req.session.oauthcode, function (thumb) {
res.writeHead(200,
{
'Content-Type': 'image/png'
}
);
// at this point, the 'thumb' variable is filled
// but I believe is not properly encoded...
// or maybe the res.end output is missing something...
res.end(thumb, 'binary');
});
});
module.exports = router;
EDIT: as commented by Nodari Lipartiya, this is kind of proxy behaviour ( server(responds with image) -> proxy (node.js/resends to client) -> end user)
I'm not sure what is coming back in thumb, but the following snippet seemed to work for me (bypassing Express for simplicity):
var http = require("http")
var fs = require("fs")
var server = http.createServer(listener)
server.listen(() => {
console.log(server.address().port)
})
var binary = fs.readFileSync("path to local image")
function listener(req, resp) {
resp.writeHead(200,
{
'Content-Type': 'image/png'
}
);
resp.end(new Buffer(binary), "binary")
}
What happens if you wrap it in a Buffer?
If I've understood everything correctly:
I did this
server.js
var fs = require('fs');
var express = require('express');
var app = express();
app.get('/img', function(req, res, next) {
var stream = fs.createReadStream('img.jpeg');
var filename = "img.jpeg";
filename = encodeURIComponent(filename);
res.setHeader('Content-disposition', 'inline; filename="' + filename + '"');
res.setHeader('Content-type', 'image/jpeg');
stream.pipe(res);
});
app.listen(9999, function () {
console.log('Example app listening on port 9999!');
});
proxy.js
var request = require('request');
var express = require('express');
var app = express();
app.get('/img', function(req, res, next) {
console.log('proxy/img');
request({
url: 'http://localhost:9999/img',
method: "GET",
}, function (error, response, body) {
res.end(body, 'binary');
});
});
app.listen(9998, function () {
console.log('Example app listening on port 9998!');
});
req.js
var request = require('request');
request({
url: 'http://localhost:9998/img',
method: "GET",
}, function (error, response, body) {
console.log('body', body);
});
works for me. Please, let me know if you'll need help.
I have a REST API server which is running on one VM1. On other VM2 machine I have built a node js server which is running as proxy. On the same VM2 machine I have application (hosted with apache which serves only html, js and css files). My node js server only resends the api calls back to the API server. This is working fine, until new requirement arrive - to add a new API endpoint (on the node js server) to download files (csv). In order to make download happen, I need to use GET method. The thing is that the required data is available only on POST endpoint from the main API server, and I am calling the API endpoint to get the data and send it back. This is the code I am trying to work it out:
var express = require('express');
var cors = require('cors');
var request = require('request');
var http = require('http');
var csv = require("fast-csv");
var config = require("./config.js");
var corsOptions = {
origin: function(origin, callback){
var originIsWhitelisted = config.whitelist.indexOf(origin) !== -1;
callback(null, originIsWhitelisted);
}
};
var handler = function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
};
var app = express();
// Enable CORS for all requests
app.use(cors(corsOptions));
app.options('*', cors(corsOptions)); // specially for pre-flight requests
app.get('/download', function(req, res){
var limit = req.query.limit;
var offset = req.query.offset;
var options = {
method: 'POST',
url: config.apiServerHost + '/search',
useQuerystring: true,
qs: {'limit': limit, 'offset': offset},
rejectUnauthorized: false,
body: 'from=date&to=date'
};
var filename = 'data.csv';
res.setHeader('Content-disposition', 'attachment; filename=\"data.csv\"');
res.setHeader('content-type', 'text/csv');
var csvStream = csv.createWriteStream({
headers: true,
objectMode: true,
transform: function (row) {
return row;
}
});
console.log(options);
function callback(error, response, body) {
if (!error && response.statusCode == 200) {
var data = JSON.parse(body);
for(var i = 0; i < data.length; i++)
csvStream.write({
"col1": "value1-"+data[0][i],
"col2": "value2-"+data[1][i],
"col3": "value3-"+data[2][i],
"col4": "value4-"+data[3][i]
});
}
csvStream.end();
}
else {
console.log("Error:", error, body);
}
}
req.pipe(request(options, callback));//.pipe(res)
csvStream.pipe(res);
});
app.use('/api', function(req, res) {
var url = config.apiServerHost + req.url;
console.log(url);
req.pipe(request({
"rejectUnauthorized": false,
"url": url
}, function(error, response, body){
if(error) {
console.log(new Date().toLocaleString(), error);
}
})).pipe(res);
});
This all code works fine when request method is POST (the same as main API server). However I receive "[Error: write after end]" when I add the body in options object. Can someone help me figure out what is happening and how to solve this problem? Thanks.
The [Error: write after end] show pip data after .end(), for your codes
req.pipe(request(options, callback));//.pipe(res)
csvStream.pipe(res);
In the callback function, the csvStream.end(); is called, then invoke csvStream.pipe could cause this error.
I'm new to Node.js.
I'm creating a simple node/express application that serves a single web page containing one button that when clicked makes a jQuery ajax request to an Express route.
The route callback makes an http.get request to openexchangerates.org for some json data containing foreign exchange rates. The JSON is then output to the Developer Tools console window.
The application works on the first button click, but on any subsequent clicks the console window displays:
GET http://127.0.0.1:3000/getFx net::ERR_CONNECTION_REFUSED
A screen grab of the Developer Tools console window shows the result of the first click, and then the second click when the connection is refused.
The error detail is as follows:
GET http://127.0.0.1:3000/getFx net::ERR_CONNECTION_REFUSED jquery-2.1.3.min.js:4
n.ajaxTransport.k.cors.a.crossDomain.send jquery-2.1.3.min.js:4
n.extend.ajax (index):18
(anonymous function) jquery-2.1.3.min.js:3
n.event.dispatch jquery-2.1.3.min.js:3
n.event.add.r.handle
My simple Node/Express application is as follows:
var express = require('express');
var app = express();
var http = require("http");
var data = "";
var json;
console.log( "__dirname", __dirname );
app.use( express.static( __dirname + '/') );
var options = {
host:"openexchangerates.org",
path:"/api/latest.json?app_id=<get free ID from openexchangerates.org>"
};
app.get("/", function( req, res ) {
res.sendFile('index.html', { root: __dirname });
})
app.get("/getfx", function(req, res) {
console.log("Route: getFx");
getFx(res);
})
function getFx(res) {
console.log("http getFx");
http.get(options, function (response) {
response.on("data", function (chunk) {
//console.log("data:\n"+chunk);
data += chunk;
});
response.on("end", function () {
json = JSON.parse(data);
console.log("http response end:");
res.end( data );
});
response.on("error", function (e) {
console.log("error:\n" + e.message);
});
})
}
app.listen(3000);
My html index page is:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Get FX</title>
<script src="http://code.jquery.com/jquery-2.1.3.min.js"></script>
<script>
$(document).ready(function() {
console.log( "document ready");
$("#btnFx").click(function() {
console.log('clicked', this );
$.ajax({
url : "http://127.0.0.1:3000/getFx",
dataType : "json",
success : function(json) {
console.log("json returned:\n", json);
}
});
} );
})
</script>
</head>
<body>
<button id="btnFx" style="width:200px">Get foreign exchange rates</button>
</body>
For openexchangerates.org to serve the data, a free app id is required. Anyone able to help resolve this may have to go through their very short sign up:
That link is here:
https://openexchangerates.org/signup/free
However it's possible that my mistake is glowingly obvious to those with better Node/Express/jQuery knowledge.
Many thanks in advance
The way you defined your data and json vars is causing subsequent requests to fail. Since you defined them up front, all requests will re-use them, meaning by the time you JSON.parse data for the second request, data will contain two valid json strings, thus making one invalid json string. To fix this, define data and json farther down in the callback.
var express = require('express');
var app = express();
var http = require("http");
//var data = "";
//var json;
console.log( "__dirname", __dirname );
app.use( express.static( __dirname + '/') );
var options = {
host:"openexchangerates.org",
path:"/api/latest.json?app_id=<get free ID from openexchangerates.org>"
};
app.get("/", function( req, res ) {
res.sendFile('index.html', { root: __dirname });
})
app.get("/getfx", function(req, res) {
console.log("Route: getFx");
getFx(res);
})
function getFx(res) {
console.log("http getFx");
http.get(options, function (response) {
var data = "";
var json;
response.on("data", function (chunk) {
//console.log("data:\n"+chunk);
data += chunk;
});
response.on("end", function () {
console.log("http response end:");
json = JSON.parse(data);
res.json(json);
});
response.on("error", function (e) {
console.log("error:\n" + e.message);
});
})
}
app.listen(3000);
Issue comes from Cross origin requests protection which happens on localhost with chrome. Try to use other browser or just Allow origin to all hosts (*) or your host (http://localhost:3000):
app.use( express.static( __dirname + '/') );
app.use(function(req,res,next){
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
// intercept OPTIONS method
if ('OPTIONS' == req.method) {
res.send(200);
}
else {
next();
}
});
I am working on an app which, among other things, pushes data to the client when an updation occurs on the database. The trouble is that the websocket on node.js listens to the databse on a different port then the node. The guy before me wrote a piece of code and then dumped it on me. The node looks somewhat like this:
var handler=http.createServer(function(req, res){
session(req, res, function(req, res, body) {
if (!req.session || !req.session.data || !req.session.data.uid || req.session.data.uid == '' || !req.session.data.role || req.session.data.role =='') {
var uri = url.parse(req.url).pathname;
if(req.method == 'GET' && uri =="/attendance-node/getMonthFromReport") {
var uri = url.parse(req.url).pathname;
var url_parts = url.parse(req.url,true);
processgetMonthFromReport(req, res, uri, url_parts.query);
return;
}
res.writeHead(401, {"Content-Type": "text/plain"});
res.write("401 Unauthorized");
res.end();
return;
}
if(req.method == 'POST') {
var uri = url.parse(req.url).pathname;
var qs = require('querystring');
var POSTVAR = qs.parse(body, '&', '=', {"maxKeys" : 0});
//var POSTVAR=JSON.parse(body);
handleRequest(req, res, uri, POSTVAR);
}
if (req.method=='GET') {
var uri = url.parse(req.url).pathname;
var url_parts = url.parse(req.url,true);
handleRequest(req, res, uri, url_parts.query);
}
});
}).listen(3014,"127.0.0.1");
var io = require('socket.io').listen(8077,"127.0.0.1");
sys.puts("websocket Server running on port 8077");
io.configure(function () {
io.set('transports', ['websocket', 'flashsocket', 'xhr-polling','jsonp-polling']);
io.set('log level', 0);
});
io.sockets.on('connection', function (socket) {
io.sockets.emit('init',"i am working via websocket");
});
As you can see the node is listening on 3014 and the socket on 8077. Now how am I suppossed to provide an handler for the message received on the socket and forward it to the node's client?
Note: I am fairly new to web development. So basically I was thrown in the water and now I am learning to swim.
P.S. Also, what would the client side of the socket look like?
P.P.S. The database sending update notification to the socket is already taken care of. It comes as a POST request.
Thanx in advance!!
It sounds like you want to have socket.io also on the client side (browser?) as well.
I'd say the best solution would be to have socket.io run on the same port as your web server. However, if it this not possible and you must keep the web socket that the database uses separate from the web server you could run two instances of socket.io.
One would be attached to the web server, and the other would be for the database.
var app = require('http').createServer(handler)
, IO = require('socket.io')
, web_io = IO.listen(app)
, data_io = IO.listen(8080)
, fs = require('fs')
app.listen(80);
function handler (req, res) {
fs.readFile(__dirname + '/index.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
web_io.sockets.on('connection', function (socket) {
socket.on('some_event', function (data) {
console.log(data);
});
});
data_io.sockets.on('connection', function (socket) {
socket.on('database_update', function (data) {
// Will be sent to everyone socket listening on port 80 (browser sockets mostlikely)
web_io.sockets.emit('database_update', data);
});
socket.on('disconnect', function () {
io.sockets.emit('user disconnected');
});
});