New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nock record outputs array of hex values instead of plain JSON when response is encoded #1212

Open
richardscarrott opened this Issue Sep 9, 2018 · 1 comment

Comments

Projects
None yet
2 participants
@richardscarrott

richardscarrott commented Sep 9, 2018

Related: #457 (comment)

What is the expected behavior?
When recording responses which are compressed and chunked, e.g. Content-Encoding: 'gzip' and Transfer-Encoding: 'chunked', I was expecting the generated fixture to decompress and combine the chunks into the human readable response; this would then allow us to remove sensitive information from the response and modify it to satisfy scenarios which are hard to reproduce against the real APIs.

What is the actual behavior?
The fixtures response is an array of hex values.

Possible solution
I'm working around this by modifying the nockDefs like this:

onst { ungzip } = require('node-gzip');

try {
  if (Array.isArray(def.response)) { // NOTE: This is a v. naive check
    def.response = JSON.parse(
      (await ungzip(Buffer.from(def.response.join(''), 'hex'))).toString(
        'utf-8'
      )
    );
  }
} catch (ex) {
  console.warn('Failed to decode response');
}

If this is in fact a bug then it'd be good to fix it in nock itself -- if it's as intended, i.e. the nock is technically returning the exact same response as the real server, then perhaps an option could be passed to nock record / nock.back to have it output the decompressed response?

How to reproduce the issue
The issue can be reproduced by recording an API which returns compressed, chunked JSON.

Does the bug have a test case?
https://github.com/richardscarrott/nock-record-chunked-encoding

Versions

Software Version(s)
Nock 9.6.1
Node 10.5.0
@richardscarrott

This comment has been minimized.

richardscarrott commented Sep 10, 2018

FYI, this is the complete afterNock function I'm using

const parseNockDefs = (
  nockDefs: (nock.NockDefinition & { rawHeaders: string[] })[]
) => {
  return nockDefs.map(def => {
    try {
      const headers = def.rawHeaders.reduce<Dictionary<string>>(
        (acc, curr, i, arr) => {
          if (i % 2 === 0) {
            acc[arr[i].toLowerCase()] = arr[i + 1].toLowerCase();
          }
          return acc;
        },
        {}
      );
      if (
        headers['transfer-encoding'] === 'chunked' &&
        headers['content-encoding'] === 'gzip' &&
        Array.isArray(def.response)
      ) {
        def.response = JSON.parse(
          gunzipSync(Buffer.from(def.response.join(''), 'hex')).toString(
            'utf-8'
          )
        );
        def.rawHeaders = Object.entries(headers).flatMap(([key, value]) => {
          if (key === 'transfer-encoding' || key === 'content-encoding') {
            return [];
          }
          return [key, value];
        });
      }
    } catch (ex) {
      console.warn('Failed to decode response');
    }
    return def;
  });
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment