Ajax post response from express js keeps throwing error - javascript

I am having a real hard time standing up bidirectional data transfer from a html page to my node.js application and then back to the html page.
I'm pretty sure I'm all over the correct solution, but I'm just not getting it to work.
I'm using the following for my node.js application:
var express = require('/usr/lib/node_modules/express');
var app = express();
app.use(function(err, req, res, next){
console.error(err.stack);
res.send(500, 'Something broke!');
});
app.use(express.bodyParser());
app.post('/namegame', function(req, res)
{
console.log('Got request name: ' + req.body.name);
setTimeout(function()
{
var newName = "New Name-O";
res.send({name: newName});
}, 2000);
}
);
app.listen(8088, function() { console.log("Server is up and running"); });
The following is my html page:
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.js"></script>
<script type="text/javascript">
// wait for the DOM to be loaded
$(document).ready(function()
{
alert("Got here!");
function DisplayName(response)
{
alert(response.newName);
}
$("#NameGameIt").click(function(event)
{
alert("How about now?");
//event.PreventDefault();
var nameSubmitted = document.getElementById("name");
//var nameSubmitted = "help!!";
alert("Name: " + nameSubmitted.value);
$.ajax({
type: "POST",
url: "http://127.0.0.1:8088/namegame",
data: {name: nameSubmitted.value},
dataType: "json",
timeout: 2500,
success: function() { alert("???");},
error: function(error1, error2, error3)
{ alert("error"); },
complete: function(arg1, arg2, arg3)
{ alert("complete"); }
});
});
});
</script>
</head>
<body>
<h1>Test form for Ajax</h1>
</br>
Name: <input type="text" id="name" name="name"></br>
<input type="button" value="NameGameIt" id="NameGameIt">
</form>
</body>
</html>
So, when I run the node application, the server comes up just fine. When I fire up the html page, I get the alert "Got here!" When I press the button "NameGameIt", I get the alert "How about now?" followed by the alert "Name: " + whatever name I entered. Once I click off that alert, the node application immediately sees the post and prints out the name to the console. Two seconds later when the node sends the response, the browser will go right into the error handler on the ajax post. The only useful data to come out in the error handler is that it is an "error" which isn't really useful.
So I know the message is getting to the node from the html page because it prints out the name that I sent and I know the html page is getting the message back from the node because it won't error out until the timeout on the node happens triggering the send. But, I have no idea why it keeps on sending me to the error handler instead of the success. I've stepped through all the way in the node code using node-inspector and it seems to be building the packet correctly with a 200 code for success and it calls .end inside .send after it's done making the packet so I don't think either of those things are biting me.
I'm about to go nuts! If anyone sees what I'm missing or has any new ideas on ways to gather more information, I would be very grateful for the help.

Your code is perfectly fine, but you're almost certainly running into a cross-domain AJAX request issue. You might be opening this HTML file on the local filesystem and making requests that way, which is what is causing this problem.
To fix it, add app.use(express.static('public')); like so:
var express = require('/usr/lib/node_modules/express');
var app = express();
app.use(function(err, req, res, next){
console.error(err.stack);
res.send(500, 'Something broke!');
});
app.use(express.bodyParser());
app.use(express.static('public'));
app.post('/namegame', function(req, res)
{
console.log('Got request name: ' + req.body.name);
setTimeout(function()
{
var newName = "New Name-O";
res.send({name: newName});
}, 2000);
}
);
app.listen(8088, function() { console.log("Server is up and running"); });
and then place your html file in the 'public' folder. Once you launch your server, you can visit http://127.0.0.1:8088/file.html and your code will run fine.

In my case adding this to the app.js works.
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
https://enable-cors.org/server_expressjs.html

Related

Nodejs wait for socket and then respond to http request

I have a NodeJS code where, basically this is what happens:
HTTP request (app.get) -> Send a request to a low level socket(using net.Socket()) -> Get response from socket -> res.send(response from socket)
This doesn't work because the net.Socket() uses async functions and events (client.on("data", callback)).
I tried something like this:
app.get("/", function(req, res){
client.connect("localhost", 420, function(){
client.write("example data");
});
client.on("data", function(data){
client.destroy();
res.send(data);
});
});
But it doesn't work because it says I am re-sending the headers (the res object won't change since the function is an event, not a sync function).
Any ideas? Or a library for sync socket requests? I have tried the following:
Synket
sync-socket
netlinkwrapper
And they don't work.
Edit: I am trying something like this:
async function sendData(client, res){
client.on('data', function(data){
console.log("Got data!");
res.send(""+data);
res.end();
console.log("Sent data!");
client.destroy();
console.log("Killed connection");
return;
});
}
app.get("/", function(req, res){
var body = req.query;
client.connect(420, "localhost", function(){
client.write("some random data");
console.log("Connected & Data sent!");
sendData(client, res);
});
});
It works the first time I try to access the page, but the second time the app crashes and I get this error:
_http_outgoing.js:489
throw new Error('Can\'t set headers after they are sent.');
^
Error: Can't set headers after they are sent.
client triggles data event multiple times.
`app.get("/", function(req, res){
client.connect("localhost", 420, function(){
client.write("example data");
});
client.pipe(res);
});
});
`
It turns out that, each time a request comes to that endpoint, a new subscription has been registered by calling the client.on('eventName', cb). So, calls starting from the second one will trigger multiples of those registrations and will cause that header error.
So, a workaround for that:
socket.on('event', (packet) => {
socket.removeAllListeners('event')
res.json({ packet });
});
That would do the trick but I'm not sure if it's a bad practice to continuously add/remove the same event.
Edit
Found a better way. once will ensure that registered event only will run once, just as we want:
socket.once('event', (packet) => {
res.json({ packet });
});

