node.js receiving POST data submitted through form using HTTP - javascript

I'm using a node.js server and need to post data over an http*s* protocol.
POST is listed as a http protocol, so I'm wondering if I'm on the wrong track.
Anyway, here is the top of my code that handles the POST. I've not included the on('end') function for berevity, but it is there.
exports.login = function(req, res){
if(req.method == 'POST'){
var datastring = '';
req.on('data', function(data){
datastring += data;
console.log("getting data");
if(datastring.length > 1e6){
req.connection.destroy();
}
});
Through console logs I can determine that the request is being made, and that the request is recognised as POST, but that req.on('data')'s function is never called.
I looked into a CONNECT protocol, but this isn't supported by browser forms - please advise how to send data through CONNECT if you don't think I can send POST data over HTTPS
Thanks for your help
EDIT: here is form that sends request:
<form name="loginForm" action="login" method="POST" onsubmit="return checkForm()" class="separate-sections">
and here is node.js code that grabs post
var app= express();
...
app.post('/login', route_login.login);
To make a long story short, does POST work over HTTPS? It doesn't seem to be working here.

Found out someone on my team had added the express bodyparser, so naturally posts no longer work in the way I had before. The change just happened to coincide with when we switched to https which made it look as if this was the issue, when it was not.

Related

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.

trying to understand how html GET and res.redirect works in express

I am new to nodejs express et al..I am trying to understand why a res.redirect needs a GET to work..whereas a res.render don't. Here is the scenario. I have a login that uses passport for authentication with a database..good so far. After authentication depending on the type of user....the user is sent to a particular html page. If I just res.render the page it works fine....but if I res.redirect to the page I get a "Cannot GET..." error indicating I did't have get('/page') block. Here is a sample code:
// get part request page
router.get('/partpage', function(req,res) {
res.render('partpage', {name: user.get("Name"),email:user.get("Email")});
});
// get dealer page
router.get('/dealers', function(req,res) {
res.render('dealers', {name: user.get("Name"),email:user.get("Email")});
});
.
.
.
router.post('/login',
passport.authenticate( 'local',
{sucessRedirect:'/',
failureRedirect:'/users/login',
failureFlash:true}),
function(req,res)
{
.
.
.
// After passport authentication.....
if (user.get("Category")==="dealer")
{
res.redirect('/users/dealers?name='+username+'&email='+useremail);
}
else
{
res.redirect('/users/partpage?name='+username+'&email='+useremail);
}
If I remove any one of the GET I get and error('Cannot GET...'). I don't understand why this is the case. More importantly I am passing parameters to the page...which one takes precedence? ...obviously something is wrong here! can anyone explain this for me? what is the correct way to to this?
The home page route is setup as follows:
in app.js
.
.
.
var routes = require('./routes/index');
.
.
.
app.set('views', path.join(__dirname,'views'));
app.set('view options', { layout:'layout.ejs' });
app.set('view engine','ejs');
.
.
.
app.use('/', routes);
res.redirect is like something after web server accepts requrest, it behind the table force the browser to change the url, which means 302 http code.
While res.render is web server just simply uses jade or ejs to render page, which means 200 http code.
In your case after user visiting /login?Category=dealer, his/her browser will be 302 to /users/dealers?name=a&email=b.
Then your server needs the router router.get('/dealers', fn) to show the page. Most importantly, user's browser url will be /users/dealers?name=a&email=b.
While if you directly use res.render in your authenticate callback, user's browser will show the rendered page, but the url is still /login?Category=dealer.
It's recommended to use redirect in your case. Otherwise if user presses 'F5' to refresh page, he/she actually is refresh url /login?Category=dealer, which will trigger your authenticate router and logic unnecessarily.
UPDATE:
The difference with render and redirect, (sorry I reply late, I wasn't able to visit stackoverflow these days due to the great wall)
1
user's browser issues http request to your server===>
your server get request, and uses res.render to output response, means your server returns 'http status 200' in response header, and 'html' in response body==>
user's browser gets '200 and html' response, then parses 'html' to view.
2
user's browser issues http request to your server===>
your server get request, and uses res.redirect, means your server returns 'http status 302 and new url' in response header, but no response returned.==>
user's browser gets '302 and new url' response, then relocate to the new url, which means user's browser iusses http request again, with this new url==>
your server get request, and uses res.render to output response, means your server returns 'http status 200' in response header, and 'html' in response body==>
user's browser gets '200 and html' response, then parses 'html' to view.

AJAX post to Google Spreadsheet from Node.js/ Express fails

I've researched a few questions similar to this but none have helped solve my problem...
Posting to a Google Spreadsheet app from a simple Node.js/ Express script on Heroku (not accessed through the browser) doesn't show up any errors but still fails. Can anyone understand why?
I've created a very small app with Node.js and Express. It basically listens for messages from a Slack channel, evaluates and strips parts of the message it needs and then posts them to a Google Spreadsheet to be stored.
I'm using the node modules express for receiving data posted from Slack and ajax-request to handle the AJAX post to Google Spreadsheets. It looks a little something like this:
var express = require('express');
var bodyParser = require('body-parser');
var ajaxRequest = require('ajax-request');
var app = express();
// Other app.stuff
app.post('/test', function (req, res, next) {
var userName = req.body.user_name;
var message = req.body.text || '';
// DOES SOME OTHER STUFF...
postToSpreadsheet(userName, message);
});
function postToSpreadsheet(user, id) {
ajaxRequest({ // Post request
url: 'https://script.google.com/macros/s/abcdefg123456/exec', // Google Spreadsheet app url
method: 'POST',
data: {Id : id, User : user}
}, function(err, res, body) { // Request callback
console.log("ERROR: " + err + " / BODY: " + body);
});
}
I receive no errors from the request callback, however the body of the post contains the HTML from Google's file not found page, which makes me think it's posting to an incorrect url.
I know it's not:
A Google script problem. The Google script works fine and the published app is public and accessible to anyone. When I just enter the url with encoded parameters into my browser e.g. https://script.google.com/macros/s/abcdefg123456/exec?Id=id&User=johnsmith it works and stores the parameters in my Google Spreadsheet.
An data to url params serialisation problem - I've tried just posting to the url above with pre-defined parameters and no data option.
A dependency problem - I've tried to get it working with a few different AJAX node modules.

Node JS HTTP Server request.on('data') event failure

I am working on a NodeACS app in which I have to send xml as request from Java HTTP client and to receive response after some manipulation. The Java HTTP Client is working fine so far but the issue is with Node JS file. The req.on('data'...) event is not firing in my case.
Following is the code of my JS file:
function index(req, res) {
console.log(req.headers); //Its getting printed on console
req.on('data', function (data) {
console.log("Inside 1"); //Not printed on console
....REST OF THE CODE....
});
req.on('end', function () {
res.writeHead(200);
res.end();
});
}
In the above code after getting request the index function is called and printing the output for console.log(req.headers); but as mentioned above the script is not running after that. Please help me out What am I missing in this.
For testing I have installed cURL on my system and sending POST request to server using cURL request using following command:
curl -X POST -d #output.xml http://localhost:7788/
Can you confirm you aren't consuming the body prior to this? If the body has been consumed already by another middleware like body-parser you would need to restream the body via something like connect-restreamer. If it were consumed, the data event would not be emitted.
If that checks out, check to see if the "end" event is being emitted. Could be a sign of the content-length header being set to the wrong value.

NodeJS HTTP request from AngularJS

I'm currently developing a web application using AngularJS on the fronted and NodeJS on the backend with express. I've had trouble requesting my backend API from the fronted however and hope you guys can help me.
Backend (NodeJS):
app.get('/test', function(req, res) {
res.json(200, {'test': 'it works!'})
})
Frontend (AngularJS):
myApp.controller('myController', function($scope, $http) {
delete $httpProvider.defaults.headers.common["X-Requested-With"]
$http.get('http://localhost:5000/test').success(function(data) {
alert('Success')
}).error(function(data, status) {
alert('Error! ' + status + ' : ' + data)
})
})
When I refresh the app I get an alert saying: Error! 0 :, however, when I request the backend with curl or by the browser, I get the test dict back. The frontend seems to be able to access the backend though because I see it in my backend log that it's done a request and got something back, but firebug says that the response is empty, what should I do?
Thanks so much, let me know if you need more info from me.
Mattias
Make sure that your frontend and backend servers have the same origin (protocol, host and port). If not, then you does not recieve response since you make cross-origin ajax request. In this case you should send special header from your backend to allow it:
Access-Control-Allow-Origin: *
You can add response header with the following code:
res.set('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Origin', '*');
Use res.status(status).json(obj) instead of res.json(status, obj)

Categories

Resources