Im trying to set cookies for my website using node.js and express.js. Heres a simplified version of my code:
var express = require('express');
var cookieParser = require('cookie-parser');
var app = express();
app.use(cookieParser());
app.post('/testCookies', function(req, res) {
console.log(req.cookies); //empty object
res.cookie('username', 'test');
console.log(req.cookies); //still an empty object
res.end();
});
I tried POSTing twice in case the cookies somehow get set after the request (im not very familiar with cookies yet) but it doesn't change anything. The console does not show any errors.
You could use req.session() instead. That would let you do
req.session.username = "test";
See the docs here.
Related
I have a angularjs frontend and nodejs backend in my project. In angular code im setting a cookie using $cookies object and its working fine, cause i can find the cookie in "Show page info" on the top left corner of the browser. However when im sending get request to the backend i cant read that cookie there. I have those lines in my server.js: const cookieParser = require('cookie-parser'); and later app.use(cookieParser());.
Then im trying to do this:
//custom passport jwt extraction function
var cookieExtractor = function (req) {
console.log(req.cookies); //logs a '{}'
var token = null;
if(req && req.cookies)
token = req.cookies['jwt'];
return token;
};
And here the problem occurs, because the cookies object is empty (i'm getting '{}' in the console). What am i doing wrong here?
EDIT:
I'm attaching a ss of browser's cookies set by my app (sorry for non-english language): cookies
Try like this :
if you want set a cookie as string use put method.
and you want set a cookie as object use putObject method.
Angularjs
angular.module('cookiesExample', ['ngCookies'])
.controller('ExampleController', ['$cookies', function($cookies) {
var obj = {};
obj.name = "Hello world";
$cookies.putObject('myCookie', obj);
}]);
nodejs
var cookieParser = require('cookie-parser');
module.exports = function(app) {
app.use(cookieParser());
}
console.log('cookie', req.cookies.myCookie);
I have a node.js + Express application. It has a webhook that I have provided to a third party service. The service sends a POST request to my webhook with JSON body which looks something like this:
{"split_info" : "null", "customerName" : "Merchant Name",
"additionalCharges" : "null", "paymentMode":"CC",
"hash":"a31ff1b91fd9b8ae9c82f38b02348d21fsdfd86cc828ac9a0acf82050996372cc656de3db0fe3bf9af52b73a182a77787241f3e19ec893391607301b03e70db8",
"status" : "Release Payment", "paymentId" : "551731" ,
"productInfo":"productInfo", "customerEmail":"test#gmail.com",
"customerPhone":"9876543212", "merchantTransactionId":"jnn",
"amount":"100.0", "udf2":"null", "notificationId" :"4", "udf1":"null",
"udf5":"null", "udf4":"null", "udf3":"null","error_Message":"No
Error"}
I am using body-parser module to read POST data. However when I do req.body it gives [object Object], if I do JSON.stringify(req.body), it gives {} i.e. empty. If I try to access the keys in the response like req.body.paymentMode then it gives undefined.
Here is my router code for the webhook: mywebhook.js
var express = require('express');
var router = express.Router();
router.post('/success', function(req, res){
//this is where I need to strip the JSON request
//req.body or JSON.stringify(req.body) or anything that works
//if everything is okay then I send
res.sendStatus(200);
});
module.exports = router;
My app.js looks like this:
var express = require('express');
var exphbs = require('express-handlebars');
var router = express.Router();
var bodyParser = require('body-parser');
var mywebhook = require('./routes/mywebhook');
var app = express();
.
.
.
app.use(bodyParser.urlencoded({'extended':'true'})); // parse application/x-www-form-urlencoded
app.use(bodyParser.json()); // parse application/json
app.use(bodyParser.json({ type: 'application/vnd.api+json' })); // parse application/vnd.api+json as json
app.use('/callwebhook', mywebhook);
.
.
.
so on
Pretty sure I am missing something or doing something wrong, but I am not able to figure it out.
Thanks.
I finally found what was going on.
The way the body-parser works is that it will only try to parse a request in which they understand the Content-Type. This is mainly so you can stack them (app.use multiple parser types without conflict) and also because you typically don't want to parse a request that's going to fail (Content-Type: text/html is unlikely to ever get through a JSON.parse, for example).
I ended up getting sent */*; charset=UTF-8 which is not even a valid Content-Type header value period. The body-parser module refused to accept it, since that is gibberish. This module does allow you to setup a function that lets you put any custom logic you want to perform the filtering.
I had to put the body parser in my router code just for this webhook case.
var bodyParser = require('body-parser');
var customParser = bodyParser.json({type: function(req) {
return req.headers['content-type'] === '*/*; charset=UTF-8';
}});
router.post('/success', customParser, function(req, res){
console.log(JSON.stringify(req.body));
});
#svens thank you for your help.
I have a node express app , using express-stormpath for authentication/authorization
I have a GET route which is called with certain jquery parameters.
If the user is logged in everything is working as expected.
If not the user login screen is shown.
After stormpath authentication and authorization is done my query params are lost.
Is there any way to retain those?
app.get('/myRoute', stormpath.groupsRequired(['admin']), function(req, res){
console.log('req.query ',req.query);
//do somehting with the query data
res.sendStatus(200);
});
after authentication req.query is {}.
Any ideas?
Thank you for the question, I work at Stormpath and I'm more than happy to help. Our express-stormpath library is open source, and we're always happy to fix bugs and review pull requests.
Can you tell me which version of our library you are using? At the moment I'm not able to reproduce the problem you are seeing. Here is a quick example that I put together with the latest version, 3.0.1:
'use strict';
var express = require('express');
var stormpath = require('express-stormpath');
var app = express();
var port = process.env.PORT || 3000;
app.use(stormpath.init(app));
app.get('/admins', stormpath.groupsRequired(['admins']), function(req, res){
res.json(req.query);
});
app.on('stormpath.ready',function () {
console.log('Stormpath Ready');
});
app.listen(port, function () {
console.log('Server listening on http://localhost:' + port);
});
With this example, I do the following:
1.) Assert that I'm not logged in, by deleting all my cookies for localhost.
2.) Type /admin?foo=bar into the URL bar.
3.) I am redirected to the login page.
4.) I login with valid credentials.
5.) I am redirected to /admins?foo=bar, as expected, and I see the req.query object in the body of the page that is rendered. This is only true if the user is in the admins group, if they are not I will see the "Unauthorized" error message page.
Can you compare my steps and my example to your application, and let us know if there are any differences? Thanks!
I don't think that stormpath is removing query from request.
But we can check it by adding middlewhare before stormpath initialization:
var express = require('express');
var stormpath = require('express-stormpath');
var app = express();
// binding middleware to assign req.query to req.q param
app.use(function(req, res, next) {
req.QUERY = req.query;
next();
});
function restoreQuery(req, res, next) {
req.query = req.QUERY;
next();
}
app.use(stormpath.init(app, {
// Optional configuration options.
}));
app.get('/myRoute',
stormpath.groupsRequired(['admin']),
restoreQuery,
function(req, res){
console.log('req.query ',req.query);
//do somehting with the query data
res.sendStatus(200);
});
I'm building a website using Node.js, Express, and Redis for session management. For whatever reason, if I have a session variable (isLoggedIn in this example), and I refresh the page, the variable doesn't get saved, however, if I call req.session.save() after setting the variable, it does get saved to Redis (redis-cli monitor shows this - not calling save() shows that the variable isn't there, whereas calling save() shows it).
I'm using this to set up and start the server:
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var swig = require('swig');
var session = require('express-session')
var RedisStore = require('connect-redis')(session);
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
// Configure the favicon first. This avoids other middleware from processing the request if we know the request is for the favicon.
app.use(favicon(__dirname + '/public/images/favicon.ico'));
// All other requests will require everything else.
// Set up the view engine.
app.set('view engine', 'html');
app.set('views', path.join(__dirname, '/views'));
app.engine('html', swig.renderFile);
// Set up our logger.
app.use(logger('dev'));
// Set up JSON parsing.
app.use(bodyParser.json());
// Set up encoded URL parsing.
app.use(bodyParser.urlencoded());
// Set up the cookie parser.
app.use(cookieParser('thedogsleepsatnight'));
// Set up our session store. This will use Redis as our session management.
app.use(session({
resave: true,
saveUninitialized: true,
secret: "thedogsleepsatnight",
store: new RedisStore()
}));
app.use(require('stylus').middleware(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
And then, in that route, I have:
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
console.log(req.session.isLoggedIn);
if (req.session.isLoggedIn) {
console.log("Logged in!");
} else {
console.log("Not logged in");
}
res.render('index');
});
router.post('/login', function(req, res) {
console.log("Going to set isLoggedIn. Currently: " + req.session.isLoggedIn);
req.session.isLoggedIn = true;
console.log("Set isLoggedIn. Currently: " + req.session.isLoggedIn);
});
module.exports = router;
From that, I should be able to navigate to /login, have the session set isLoggedIn to true, and that should save automatically to Redis. After that, heading to / should tell me that I'm logged in. Loading /login does set the variable, the second log shows that, but loading / says that I'm not logged in. redis-cli monitor shows
1414076171.241836 "setex" "sess:FIDJ9qDbX_0u9pzlC6VZEW76zZcyiPME" "86400" "{\"cookie\":{\"originalMaxAge\":null,\"expires\":null,\"httpOnly\":true,\"path\":\"/\"}}"
upon saving, which doesn't include the isLoggedIn variable, but adding in req.session.save() shows:
1414076475.601644 "setex" "sess:FIDJ9qDbX_0u9pzlC6VZEW76zZcyiPME" "86400" "{\"cookie\":{\"originalMaxAge\":null,\"expires\":null,\"httpOnly\":true,\"path\":\"/\"},\"isLoggedIn\":true}"
Any idea on why I have to call req.session.save() when all of the examples I've seen don't use it?
Okay, so, I've figured it out. I'll put the answer here for anyone else that happens to get caught on this.
For GET requests, the server assumes that you're going to be sending data back, and will automatically save session data once the route is fully processed.
For POST requests (what I'm using), however, the same assumption isn't made. Session states are only saved in one of two conditions - either when data is being sent out (through res.send, res.redirect, etc.), or if you manually call req.session.save(). I was already calling /login from an AJAX request, I just wasn't returning anything if certain conditions were met. Having the server respond to the client with some data after setting the session variable fixed this.
If the brilliant answer from #thatWiseGuy is not solving the problem ... here is a hint.
I called a axios POST request from document loading:
document.addEventListener('DOMContentLoaded', function () {
axios.post('/do-magic', {
data: data
}, {withCredentials: true, credentials: 'include'}).then(res => {
// even more magic
}).catch(err => console.error(err));
}, false);
On server side, in the "do-magic" route, whenever I set a session and hit save, was not saved with the code below.
req.session.isMagic = true;
req.session.save();
I am not sure what is the reason behind, but when I invoked this call delayed, it was working properly and saving my session.
document.addEventListener('DOMContentLoaded', function () {
window.setTimeout(() => {
axios.post('/do-magic', {data: data}, {withCredentials: true, credentials: 'include'}).then(res => {
// even more magic
}).catch(err => console.error(err));
}, false);
}, 1000);
There are similar SO questions, but I could not find a precise answer to this issue.
I need to push back some text from the client side to the server side from time to time. The user side does not expect an answer from the server side. I though I would use POST as following:
var request = new XMLHttpRequest();
request.open('POST', MY_URL, true);
request.setRequestHeader('Content-Type', 'text/html;charset=utf-8');
request.send(myMsg);
From Chrome, I can see that the header and payload are correct. The status is 200 OK.
On the server side, I try to retrieve the body content as following:
function myFunction(req, res) {
console.log("Reached myFunction, reqBody is: '" + req.body + "'");
res.end();
}
But I get:
Reached myFunction, reqBody is: 'undefined'
What am I doing wrong? Should I use 'application/json; charset=utf-8' with a JSON instead?
Update
I have been doing some more research and the req object on the server side does not have a body property. However, the headers is fine.
I initiate my application with the following:
var express = require('express');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
...
self.app = express();
...
self.app.use(bodyParser());
self.app.use(cookieParser());
Any ideas?
When using the body-parser middleware, it's important that the content type matches. In this case, you've specified text/html, so you should use the bodyParser.text() middleware. In addition, you need to specify text/html as the type. So a full example would look like:
var express = require("express");
var bodyParser = require("body-parser");
var app = express();
app.use(bodyParser.text({
type: "text/html"
}));
app.post("/test", function(req, res) {
console.log(req.body);
res.end();
});
app.listen(3000);
You could also use a wildcard, such as type: "text/*" for the options to bodyParser.text().
When I ran this using your example, I see "hi" output to the console when I hit /test.
try :
request.setRequestHeader('Content-Type', "application/x-www-form-urlencoded");
this might help.