Node.js get response outside app.post - node.js

I want get response, to save cookie.. I used express on node.js
app.post('/', function (req, res) {
res.setHeader("Set-Cookie", ["dok=javascript"]);
})
I want to do outside of app.post - real time used socket.io
for example:
socket.on('Login-clicked', function(data) {
if(data == ok) {
res.setHeader("Set-Cookie", ["dok=javascript"]);
}
});
How can i do?

I think what you are trying to do here is access res in socket.on('Login-clicked') event.To do that first make res global.
global.res={};
app.post('/', function (req, res) {
global.res=res;
});
socket.on('Login-clicked', function(data) {
if(data == ok) {
global.res.setHeader("Set-Cookie", ["dok=javascript"]);
}
});

Related

Altering express session after res.render is executed

I am looking to store information generated by a post-route in the session, pass it on to a get-route (where I redirect after the post is done), run res.render() with that information from the session and then clear it so the session-variable is empty for the next route (Code block explains problem as well if this was too vague). Please keep in mind that the code below is a simplified version, my program contains a working session in which I can store and access variables.
const clearSessionMessage = async (req, res, next) => {
await res.on('finish', () => {
let sess = req.session;
sess.message = '';
});
next();
};
app.use(clearSessionMessage);
app.get('/route', (req, res) => {
let sess = req.session;
res.render('template', { message: sess.message });
});
app.post('/post/route' (req, res) => {
let sess = req.session;
sess.message = 'The message I want to pass';
res.redirect('/route');
});
Possible solutions I have tried:
Change the 'finish' parameter in res.on() to: finish, end or close
Force the session to save with req.session.save(callback)
After some research I have been able to solve my problem.
It is possible to edit the session after calling res.render(); but if you wish to do that you have to make sure you force the session to save with req.session.save(callback). This is because express will automatically save the session after a res.render();, edits after the render are not automatically saved!
app.get('/route', (req, res) => {
res.render('template', { message: req.session.message });
req.session.message = undefined;
req.session.save(err => {
if (err) {
throw err;
};
});
});
app.post('/post/route' (req, res) => {
req.session.message = 'The message I want to pass';
res.redirect('/route');
});
You don't really need to save or modify the session after a res.render call but save a local variable before destroying the session, which is then passed to the rendered page:
app.get('/route', (req, res) => {
let msg = req.session.message;
req.session.message = undefined;
res.render('template', { message: msg });
});
app.post('/post/route' (req, res) => {
req.session.message = 'The message I want to pass';
res.redirect('/route');
});

nodejs callback issue.. not a function

