0

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?

Ivan Velichko
  • 6,348
  • 6
  • 44
  • 90

1 Answers1

0

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.

Ivan Velichko
  • 6,348
  • 6
  • 44
  • 90