flickr / yakbak

Record and playback HTTP responses
MIT License
1.06k stars 84 forks source link

Respect Content-Encoding and Content-Type in tapes #2

Open jeremyruppel opened 8 years ago

jeremyruppel commented 8 years ago

It would be fantastic if the tape format took content-encoding and content-type into account when reading/writing tapes so that the recorded request body is human-readable and easily editable.

felipead commented 7 years ago

We're using Yakbak in a project and we need this feature. Let me know what you have in mind on how this should be implemented. I might submit a pull request.

jeremyruppel commented 7 years ago

I imagined this as a sort of content-type-aware parse/stringify and content-encoding-aware decode/encode. record.js would be responsible for decoding and parsing the response body if supported response header values were found, something like this pseudocode:

// record.js

return buffer(res).then(function (body) {
  // obviously body is an array right now, we'll have to change that
  return decode(body, res.headers['content-encoding']);
}).then(function (body) {
  return render({ req: req, res: res, body: body });
}) /* ... */

// decode.js
module.exports = function decode(body, encoding) {
  if (encoding === 'gzip') {
    return Promise.fromCallback(function (done) {
      zlib.gunzip(body, done);
    });
  } else {
    return Promise.resolve(body);
  }
};

I don't want to introduce any dependencies in tapes that aren't in node core, so unfortunately re-encoding the body probably has to be done in the template itself, perhaps something like:

// tape.ejs
<% if (res.headers['content-type'] === 'gzip') { %>
var encode = zlib.createGzip();
<% } else { %>
var encode = new stream.PassThrough;
<% } %>

encode.pipe(res);
encode.end(body);

encode/decode are probably safe because they ought to be strictly inverse functions. parse/stringify are arbitrary though; I'm not sure there's a good way to reliably make the response body more readable/editable in the tape and then return it to exactly what the server responded with. Maybe we should start with encode/decode, which at least will give you a human-readable response body, then later we can think about formatting it.