I found a bit of intriguing behavior on an exercise about nodejs.
The aim is to transform POST data of a request to uppercase and send back using stream.
My problem is I'm not having the same behavior between these two pieces of code (the transform function just take the buf and queueit to uppercase) :
var server = http.createServer(function (req, res) {
var tr = through(transform);
if (req.method === 'POST') {
req.pipe(tr).pipe(res);
}
});
var tr = through(transform);
var server = http.createServer(function (req, res) {
if (req.method === 'POST') {
req.pipe(tr).pipe(res);
}
});
The first one is correct and gives me :
ACTUAL EXPECTED
------ --------
"ON" "ON"
"THEM" "THEM"
"BUT," "BUT,"
...
My version with the trvar outside :
ACTUAL EXPECTED
------ --------
"QUICK." "QUICK."
"TARK'S" "TARK'S"
"QUICK." !== "BIMBOOWOOD"
"TARK'S" !== "BIMBOOWOOD"
"BIMBOOWOOD" !== "SO"
"BIMBOOWOOD" !== "SO"
...
For info the transform function :
function transform(data) {
this.queue(data.toString().toUpperCase());
}
var http = require('http')
var through = require('through')
var server = http.createServer(function(req, res) {
console.error("Been called")
if (req.method != 'POST') return res.end('send me a POST\n');
var tr = through(function(buf){
this.queue(buf.toString().toUpperCase())
})
req.pipe(tr).pipe(res)
})
server.listen(parseInt(process.argv[2]));
Run this example. Note the console.error call. The createServer requestListener is being called twice, so two instances of 'tr' are being created. If 'tr' is created outside the callback there is only one. This results in unexpected behavior when the requests and writes don't happen in the order we get oddness.
I suspect this is not intended behavior for the through module.
The comments in the problem are correct that it's an asynchronous issue (the biggest pitfall for somebody new to Node in my own experience).
PSB's solution is correct, but I wanted to be able to break the through instance out into a separate function rather than have to define it inside the createServer callback function.
The through instance needs to be wrapped in a closure so this.queue keeps the intended context.
var http = require('http');
var through = require('through');
var server = http.createServer(function(req,res){
if(req.method==='POST'){
req.pipe(tr()).
pipe(res);
}
});
server.listen(process.argv[2]);
var tr = function(){
return(through(
function(buf){
this.queue(buf.toString().toUpperCase());
})
);
};