Avoid req.flash delete data on middleware - node.js

I'm using connect-flash with express to handle flash messages, but that messages are deleted when i read that properties, for example:
Defining flash message:
req.flash("myMessage", "Hey!");
Reading message:
console.log(req.flash("myMessage")); // Hey!
console.log(req.flash("myMessage")); // undefined
Data is erased on first read, and this is a problem, because i need to read the data of req.flash in a middleware to filter the http request and after in the controller (Which is in another file) i need to read the same req.flash data but i can't because in the read of the middleware was erased.
What can i do in this case?

The messages are stored on req.session.flash internally, see the source code.
This means you can get the message by indexing directly into req.session.flash["myMessage"] without it getting cleared.
This is technically an implementation detail of req.flash() you shouldn't rely on, but I think if you pin the version of connect-flash in your requirements it's safe enough.

Calling the req.flash again obviously the first call actually delete the flash data. So that's why when you call again the req.flash the data is now undefined or empty array.
1st console.log output: [ 'Hey!' ]
2nd console.log output: []
Does it make sense?

Store the message in the request object like:
req.myMessage = req.flash("myMessage");
And that will be available in all middlewares you want for that specific request.
Btw, make sure you are using connect-flash because you are redirecting the user to another route and that starts a new request and you want to save data between requests (and that's why you want to use a session for that). That being said, removing the message from the session is encouraged instead of just trying to access it.
If you are not redirecting the user, rethink if connect-flash is necessary.

Related

What happens if I do not use body parser or express.json()?

I am new to the whole backend stuff I understood that both bodyparser and express.json() will parse the incoming request(body from the client) into the request object.
But what happens if I do not parse the incoming request from the client ?
without middleware parsing your requests, your req.body will not be populated. You will then need to manually go research on the req variable and find out how to get the values you want.
Your bodyParser acts as an interpreter, transforming http request, in to an easily accessible format base on your needs.
You may read more on HTTP request here ( You can even write your own http server )
https://nodejs.org/api/http.html#http_class_http_incomingmessage
You will just lose the data, and request.body field will be empty.
Though the data is still sent to you, so it is transferred to the server, but you have not processed it so you won't have access to the data.
You can parse it yourself, by the way. The request is a Readable stream, so you can listen data and end events to collect and then parse the data.
You shall receive what you asked for in scenarios where you do not convert the data you get the raw data that looks somewhat like this username=scott&password=secret&website=stackabuse.com, Now this ain't that bad but you will manually have to filter out which is params, what is a query and inside of those 2 where is the data..
unless it is a project requirement all that heavy lifting is taken care of by express and you get a nicely formatted object looking like this
{
username: 'scott',
password: 'secret',
website: 'stackabuse.com'
}
For Situation where you DO need to use the raw data express gives you a convenient way of accessing that as well all you need to do is use this line of code
express.raw( [options] ) along with express.json( [options] )

Piping a readstream into a writestream does not work

I (as the client) am trying to post an image with restify, and the server just needs to save it.
req.pipe(fs.createWriteStream('test.jpg'));
is not working. An empty file is created but nothing more. It works when I copy req.body into a buffer and then fs.writeFile(...). I have also tried req.body.pipe, but this throws an error.
You're probably using a body parser middleware that is already reading all of the data from the request so there is nothing left to read. Try adjusting the placement of your route handler and/or body parsing middleware if you want to read directly from the request object.
However, that will only work if the request contains only the image data. Typically a request is formatted as multipart/form-data if it contains at least one file, so you cannot just pipe the request and expect image data only.
So something else in your middleware chain, probably restify.bodyParser(), is already streaming the request body into a buffer or string as req.body and you can't stream something twice. Find the middleware and disable it for this route if you want to handle the streaming straight to the filesystem yourself.

sails.js Use session param in model

This is an extension of this question.
In my models, every one requires a companyId to be set on creation and every one requires models to be filtered by the same session held companyid.
With sails.js, I have read and understand that session is not available in the model unless I inject it using the controller, however this would require me to code all my controller/actions with something very, very repetitive. Unfortunate.
I like sails.js and want to make the switch, but can anyone describe to me a better way? I'm hoping I have just missed something.
So, if I understand you correctly, you want to avoid lots of code like this in your controllers:
SomeModel.create({companyId: req.session.companyId, ...})
SomeModel.find({companyId: req.session.companyId, ...})
Fair enough. Maybe you're concerned that companyId will be renamed in the future, or need to be further processed. The simplest solution if you're using custom controller actions would be to make class methods for your models that accept the request as an argument:
SomeModel.doCreate(req, ...);
SomeModel.doFind(req, ...);
On the other hand, if you're on v0.10.x and you can use blueprints for some CRUD actions, you will benefit from the ability to override the blueprints with your own code, so that all of your creates and finds automatically use the companyId from the session.
If you're coming from a non-Node background, this might all induce some head-scratching. "Why can't you just make the session available everywhere?" you might ask. "LIKE THEY DO IN PHP!"
The reason is that PHP is stateless--every request that comes in gets essentially a fresh copy of the app, with nothing in memory being shared between requests. This means that any global variables will be valid for the life of a single request only. That wonderful $_SESSION hash is yours and yours alone, and once the request is processed, it disappears.
Contrast this with Node apps, which essentially run in a single process. Any global variables you set would be shared between every request that comes in, and since requests are handled asynchronously, there's no guarantee that one request will finish before another starts. So a scenario like this could easily occur:
Request A comes in.
Sails acquires the session for Request A and stores it in the global $_SESSION object.
Request A calls SomeModel.find(), which calls out to a database asynchronously
While the database does its magic, Request A surrenders its control of the Node thread
Request B comes in.
Sails acquires the session for Request B and stores it in the global $_SESSION object.
Request B surrenders its control of the thread to do some other asynchronous call.
Request A comes back with the result of its database call, and reads something from the $_SESSION object.
You can see the issue here--Request A now has the wrong session data. This is the reason why the session object lives inside the request object, and why it needs to be passed around to any code that wants to use it. Trying too hard to circumvent this will inevitably lead to trouble.
Best option I can think of is to take advantage of JS, and make some globally accessible functions.
But its gonna have a code smell :(
I prefer to make a policy that add the companyId inside the body.param like this:
// Needs to be Logged
module.exports = function(req, res, next) {
sails.log.verbose('[Policy.insertCompanyId() called] ' + __filename);
if (req.session) {
req.body.user = req.session.companyId;
//or something like AuthService.getCompanyId(req.session);
return next();
}
var err = 'Missing companyId';
//log ...
return res.redirect(307, '/');
};

Failed to write session data in express

Sometimes the data I'm storing in a session won't be saved.
The next request the data is just gone.
The way I'm storing the data in the session is very straight-forward:
// Store the complete user data in the session
req.session.user = user;
// Redirect to the correct url
res.redirect(redirectUrl);
As you can see, I do a redirect immediately afterwards.
I did have an entry that contained a lot of data.
When I removed that entry, everything started working again.
So now I wonder:
Does this happen because the object is "too big" for a session or
because there is some race condition with the saving of the session?
As far as I can tell, there is no asynchronous function that lets you save the session before doing a redirect...
You can rule out whether the issue is the first function completing by wrapping both of them in async.series: https://github.com/caolan/async#series

Is it ok to work directly on the data in req.body?

I'm working on an app in Node/Express/Jade.
I have a GET route which render a form. When the user submit this, a POST route is handling the request. I use bodyParser, which populate the req.body.
I then sanitize, validate and generate new data directly in the req.body:
// Shorthand variable
var doc = req.body;
// Sanitise and transform user input
doc.company = sanitize( doc.company ).trim();
doc.contact_person = sanitize( doc.contact_person ).trim();
...
// Validate user input
validator.check( doc.company, 'Some error message' ).notEmpty();
validator.check( doc.contact_person, 'Another error message' ).notEmpty();
...
// Generate new object data
doc.slug = sanitize( doc.company ).toSlug();
...
Question: is if there are any special reason for me not to edit the data directly in the req.body? Should I instead making a new "doc" object from the data in req.body, and in that new object sanitize, validate and add the new generated data.
It's fine to edit data in req.body. The only thing you should be aware of is that the next route or middleware will get a modified version of req.body.
So, you may create a single route/middleware to sanitize and transform your req.body and then use transformed results in multiple routes.
You can definitely modify it. For example, the express.json middleware parses raw body data into JSON for the rest of the middleware chain.
It's best to use a copy if your intention isn't to alter data for the rest of the chain, even if it won't interfere with correct operation. It prevents sometimes hard-to-debug errors that might crop up in later development.

Resources