NodeJS request reset session - node.js

I am doing a post request from my server to another server and for it i'm using the library https://github.com/request/request.
So, I use the next code:
router.post('/extern/*', function(req, res, next) {
var path = req.params['0'];
var input = req.body.text;
var encript = crypto.encrypt(input);
request.post(config.petitionServer + path).form({data: encript}).pipe(res)
});
The session has been initialized before calling this post, but when it executes, the session is reseted. So, in this case, I lose the csrf code from the session var.
The error is in the 'pipe' function, because if I call it I lose the session, not in other case, but I need to use it.
How can I use the pipe function without lose the actual session?

I believe express-session is saving it's sessions into cookies and what you are doing is piping the hole response from config.petitionServer + path to client so it overwrites cookies that the express-session has saved. Maybe it would be a better idea just to pipe the body of the respone?
router.post('/extern/*', function(req, res, next) {
var path = req.params['0'];
var input = req.body.text;
var encript = crypto.encrypt(input);
request.post({url: config.petitionServer + path, formData: {data: encript}, function(err, httpResponse, body))
res.send(body);
});

As mentioned in other answers, your express session is getting reset by the cookie that is sent from the other server.
There's a couple of ways you could solve this problem. If you don't need the cookie from your petition server, you could delete the header before you pipe the response:
router.post('/myServerUrl', function(req, res) {
request.post('/remoteServerUrl', { data })
.on('response', function(response) {
delete response.headers['set-cookie'];
})
.pipe(res);
});
If you don't want to modify any headers, you should be able to pipe the response inside of the response handler along with the content type.
router.post('/myServerUrl', function(req, res) {
request.post('/remoteServerUrl', { data })
.on('response', function(response) {
res.set('Content-Type', 'image/jpeg')
response.pipe(res);
});
});

I founded the solution and it was my bad.
Session is in req.session and the petition server was using also the express-session module. When request was received by petition server, this one replaced the session var by the one of the petition server.
The solution was to remove express-session module from petition server.
Anothe solution could be manage the session from the host server preventing to replace it. But I didnt do it

Related

Nodejs Express send res.render and res.json simultaneously

How can I send res.render and res.json simultaneously in NodeJS with Express. I wanted something like:
app.get(basePath, function (req, res, next) {
//More stuff
res.json({token: token});
res.render(path.join(publicPath, '/main'),
{mv: mv});
});
but it only gives me the token without rendering the page. Using this method:
app.get(basePath, function (req, res, next) {
//More stuff
res.render(path.join(publicPath, '/main'),
{mv: mv, token: token});
});
I don't have access to token param (I have to store it in client)
The idea is to avoid to use 2 requests (one for page testing the token and one for generate new token rtesting the old one). And avoid to have a hidden span with the token in every views.
HTTP uses a cycle that requires one response per request. When the client sends a request the server should send only one response back to client. So that you need to send only one response to the client either res.render() or res.json().
If you like to set some data like authentication token, you can set on your header using res.set() or res.header(). documentation
app.get(basePath, function (req, res, next) {
//More Stuff ...
res.header('token', JSON.stringify({ token: 'token' })); //use encrypted token
res.render(path.join(publicPath, '/main'), { mv: mv });
});
To set header for all routers or particular set of router you can use middleware
1) use a middleware to generate the token
2) quick tip, {token:token} is the same as {token}

nodejs: multiple GET requests with async nano/express not working

