Node.JS POST request to Express app secured by passport - node.js

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.

Related

Add header to all responses after processing but before sending to client

I have two endpoints in a node js app:
app.get('search', myGetController);
app.post('add', myPostController);
For simplicity, let's assume both services have only the following code:
exports.myGetController = function(req, res) {
res.status(404).json({ error: "not found" });
};
I want to have a middleware that is executed after the processing of the controllers, but before they are sent to the browser, so I can add a header based on the body of the response.
// process all responses to add ed25519
app.use(function(req, res, next) {
res.setHeader('CharCount', [How To get Body content]);
next();
});
I have two questions:
First of all, I would like to have all my controllers pass by that middleware after processing.
Second, I would like to access the body content so I can generate a header based on its content.
UPDATE
I have tried the suggested answer someone posted, and it is not working, or I am missing something.
This is what I have (before setting up my routes):
app.use(function(req, res, next) {
const oldResJson = res.json;
res.json = function(body) {
res.setHeader('myToken', generateHeaderBasedOnBody(oldResJson));
oldResJson.call(res, body);
}
next();
});
The response that is being passed to my method is an empty string, even though the response sent by the service is not empty. Am I doing this in the wrong place, or what am I missing?
One solution for this issue would be to override the res.json function like so:
// process all responses to add ed25519
app.use(function(req, res, next) {
const oldResJson = res.json;
res.json = function(body) {
res.setHeader('CharCount', /* Use body here */);
oldResJson.call(res, body);
}
next();
});
By doing this, you don't even need to change your controllers.

NodeJS request reset session

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

Express middleware before response is carried out to client

I need to modify the response data a module sends to the client, as the module uses res.send i can't seem to figure out a way for me to modify the data before it's carried out to the client.
Is there any kind of middleware/event that I can use to catch the res.send and modify the data before its executed?
I am aware that router.use exists but it's called before the router.post function and not before the res.send is sent to the client. So I need some kind of middleware which is called after the router.post function is done but before anything is sent to the client.
Well you can override the send function:
app.use(function (req, res) {
var send = res.send;
res.send = function (body) { // It might be a little tricky here, because send supports a variety of arguments, and you have to make sure you support all of them!
// Do something with the body...
send.call(this, body);
};
});
If you want to support more than just calling send(like calling end method), then you have to override more functions...
You can check connect-livereload on how it adds a script to any html output.
One more solution from here:
expressApp.use(function (req, res, next) {
req.on("end", function () {
console.log('on request end');
});
next();
});
Important Note: To work, this needs to be placed before body parser since it recreates the response object. see this answer
It can be done by overriding res.send
We override the res.send function to capture the response body in our API analytics tool as follows
// It will monkey patch the res.send.
// The patch intercepts the send invocation, executes is logic such as atatus.setResponseBody
// then restores the original send function and invokes that to finalize the req/res chain
const resSendInterceptor = (res, send) => (content) => {
// Set response body in Atatus Analytics
// Atatus is our API analytics tool
atatus.setResponseBody(content || '');
// TODO: You can modify your response body as you wish.
// Invoke the original send function.
res.send = send;
send.apply(this, arguments);
};
// Express Middleware
app.use((req, res, next) => {
// Overrides res.send
res.send = resSendInterceptor(res, res.send);
return next();
});
Your lack of code makes it really hard to answer your question, but you could use something like
Express 4.0:
router.use('/path', function (req, res) {
// Modify req
});
.use on a route will parse that before continuing on to the actual route so if somebody submitted a form or something, it will hit the .use before it goes to the .post or .get
Or you can do
Express 4.0:
app.use(function (req, res) {
// Modify Req
if (req.body.hasOwnProperty('some_form_name')) {
// Do Somthing
}
});
Which is the same thing, but it will be called before every request for every route.
Not sure if this answers your question but I think this might be what you're looking for?

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);

Connect or Express middleware to modify the response.body

I would like to have a middleware function which modifies the response body.
This is for an express server.
Something like:
function modify(req, res, next){
res.on('send', function(){
res.body = res.body + "modified"
});
next();
}
express.use(modify);
I don't understand what event to listen for. Any help or documentation would be appreciate.
You don't need to listen to any events. Just make it
function modify(req, res, next){
res.body = res.body + "modified";
next();
}
And use it after you use the router. This way after all your routes have executed you can modify the body
I believe the OP actually wants to modify the response stream once a middleware has handled the request. Look at the bundled Compress middleware implementation for an example of how this is done. Connect monkey patches the ServerResponse prototype to emit the header event when writeHead is called, but before it is completed.
express-mung is designed for this. Instead of events its just more middleware. Your example would look something like
const mung = require('express-mung')
module.exports = mung.json(body => body.modifiedBy = 'me');
Overwriting the response's write method seemed to work for me with Express 4. This allows modifying the response's body even when it's a stream.
app.use(function (req, res, next) {
var write = res.write;
res.write = function (chunk) {
if (~res.getHeader('Content-Type').indexOf('text/html')) {
chunk instanceof Buffer && (chunk = chunk.toString());
chunk = chunk.replace(/(<\/body>)/, "<script>alert('hi')</script>\n\n$1");
res.setHeader('Content-Length', chunk.length);
}
write.apply(this, arguments);
};
next();
});
Just make sure to register this middleware before any other middleware that may be modifying the response.
There seems to be a module for doing just this called connect-static-transform, check it out:
https://github.com/KenPowers/connect-static-transform
A connect middleware which allows transformation of static files before serving them.
And it comes with examples, like this one.

Resources