I use request
package with crypto
. It seems that request
implements legacy stream
protocol and don't write any data to the piped destination until it's writable
.
Stream.prototype.pipe = function(dest, options) {
var source = this;
function ondata(chunk) {
if (dest.writable) {
if (false === dest.write(chunk) && source.pause) {
source.pause();
}
}
}
...
So, if I use the next code:
const crypto = require('crypto');
const request = require('request');
var hasher = crypto.createHash('sha256');
// Uncomment the line below to fix!
// hasher.setEncoding('hex');
console.log(hasher.writable);
request('http://ya.ru').pipe(hasher).on('finish', function() {
console.log('Hash is', hasher.read());
});
it produces the sha256('')
(i.e. from empty value). But when I use hasher.setEncoding('hex')
the code produces sha256(<response_body>)
and hasher.writable
gives true
.
I can't understand what is the reason of acting this way? And where is that stated in the documentation?
Finally, there was a bug in Node. Here is even smaller code sample to reproduce it:
var hasher = crypto.createHash('sha256');
const _ = hasher._writableState; // we don't even have to call .setEnconding() here
console.log(hasher.writable);
Stream1 implementation required this.writable
to be true in the destination stream.
Stream.prototype.pipe = function(dest, options) {
var source = this;
function ondata(chunk) {
if (dest.writable) {
if (false === dest.write(chunk) && source.pause) {
source.pause();
}
}
}
source.on('data', ondata);
...
Calling to hasher.setEncoding('hex')
(or any other access to this._writableState
) triggered a call to the actual constructor of the stream. Before it this.writable
was undefined
.