Marcelo Vitoria
Marcelo Vitoria

Reputation: 601

How to send data from JQuery AJAX request to Node.js server

What i want to do:
Simply send some data (json for example), to a node.js http server, using jquery ajax requests.

For some reason, i can't manage to get the data on the server, cause it never fires the 'data' event of the request.

Client code:

$.ajax({
    url: server,
    dataType: "jsonp",
    data: '{"data": "TEST"}',
    jsonpCallback: 'callback',
    success: function (data) {
        var ret = jQuery.parseJSON(data);
        $('#lblResponse').html(ret.msg);
    },
    error: function (xhr, status, error) {
        console.log('Error: ' + error.message);
        $('#lblResponse').html('Error connecting to the server.');
    }
});

Server code:

var http = require('http');
http.createServer(function (req, res) {

    console.log('Request received');

    res.writeHead(200, { 'Content-Type': 'text/plain' });
    req.on('data', function (chunk) {
        console.log('GOT DATA!');
    });
    res.end('callback(\'{\"msg\": \"OK\"}\')');

}).listen(8080, '192.168.0.143');
console.log('Server running at http://192.168.0.143:8080/');

As i said, it never gets into the 'data' event of the request.

Comments:
1. It logs the 'Request received' message;
2. The response is fine, im able to handle it back on the client, with data;

Any help? Am i missing something?

Thank you all in advance.

EDIT:
Commented final version of the code, based on the answer:

Client code:

$.ajax({
type: 'POST' // added,
url: server,
data: '{"data": "TEST"}',
//dataType: 'jsonp' - removed
//jsonpCallback: 'callback' - removed
success: function (data) {
    var ret = jQuery.parseJSON(data);
    $('#lblResponse').html(ret.msg);
},
error: function (xhr, status, error) {
    console.log('Error: ' + error.message);
    $('#lblResponse').html('Error connecting to the server.');
}
});


Server code:

var http = require('http');
http.createServer(function (req, res) {

    console.log('Request received');

    res.writeHead(200, { 
        'Content-Type': 'text/plain',
        'Access-Control-Allow-Origin': '*' // implementation of CORS
    });
    req.on('data', function (chunk) {
        console.log('GOT DATA!');
    });

    res.end('{"msg": "OK"}'); // removed the 'callback' stuff

}).listen(8080, '192.168.0.143');
console.log('Server running at http://192.168.0.143:8080/');


Since i want to allow Cross-Domain requests, i added an implementation of CORS.

Thanks!

Upvotes: 20

Views: 63121

Answers (1)

Brion Finlay
Brion Finlay

Reputation: 554

To get the 'data' event to fire on the node.js server side, you have to POST the data. That is, the 'data' event only responds to POSTed data. Specifying 'jsonp' as the data format forces a GET request, since jsonp is defined in the jquery documentation as:

"jsonp": Loads in a JSON block using JSONP. Adds an extra "?callback=?" to the end of your URL to specify the callback

Here is how you modify the client to get your data event to fire.

Client:

<html>
<head>
    <script language="javascript" type="text/javascript" src="jquery-1.8.3.min.js"></script>
</head>

<body>
    response here: <p id="lblResponse">fill me in</p>

<script type="text/javascript">
$(document).ready(function() {
    $.ajax({
        url: 'http://192.168.0.143:8080',
        // dataType: "jsonp",
        data: '{"data": "TEST"}',
        type: 'POST',
        jsonpCallback: 'callback', // this is not relevant to the POST anymore
        success: function (data) {
            var ret = jQuery.parseJSON(data);
            $('#lblResponse').html(ret.msg);
            console.log('Success: ')
        },
        error: function (xhr, status, error) {
            console.log('Error: ' + error.message);
            $('#lblResponse').html('Error connecting to the server.');
        },
    });
});
</script>

</body>
</html>

Some helpful lines to help you debug the server side:

Server:

var http = require('http');
var util = require('util')
http.createServer(function (req, res) {

    console.log('Request received: ');
    util.log(util.inspect(req)) // this line helps you inspect the request so you can see whether the data is in the url (GET) or the req body (POST)
    util.log('Request recieved: \nmethod: ' + req.method + '\nurl: ' + req.url) // this line logs just the method and url

    res.writeHead(200, { 'Content-Type': 'text/plain' });
    req.on('data', function (chunk) {
        console.log('GOT DATA!');
    });
    res.end('callback(\'{\"msg\": \"OK\"}\')');

}).listen(8080);
console.log('Server running on port 8080');

The purpose of the data event on the node side is to build up the body - it fires multiple times per a single http request, once for each chunk of data that it receives. This is the asynchronous nature of node.js - the server does other work in between receiving chunks of data.

Upvotes: 20

Related Questions