Node JS HTTP GET request body - javascript

I am using the express module in node.js and I am trying to read the body of an HTTP GET request and send an answer back to the user based on the content of the body. I am new to node.js and this is not working for me.
I know I should be using HTTP POST for this (and it works when I am using post), but the server I am trying to mimic in node.js uses GET, so I have to stick to it. Is there a way to do this in node.js? Thanks!
Here is a sample code I did. When I use app.post, I see the logs for the body, but when I use app.get, I see no logs at all!
app.get('/someURL/', function(req, res){
var postData = '';
req.on('data', function(chunk) {
console.log("chunk request:");
console.log(chunk);
postData += chunk;
});
req.on('end', function() {
console.log("body request:");
console.log(postData);
});
//Manipulate response based on postData information
var bodyResponse = "some data based on request body"
res.setHeader('Content-Type', 'application/json;charset=utf-8');
res.setHeader('Content-Length', bodyResponse.length);
res.send(bodyResponse);
};

The version of Node's HTML parser you are using does not support bodies in GET requests. This feature is available on the latest unstable v0.11 branch.
https://github.com/joyent/node/issues/7575
https://github.com/joyent/node/issues/5767

Related

Getting JSON-objects with Node.js WITHOUT stream

I am trying to make a JSON-objects exchange between client (web-browser) and server (Node.js) with vanilla javascript. I use a httpRequest in client and POST method. On server, I want to get a JSON-data from that POST-request, but I feel like that streams and chunks are too complicated. Is there a way to get data like a simple object? Does it exist at all?
Client-side request (looks OK):
button.onclick = function serverCommunication() {
var serverInteraction = new XMLHttpRequest('POST', '/chooochooo', true);
serverInteraction.open("POST", '/logInAttempt', true);
serverInteraction.setRequestHeader('Content-Type', 'application/json');
serverInteraction.send(JSON.stringify(myObject));// JSON-data has been sent, hoooraaaa!
};
You can try this
if(req.method === 'POST')
let body = '';
req.on('data', chunk => {
body += chunk.toString();
});
console.log(body);
But this has its limitations and i would suggest using express for handling requests.

Neither Node.js PUT or POST routes are presenting the data that is being received

I tried this with a number of different modules and methods.
Even by proving the other modules do work as expected in Node by building a separate test project and testing each module individually.
Posting FROM Node's hosted router to a remote API (not TO Node's hosted API)
This problem is not one of SENDING data to an API. It must IMO a problem in the receiving API's not giving up the data it IS receiving for some reason.
I've proven the PUT or POST calls are sending the data by sending the call to http://httpbin/org. That site shows me I'm sending what I expect to be sending.
Here is how I'm sending. I can even see in the receiving API that that API is certainly getting called successfully.
-- sending -- ((Again. This shows my node.http attempt. But I get the same problem using requestjs, requestifyjs, needlejs))
router.get('/', function (req, res, next) {
var hst = req.headers.host.split(':');
var lookbackURL = 'https://' + req.headers.host + req.baseUrl;
lookbackURL = 'http"httpbin.org/put';
var dat = {
what: 'ever'
, try: 'again'
};
var bdy = JSON.stringify(dat);
var options = {
host: hst[0], port: hst[1], path: req.baseUrl, method: 'PUT'
, headers: { 'Content-Type': 'application/json' }
};
var r = nodeHttp.request(options); r.write(bdy); r.end();
res.sendStatus(200);
});
-- receiving --
router.put('/', function (req, res, next) {
console.log('r', req);
});
No matter what module or method I use, in all cases, the receiving req object doesn't contain the what or try data.
BUT in my test project the data is there as I expect it to be, in all cases.
Doing the same console.log(req); in the test project, reqestjs, requestjs, needlejs, node.http all show a proper body object.
But in this problem there isn't a body object in req.
And sending this put/post to http://httpbin.org I can see the body object is being sent.
Any ideas?
Issue found. And it was something no one on here could have gotten for the code I posted.
For reasons I will not go into I have to take body-parser out this application. This also means app.use() won't have a parser given to it.
And that means I have to deal with getting the data on my own. So I've added a req.on('data') listener to read the chunk from the call to the API.
router.put('/', function (req, res, next) {
var data = '';
req.on('data', function (chunk) {
data += chunk;
.....
});
.....
I also decided to do this as a PUT using Requestify.
This just goes to show how easy it is to become complacent and forget how things really work; the assumption of body-parser (or other things) always being there for instance. Or what it is really doing for you.
NEXT I have to figure out how to get a value out of the `req.on('data) back to the method PUTting to the API. Any tips? Appreciated.

How to get entire request in node.js

I would like to get the entire request (header and body just as they appear when they arrive at the application) in Node.js. I'm able to get it by reading directly from the socket on connection (example below), but I haven't found a way to associate it with a particular request object as it's processed by the server.
...
var server = http.createServer(app).listen();
server.on('connection', function(socket) {
socket.on('data', function(data) {
console.log(data.toString());
});
});
...
app.get("/", function(req, res) {
//get the data that would be output from the above snippet in this context
//do something with it
});
This is just one example to illustrate what I'm looking for, I'm open to any method to achieve this other than attempting to reconstruct the request from information provided in the request object.

sock.js not allowing POST method for node server

Trying to bring up a node server that uses sock.js for websocket communication.
Can bring up the server fine and have established the websocket communication. However, we also need to POST to this instance with HTTP so that we can then send a message through the websocket. The message is dependent on the POST payload...
However, sock.js does not seem to be accepting the handler that we're creating, and is only allowing a GET method. This is causing a 405 HTTP code for any POSTs done to the server.
Please see following code. If I remove the sock.js implementation, I'm then able to process GET and POST requests with the server.
var app = require('http');
var sockjs = require('sockjs');
var sk = sockjs.createServer({ sockjs_url: '//cdn.jsdelivr.net/sockjs/1.0.1/sockjs.min.js' });
sk.on('connection', function (conn) {
console.log('connection' + conn);
conn.on('close', function () {
console.log('close ' + conn);
});
conn.on('data', function (message) {
console.log('message ' + conn,
message);
conn.write(message);
});
});
var server = app.createServer( function(req, res) {
if (req.method == 'POST') {
console.log("POST");
var body = '';
req.on('data', function (data) {
body += data;
console.log("Partial body: " + body);
});
req.on('end', function () {
console.log("Body: " + body);
});
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('post received');
}
else
{
console.log("GET");
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('get received');
}
});
sk.installHandlers(server);
I've tried different ways to set up the handlers, including following the example here; but regardless it just doesn't seem like I'm falling into my handlers but instead sock.js is not allowing POSTs.
If this is expected behavior from sock.js and is working the way it;s intended to, then recommendations for what to use would be appreciated. This is an attempt to move away from socket.io because that isn't working in all cases for us... but without being able to POST to the node server we probably won't be able to use sock.js either.
You're missing the prefix in your call to installHandlers. This results in sockjs handling all requests, rather than just those that are destined to it.
Just specify a prefix:
sk.installHandler(server,{prefix:"/whatever"});
It should of course match the prefix you use client-side.
Alternatively, if you don't want to use a prefix, use different ports.

Basic Ajax send/receive with node.js

So I'm trying to make a very basic node.js server that with take in a request for a string, randomly select one from an array and return the selected string. Unfortunately I'm running into a few problems.
Here's the front end:
function newGame()
{
guessCnt=0;
guess="";
server();
displayHash();
displayGuessStr();
displayGuessCnt();
}
function server()
{
xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET","server.js", true);
xmlhttp.send();
string=xmlhttp.responseText;
}
This should send the request to server.js:
var http = require('http');
var choices=["hello world", "goodbye world"];
console.log("server initialized");
http.createServer(function(request, response)
{
console.log("request recieved");
var string = choices[Math.floor(Math.random()*choices.length)];
console.log("string '" + string + "' chosen");
response.on(string);
console.log("string sent");
}).listen(8001);
So clearly there are several things going wrong here:
I get the feeling the way I am "connecting" these two files isn't correct both in the xmlhttp.open method and in using response.on to send the string back to the front end.
I'm a little confused with how I call this page on localhost. The front end is named index.html and the sever posts to 8001. What address should I be go to on localhost in order to access the initial html page after I have initialized server.js? Should I change it to .listen(index.html) or something like that?
are there other obvious problems with how I am implementing this (using .responsetext etc.)
(sorry for the long multi-question post but the various tutorials and the node.js source all assume that the user already has an understanding of these things.)
Your request should be to the server, NOT the server.js file which instantiates it. So, the request should look something like this: xmlhttp.open("GET","http://localhost:8001/", true); Also, you are trying to serve the front-end (index.html) AND serve AJAX requests at the same URI. To accomplish this, you are going to have to introduce logic to your server.js that will differentiate between your AJAX requests and a normal http access request. To do this, you'll want to either introduce GET/POST data (i.e. call http://localhost:8001/?getstring=true) or use a different path for your AJAX requests (i.e. call http://localhost:8001/getstring). On the server end then, you'll need to examine the request object to determine what to write on the response. For the latter option, you need to use the 'url' module to parse the request.
You are correctly calling listen() but incorrectly writing the response. First of all, if you wish to serve index.html when navigating to http://localhost:8001/, you need to write the contents of the file to the response using response.write() or response.end(). First, you need to include fs=require('fs') to get access to the filesystem. Then, you need to actually serve the file.
XMLHttpRequest needs a callback function specified if you use it asynchronously (third parameter = true, as you have done) AND want to do something with the response. The way you have it now, string will be undefined (or perhaps null), because that line will execute before the AJAX request is complete (i.e. the responseText is still empty). If you use it synchronously (third parameter = false), you can write inline code as you have done. This is not recommended as it locks the browser during the request. Asynchronous operation is usually used with the onreadystatechange function, which can handle the response once it is complete. You need to learn the basics of XMLHttpRequest. Start here.
Here is a simple implementation that incorporates all of the above:
server.js:
var http = require('http'),
fs = require('fs'),
url = require('url'),
choices = ["hello world", "goodbye world"];
http.createServer(function(request, response){
var path = url.parse(request.url).pathname;
if(path=="/getstring"){
console.log("request recieved");
var string = choices[Math.floor(Math.random()*choices.length)];
console.log("string '" + string + "' chosen");
response.writeHead(200, {"Content-Type": "text/plain"});
response.end(string);
console.log("string sent");
}else{
fs.readFile('./index.html', function(err, file) {
if(err) {
// write an error response or nothing here
return;
}
response.writeHead(200, { 'Content-Type': 'text/html' });
response.end(file, "utf-8");
});
}
}).listen(8001);
console.log("server initialized");
frontend (part of index.html):
function newGame()
{
guessCnt=0;
guess="";
server();
displayHash();
displayGuessStr();
displayGuessCnt();
}
function server()
{
xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET","http://localhost:8001/getstring", true);
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){
string=xmlhttp.responseText;
}
}
xmlhttp.send();
}
You will need to be comfortable with AJAX. Use the mozilla learning center to learn about XMLHttpRequest. After you can use the basic XHR object, you will most likely want to use a good AJAX library instead of manually writing cross-browser AJAX requests (for example, in IE you'll need to use an ActiveXObject instead of XHR). The AJAX in jQuery is excellent, but if you don't need everything else jQuery offers, find a good AJAX library here: http://microjs.com/. You will also need to get comfy with the node.js docs, found here. Search http://google.com for some good node.js server and static file server tutorials. http://nodetuts.com is a good place to start.
UPDATE: I have changed response.sendHeader() to the new response.writeHead() in the code above !!!
Express makes this kind of stuff really intuitive. The syntax looks like below :
var app = require('express').createServer();
app.get("/string", function(req, res) {
var strings = ["rad", "bla", "ska"]
var n = Math.floor(Math.random() * strings.length)
res.send(strings[n])
})
app.listen(8001)
https://expressjs.com
If you're using jQuery on the client side you can do something like this:
$.get("/string", function(string) {
alert(string)
})
I was facing following error with code (nodejs 0.10.13), provided by ampersand:
origin is not allowed by access-control-allow-origin
Issue was resolved changing
response.writeHead(200, {"Content-Type": "text/plain"});
to
response.writeHead(200, {
'Content-Type': 'text/html',
'Access-Control-Allow-Origin' : '*'});
Here is a fully functional example of what you are trying to accomplish. I created the example inside of hyperdev rather than jsFiddle so that you could see the server-side and client-side code.
View Code:
https://hyperdev.com/#!/project/destiny-authorization
View Working Application: https://destiny-authorization.hyperdev.space/
This code creates a handler for a get request that returns a random string:
app.get("/string", function(req, res) {
var strings = ["string1", "string2", "string3"]
var n = Math.floor(Math.random() * strings.length)
res.send(strings[n])
});
This jQuery code then makes the ajax request and receives the random string from the server.
$.get("/string", function(string) {
$('#txtString').val(string);
});
Note that this example is based on code from Jamund Ferguson's answer so if you find this useful be sure to upvote him as well. I just thought this example would help you to see how everything fits together.

Categories

Resources