Cannot GET / DELETE Express.js

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"
});

Add an error page to this express app?

I'm building an express app, a basic twitter interface.
I want to add an error page to the application, so that if anything goes wrong with the routes the user will see a friendly message rendered, instead of the default error code.
Here is a snippet of my code:
//Tell app to render template
app.get('/', function(req, res){
if(!error){
res.render('index', {
myName: myName,
profileImage: profileImage,
screenName: screenName,
followerCount: followerCount,
dateTweeted: dateTweeted,
tweetContent: tweetContent,
noOfRetweets: noOfRetweets,
noOfLikes: noOfLikes,
});
}
});
Why can't I just do this?
else{
res.send('sorry, bro, page not found!);
}
Or do I need to do something with passing the error to the 'next’ handler? I can't get my head around how that works.
Would really appreciate some help please!
Your question is not very specific but I assume you will get some errors during manipulation.
Then you can send type of error like this after getting error
//Tell app to render template
app.get('/', function(req, res) {
if ("not error") {
//You can do whatever you want
res.status(200).send({message:"Success message"})
}else{//If error you can choose your error code with relevant message
res.status(400).send({message:"Bad request error"});
//OR
res.status(404).send({message:"Not found error"});
//OR
res.status(401).send({message:"Unauthorization error"});
//OR
res.send(500).send({message:"Any server side erorr"});
}
});
You can build a custom middlewarethat does this for you...
function errorMiddleware(req, res, next) {
// implement some logic, do your check...
let thereAreErrors = /* ? */ false;
if(!thereAreErrors) {
return next();
}
return res.status(400).end();
}
function indexRouteCtrl(req, res) {
return res.render('index');
}
app.get('/'/, errorMiddleware, indexRouteCtrl);

Node.js app crash after one request sent

I send a POST request from front end and I declare my route like below
router.post('/login', function(req, res, next) {
});
My app crash and I got Error: Can't set headers after they are sent.
Here is my full code for route : http://pastebin.com/EnfXu8Vm
You cannot send twice the reply to the same request.
So the code here:
if(result){
res.json({msg:0})
}
res.json({msg:1})
You can probably want to do
if (result) {
res.json({msg:0});
} else {
res.json({msg:1});
}
or, to be more similar to your original code (so without else):
if (result) {
return res.json({msg:0});
}
res.json({msg:1});

Secure POST request from NodeJS to Node/Express hangs

I'm using the following to send POST data to a secure nodejs server:
File: main.js
var strdata = JSON.stringify({"data":"thisdata"});
var options = {
host: '192.168.1.63',
port: 3001,
path: '/saveconfig',
method: 'POST',
rejectUnauthorized: false,
requestCert: true,
agent: false,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(strdata)
}
};
var req = https.request(options, function(res) {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
});
console.log(req.write(strdata));
console.log(req.end());
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
req.on('finish', function() {
console.log("finished request");
});
In an otherwise functional expressjs server, these are the appropriate snippets:
File: app.js
app.post('/saveconfig', function() {
data.saveconfig; console.log("received request"); } );
app.get('/getconfig', data.getconfig);
File: data.js
exports.saveconfig = function(req, res) {
console.log("saveing config");
res.send(200);
res.end();
};
exports.getconfig = function(req, res) {
res.send("get OK");
}
With app.js running on the server (Ubuntu), I run main.js from the client (Windows 7). req.write and req.end execute and "finished request" logs to the console, but the request callback never fires.
On the server in app.js, the app.post event fires and logs "received request" to the console. But "saving config" never logs to the console. Only after I kill (^C) main.js, express then logs to the console "POST /saveconfig".
I know I'm missing something simple, but I've read dozens of coding examples and you can likely gather from my snippet, I've tried everything I can find or think of. I'd guess the request isn't finishing, but I don't know why. What is missing to get "exports.saveconfig" to fire?
additional information
The answer posted below fixed my problem. Because I'm new to stackoverflow, I can't post my own answer, but here's the rest of the story...
I appreciate your help. Being still new to JavaScript, I found I can learn a lot about an object by converting it to string. I was originally attempting to convert the req parameter to a string using a custom function. I just discovered it was apparently running into an endless loop after using JSON.stringify instead.
The code looked something like this:
exports.saveconfig = function (db) {
return function(req, res) {
console.log("saving config");
console.log(mymodule.serialize(req));
res.end("OK");
console.log(req.body);
};
};
I would have thought the above code should have logged the following to the console- even if the serialize method was in an endless loop:
POST /saveconfig
saving config
[nothing because of the endless loop]
Instead I got:
saving config
connections property is deprecated. Use getConnections() method
Being new to JavaScript, I assumed something was wrong with the request, the server, or some plumbing in-between. Of course, then the debugging code I added (along with my ignorance of JS) compounded the problem.
Changing
app.post('/saveconfig', function() {
data.saveconfig; console.log("received request"); } );
to
app.post('/saveconfig', datarts.saveconfig);
and removing the endless loop fixed the problem.
The problem is in you're app.js. You use data.saveConfig inside your callback without calling it. The right way would be
app.post('/saveconfig', function(req,res) {
data.saveconfig(req, res);
console.log("received request");
});
app.get('/getconfig', data.getconfig);
or (I assume the console.log is just for debugging purposes):
app.post('/saveconfig', data.saveconfig);
app.get('/getconfig', data.getconfig);
You could do your console.log() inside your data.saveconfig method if you want to go with the second example.

Categories