I have a superstrange error with node.js and express which is driving me nuts for two days now.
I want to display a series of images on my web app. Therefore, I'm sending a GET request from the client to my express API, which then should deliver the image.
It works perfectly with only ONE image per page.
However, if I want to display a series of images, let's say 8 images, ONLY THE LAST IMAGE IS BEING RENDERED! But the order changes occassionaly, sometimes it's the penultimate image that works, it's being shuffled in a complete random order!
But it's not only a problem with images - it's the same behaviour with ALL (async) requests!
For example, if I want to render some usernames to an iframe, I only get the data for the last iframe, all others show mit a 404 error with CANNOT GET.
This is my code on the frontend:
<iframe src="http://127.0.0.1:3000/files/bigThumb/file-version-2017-12-27T11-53-45-647Z-3DnsDX?projectdb=cdu_regierung&companydb=cdu&authsession=supersecrettoken"></iframe>
<iframe src="http://127.0.0.1:3000/files/bigThumb/file-version-2017-12-27T13-08-58-189Z-q52KKd?projectdb=cdu_regierung&companydb=cdu&authsession=supersecrettoken"></iframe>
<iframe src="http://127.0.0.1:3000/files/bigThumb/file-version-2017-12-27T13-08-58-189Z-q52KKd?projectdb=cdu_regierung&companydb=cdu&authsession=supersecrettoken"></iframe>
<iframe src="http://127.0.0.1:3000/files/bigThumb/file-version-2017-12-27T13-08-58-189Z-q52KKd?projectdb=cdu_regierung&companydb=cdu&authsession=supersecrettoken"></iframe>
this is my code in on the server side
app.all('/files/:action/:versionId', async function(req, res) {
try {
var projectName = req.query.projectdb;
var companyName = req.query.companydb;
var authSession = req.query.authsession;
var nano = _nano({url: 'http://127.0.0.1:5984/', cors: true, cookie: 'AuthSession='+ authSession});
var session = await nano.session();
session = session[0];
var username = session.userCtx.name;
res.send(username);
} catch(err) {
return res.status(401).send(err);
}
})
My guess is that it has something to do with ASYNC function in
app.all('/files/:action/:versionId', async function(req, res) {
as I never had this problem with standard sync function(req, res)
What am I doing wrong??
EDIT
I have them same problem with this code below.
app.all('/files/:action/:versionId', function(req, res) {
request('https://jsonplaceholder.typicode.com/posts/1', function (error, response, body) {
res.send(body);
});
It works perfectly with 1 GET, but not with 8 simultaneous GET requests. Also, I'm getting this error in the log:
_http_outgoing.js:494
throw new Error('Can\'t set headers after they are sent.');
Error: Can't set headers after they are sent.
at validateHeader (_http_outgoing.js:494:11)
I found the solution - it's a bug caused by the nodejs middleware "express-formidable". The issue is discussed here.
https://github.com/utatti/express-formidable/issues/6
Just use the "formidable" middleware and you're good to go.
This is the code I ended up with.
var formidable = require('formidable');
// init formidable middleware
app.use(function (req, res, next) {
var form = new formidable.IncomingForm({
encoding: 'utf-8',
multiples: false,
keepExtensions: true,
})
form.once('error', console.log)
form.parse(req, function (err, fields, files) {
Object.assign(req, {fields, files});
next();
})
});

express response locals disappear

I would like to send error messages back to the client without adding them to the url. Here is my attempt:
exports.register = function(req, res) {
if (req.body.password != req.body.password_repeat) {
res.locals.err = 'Passwords must match.';
res.locals.action = 'register';
res.redirect('/');
return;
}
...
exports.index = function(req, res) {
req.url = '/';
res.render('index', {
action: res.locals.action,
error: res.locals.error,
redirect: res.locals.redirect
});
};
So the redirect works fine and exports.index executes. The problem is that res.locals are gone by then. Is this because once I redirect it is considered a new req/res cycle? Any way I can pass this information through redirect without doing something like res.redirect('/?error=error')
You can use flash package from expressjs, but you need to have session middleware to use it. Also, you can use express-flash package from RGBboy but you need to have both cookieParser and session middlewares in this case.

Node.JS POST request to Express app secured by passport

Mechanism :
I am making this POST request to my API :
request.post('http://localhost:9876/api/alerts',{body: "test"}, function (err, res, body) {
if (err) {
self.emit('log','ERROR : API error - '+err);
}
self.emit('log','RESPONSE - '+res.statusCode);
});
On the server side, I have :
app.post('/api/alerts',function(req,res){
console.log(req);
res.status(200).send('OK');
});
Communication is made and it returns a 200 status. But on the server side, I see no trace of my request's body.
The full 'req' log is available here : https://gist.github.com/xShirase/0f9de0048e5cfa40a98c , the most relevant part being :
body: {},
I was wondering if it was coming from the Passport middleware that I use to secure the rest of my routes, or if I just botched the client request...
I have tried many different requests formats on the client side, and nothing has worked, and I have very little experience with Passport, so please let me know where my problem comes from.
Unless you have a (custom) middleware earlier up in the route/middleware chain that is doing something like:
app.use(function(req, res, next) {
var buffer = '';
req.setEncoding('utf8');
req.on('data', function(d) {
buffer += d;
}).on('end', function() {
req.body = buffer;
next();
});
});
then you probably shouldn't expect req.body to be populated since the common body parsing modules expect a Content-Type of one of application/json, application/x-www-form-urlencoded, or multipart/form-data. Your request() doesn't seem to be setting any of these, which really is correct since it's just free-form data, but that means no middleware is reading request data.

How to write to response from HTTP Client Node.JS

I have the following...
var request = require('request');
exports.list = function(req, res){
res.send("Listing");
};
exports.get = function(req, res){
request.get("<URL>", function (err, res, body) {
if (!err) {
res.send(body,"utf8");
}
});
};
This fails with the following....
TypeError: Object #<IncomingMessage> has no method 'send'
How do I do this?
UPDATE tried to use write instead of send but...
/Users/me/Development/htp/routes/property.js:9
res.setHeader('Content-Type', 'text/html');
^
TypeError: Object #<IncomingMessage> has no method 'setHeader'
Also writing out to the console instead works fine.
Problem was with scope of variables, my response output was the same name as the response object I got back in my callback. Changing this around (resp vs res) made it work....
exports.get = function(req, res){
request.get("<url>", function (err, resp, body) {
if (!err) {
res.send(body);
}
});
};
What you are trying to do, is to make Request > Response server. But you are using Request module, that allows to get stuff rather than respond.
What you need is http or better get express.js and use it, as it is straight forward and well popular web framework for exactly what you need.
I wasn't aware OP is using Express. You will encounter a similar error if you attempt to use req.send with the vanilla HTTP module instead of Express.
var http = require('http');
function requestHandler(req, res){
//res.send(200, '<html></html>'); // not a valid method without express
res.setHeader('Content-Type', 'text/html');
res.writeHead(200);
res.end('<html><body>foo bar</body></html>');
};
http.createServer(handler).listen(3000);

Resources