I am currently learning NodeJS and working on a mini app, trying to understand callback. However I keep getting the error:
callback(undefined,price);
^TypeError: callback is not a function
This is my code :
var getCoin = (coin, callback) => {
request({url:`https://https://rest.coinapi.io/${coin}&ssr=USD`,
json: true
}, (error, response, body) => {
if(error){
callback("error");
}
else if (response.statusCode == 200) {
let price = body.RAW[coin].USD.PRICE;
callback(undefined,price);
}
})
};
app.get('/', (req, res) => {
coin.getCoin('BTC', ()=> {
res.render('index.hbs', {
coin:'Bitcoin',
price: coin.getCoin('BTC')
});
});
});
Try this code:
app.get('/', (req, res) => {
coin.getCoin('BTC', (err, price)=> {
res.render('index.hbs', {
coin:'Bitcoin',
price: price
});
});
});
I am assuming coin.getCoin accepts two arguments, second argument is callback which itself needs to accept args to work properly. Now in app.get('/' you called coin.getCoin and passed an anonymous function that will be treated as callback for it, if coin.getCoin does its job correctly then price will have the value that will eventually be passed to index.hbs and res.render will do the rest job.

nodejs proxy timing and async behavior

I have a question about the code below:
I would need a confirmation that all the processing done in proxyRes event
will be done asynchronously and all processing time in it won't affect
the proxying time.
Thank you in advance for help in this
var server = http.createServer(function (req, res) {
console.time();
var proxy = httpProxy.createProxyServer();
proxy.web(req, res, {
target: 'https://gdev.sserver.be/api/host1/account',
});
console.timeEnd();
proxy.on('proxyRes', function (proxyRes, req, res) {
//console.log('RAW Response from the target', JSON.stringify(proxyRes.headers, true, 2));
proxyRes.on('data', function (chunk) {
console.log('resp => ' + chunk);
connection.query('INSERT INTO test SET ?', {content: chunk}, function(err, result) {
if (err) throw err;
console.log('writing in db');
});
});
proxy.close();
proxy = null;
});
}).listen(3000);
Yes, the contents of your proxyRes handler appear to be asynchronous. The proxy will occur while the database query is still doing what it needs to do, so you're right that it won't affect proxying time.

Finish processing request in express.js

When I have a simple function processing the request I can use res.end() and return to end it at any point (some error happened/incorrect data, etc.)
get('/', function (req, res) {
if (!req.param('id')) {
res.send('Must provide ID!');
res.end(); // <-- response is ready, send it to client
return; // <-- request processing stops here, get() finishes
}
// do other stuff
res.send('ok'); // <-- this can never overlap with the previous res.send()
});
However, if there are functions embedded in other functions, return will only quit the last one
get('/', function (req, res) {
validate(req);
// do other stuff
res.send('ok'); // <-- this can cause errors? res was ended already
});
function validate(req, res) {
if (!req.param('id')) {
res.send('Must provide ID!');
res.end(); // <-- send response to client
return; // <-- this one exists only from validate()
}
}
I believe to send the response to client res.end() should be called, but how can I stop further code from processing - i.e. return from all functions?
It is impossible to return from a called function, just use a callback as below:
function validate(req, res, callback) {
if (!req.param('id')) {
res.send('Must provide ID!');
res.end();
} else {
callback();
}
}
get('/', function (req, res) {
validate(req, function () {
res.send('ok');
});
});
You could return true or false in validate function depending on if you had already sent response.
But, it's not node style. Using callbacks is preferred in node.
I know this is an old question but may be helpful for others. You could use res.headersSent like this
get('/', function (req, res) {
validate(req);
// will only be sent if validate hasn't already sent the error message
if(!res.headersSent) {
res.send('ok');
}
});
function validate(req, res) {
if (!req.param('id')) {
res.send('Must provide ID!');
res.end();
}
}

Invoking an asynchronous method inside a middleware in node-http-proxy

I'm trying to create a proxy with node-http-proxy in Node.js that checks whether a request is authorized in a mongodb.
Basically, I created a middleware module for the node-http-proxy that I use like this:
httpProxy.createServer(
require('./example-middleware')(),
9005, 'localhost'
).listen(8005)
What the middleware module does is using mongojs to connect to mongodb and run a query to see if the user is authorized to access the resource:
module.exports = function(){
// Do something when first loaded!
console.log("Middleware loaded!");
return function (req, res, next) {
var record = extractCredentials(req);
var query = -- Db query --
//Debug:
log("Query result", query);
db.authList.find(query).sort({
"url.len": -1
}, function(err, docs){
console.log(docs);
// Return the creator for the longest matching path:
if(docs.length > 0) {
console.log("User confirmed!");
next();
} else {
console.log("User not confirmed!");
res.writeHead(403, {
'Content-Type': 'text/plain'
});
res.write('You are not allowed to access this resource...');
res.end();
}
});
}
}
Now the problem is that as soon as I add the asynchronous call to mongodb using mongojs the proxy hangs and never send the response back.
To clarify: on a "User not confirmed" everything works fine and the 403 is returned. On a "user confirmed" however I see the log but the browser then hangs forever and the request isn't proxied.
Now, if I remove the "user confirmed" and next() part outside of a callback it does work:
module.exports = function(){
// Do something when first loaded!
console.log("Middleware loaded!");
return function (req, res, next) {
var record = extractCredentials(req);
var query = --- query ---
console.log("User confirmed!");
next();
}
but I can't do that since the mongojs query is meant (rightfully I guess) to be executed asynchronously, the callback being triggered only when the db replied...
I also tried the version without using a middleware:
http.createServer(function (req, res) {
// run the async query here!
proxy.proxyRequest(req, res, {
host: 'localhost',
port: 9000
});
}).listen(8001);
But that did not help either...
Any clue? Note that I'm new to node.js so I suspect a misunderstanding on my side...
Found the answer, actually the catch is that the request needs to be buffered:
httpProxy.createServer(function (req, res, proxy) {
// ignore favicon
if (req.url === '/favicon.ico') {
res.writeHead(200, {
'Content-Type': 'image/x-icon'
} );
res.end();
console.log('favicon requested');
return;
}
var credentials = extractCredentials(req);
console.log(credentials);
var buffer = httpProxy.buffer(req);
checkRequest(credentials, function(user){
if(user == ...) {
console.log("Access granted!");
proxy.proxyRequest(req, res, {
host: 'localhost',
port: 9005,
buffer: buffer
});
} else {
console.log("Access denied!");
res.writeHead(403, {
"Content-Type": "text/plain"
});
res.write("You are not allowed to access this resource...");
res.end();
}
});
}).listen(8005);
Two problems:
You're not calling next(); in the else case of your sort callback.
The second parameter to your sort callback is a Cursor, not an array of documents. As such, docs.length > 0 is never true and the code always follows the else path.

Resources