2

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.

Brian
  • 3,264
  • 4
  • 30
  • 43
  • Do you get access denied due to same-origin policy in the browser console? – Kevin B Apr 17 '13 at 21:42
  • @Kevin B The browser console isn't showing any sort of message at all, just the warn message about my character encoding of the HTML document wasn't declared. . . which I think I'm safe ignoring – Brian Apr 18 '13 at 12:21

2 Answers2

2

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.

Benjamin
  • 739
  • 4
  • 6
  • Thanks so much for pointing me in the right direction. My sin was great on this one, I was just running the html in my browser directly off my file system as you supposed. Furthermore, I had just created my node application from scratch, not using express tools, so. . . I went back and created my node app using the command 'express -s -e expressTest' which created the public folder for me you were referring to. Once I put my html in there and put my post handler in the app.js it created, everything worked like magic. Thanks so much for the help. – Brian Apr 18 '13 at 14:39
  • A note to anyone else who is having similar issues, I would recommend checking out faye and seeing if it might meet node and webpage communication needs. I found it today and I have had very good success with it so far. Publish/subscribe is a familiar paradigm to me and I'm keeping my fingers crossed that I don't find any gothcas because so far I really like it. – Brian Apr 18 '13 at 19:37
2

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

Marco Canora
  • 335
  • 2
  • 15