From 09b4544211e2326586ab5f3e4847d871b168f7de Mon Sep 17 00:00:00 2001 From: Evan Hahn Date: Tue, 6 Aug 2019 14:12:19 -0500 Subject: [PATCH] Fix User-Agent version bug in Node *tl;dr: in Node, we were sending `User-Agent: Airtable.js/undefined`. This fixes that.* [This line](https://github.com/Airtable/airtable.js/blob/d9bf0f68f58ec82ffd63a206866229c61801a8c7/lib/run_action.js#L26) "computes" the user agent: ```js var userAgent = 'Airtable.js/' + process.env.npm_package_version; ``` This actually has _two_ code paths: 1. In the browser, [we transformed `process.env.npm_package_version`](https://github.com/Airtable/airtable.js/blob/d9bf0f68f58ec82ffd63a206866229c61801a8c7/gruntfile.js#L15-L18) into the real package version. As far as I know, this bug never manifests itself in browsers. 2. In Node, `process.env.npm_package_version` is a value [magically set by npm](https://docs.npmjs.com/misc/scripts#packagejson-vars). However, when I tested this with [a quick one-off script](https://gist.github.com/EvanHahn/e0f712798b1af53af4c2478bc72ab608), that value was `undefined`. This explains the bug. There are a number of ways to fix this problem: 1. Hard-code the version into the source code. While [this header is tested](https://github.com/Airtable/airtable.js/blob/d9bf0f68f58ec82ffd63a206866229c61801a8c7/test/base.test.js#L30), this approach would require manual changes, which could be brittle if you forget to run `npm test` before releasing. 2. Figure out why `process.env.npm_package_version` isn't being set and make sure it's set reliably. Documentation for these values is scant (it's unclear whether the value changes depending on the subpackage you're in or if it reflects the top-level package), and it didn't work even in my simple case, so I was inclined to steer clear of this. 3. Create a Node build in addition to a browser build. I felt like this solution was overkill, among its other issues. 4. Use `require('./package.json').version`. This works fine in Node, but increases the size of the browser build and includes unnecessary package info. (I've also had some issues requiring `package.json` in the browser in the past, though I can't remember what they were.) 5. Use `require('./package.json').version` in Node and `process.env.npm_package_version` in the browser. This is what I went with. `npm test` passes after this change. --- lib/package_version.js | 3 +++ lib/package_version_browser.js | 1 + lib/run_action.js | 5 +++-- package.json | 3 ++- 4 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 lib/package_version.js create mode 100644 lib/package_version_browser.js diff --git a/lib/package_version.js b/lib/package_version.js new file mode 100644 index 00000000..dc9c54da --- /dev/null +++ b/lib/package_version.js @@ -0,0 +1,3 @@ +// This will become package_version_browser.js when doing a browser build. +// See for more. +module.exports = require('../package.json').version; diff --git a/lib/package_version_browser.js b/lib/package_version_browser.js new file mode 100644 index 00000000..8de08b02 --- /dev/null +++ b/lib/package_version_browser.js @@ -0,0 +1 @@ +module.exports = process.env.npm_package_version; diff --git a/lib/run_action.js b/lib/run_action.js index f349ac03..ea95264f 100644 --- a/lib/run_action.js +++ b/lib/run_action.js @@ -2,10 +2,13 @@ var internalConfig = require('./internal_config.json'); var objectToQueryParamString = require('./object_to_query_param_string'); +var packageVersion = require('./package_version'); // This will become require('xhr') in the browser. var request = require('request'); +var userAgent = 'Airtable.js/' + packageVersion; + // "Full Jitter" algorithm taken from https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/ function exponentialBackoffWithJitter(numberOfRetries, initialBackoffTimeMs, maxBackoffTimeMs) { var rawBackoffTimeMs = initialBackoffTimeMs * Math.pow(2, numberOfRetries); @@ -22,8 +25,6 @@ function runAction(base, method, path, queryParams, bodyData, callback, numAttem 'x-api-version': base._airtable._apiVersion, 'x-airtable-application-id': base.getId(), }; - - var userAgent = 'Airtable.js/' + process.env.npm_package_version; var isBrowser = typeof window !== 'undefined'; // Some browsers do not allow overriding the user agent. // https://github.com/Airtable/airtable.js/issues/52 diff --git a/package.json b/package.json index 3e685517..6b6b3ed5 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,8 @@ }, "main": "./lib/airtable.js", "browser": { - "request": "xhr" + "request": "xhr", + "./lib/package_version": "./lib/package_version_browser" }, "files": [ "/README.md",