hrsh7th / msw-snapshot

Transparently create an API cache for testing.
6 stars 2 forks source link

Headers order affects hash #4

Closed Maxim-Mazurok closed 11 months ago

Maxim-Mazurok commented 1 year ago

Something changed the order of headers in my request, not sure what exactly, maybe node-fetch update.

And it resulted in new snapshots being generated.

This is the original req.headers.raw():

{
  accept: '*/*',
  'accept-encoding': 'gzip, deflate, br',
  'user-agent': 'node-fetch',
  host: 'd.joinhoney.com'
}

And this is sorted:

{
  accept: '*/*',
  'accept-encoding': 'gzip, deflate, br',
  host: 'd.joinhoney.com',
  'user-agent': 'node-fetch'
}

I used this function:

function sortObjectByKeys(obj) {
  const sortedKeys = Object.keys(obj).sort();
  const sortedObj = {};

  sortedKeys.forEach(key => {
    sortedObj[key] = obj[key];
  });

  return sortedObj;
}

generated by GPT4: https://chat.openai.com/share/1b103ef9-723e-4b5a-9c88-a2179ba26f34

I will be using the following patch for now:

See https://github.com/hrsh7th/msw-snapshot/issues/4

diff --git a/node_modules/msw-snapshot/dist/cjs/index.js b/node_modules/msw-snapshot/dist/cjs/index.js
index a43042c..9407cdb 100644
--- a/node_modules/msw-snapshot/dist/cjs/index.js
+++ b/node_modules/msw-snapshot/dist/cjs/index.js
@@ -129,6 +129,16 @@ var snapshot = function (config) {
     }); });
 };
 exports.snapshot = snapshot;
+function sortObjectByKeys(obj) {
+  const sortedKeys = Object.keys(obj).sort();
+  const sortedObj = {};
+
+  sortedKeys.forEach(key => {
+    sortedObj[key] = obj[key];
+  });
+
+  return sortedObj;
+}
 /**
  * Create snapshot name from request.
  */
@@ -152,7 +162,7 @@ var createSnapshotName = function (req, config) { return __awaiter(void 0, void
                 _e = [req.method,
                     req.url.origin,
                     req.url.searchParams.entries(),
-                    req.headers.raw(),
+                    sortObjectByKeys(req.headers.raw()),
                     req.cookies];
                 return [4 /*yield*/, cloned.text()];
             case 3: return [2 /*return*/, _b.apply(_a, [_d.apply(_c, [_e.concat([

Caution is that technically order of headers can matter depending on server implementation, but that would be pretty unconventional server I think. Order of headers usually matters if you have headers with the same key, but since req.headers.raw() returns an object - all keys are already unique, so this shouldn't be an issue. Hope this helps someone!

hrsh7th commented 1 year ago

I'm refactoring msw-snapshot now. The refactored version uses getSortedEntries for this. But it has some of the brealing changes.

hrsh7th commented 11 months ago

The new version of msw-snapshot was published and it would solve this problem. Close for now.