From b2a2ca02464fc375ffb28aef8ee6a755502b6b0d Mon Sep 17 00:00:00 2001 From: Pablo Carranza Velez Date: Thu, 23 Mar 2017 13:08:21 -0300 Subject: [PATCH] Issue #230: Add a custom User-Agent header to all requests Header is in the format Supervisor/X.Y.Z (Linux; Resin OS v2.A.B.revC; Dev) - omitting any fields that are not available depending on the OS. Change-Type: minor Signed-off-by: Pablo Carranza Velez --- src/application.coffee | 3 ++- src/device.coffee | 8 +++----- src/lib/os-release.coffee | 32 +++++++++++++++++++++++++++++++ src/lib/supervisor-version.coffee | 6 ++++++ src/request.coffee | 14 ++++++++++++++ src/utils.coffee | 23 +--------------------- 6 files changed, 58 insertions(+), 28 deletions(-) create mode 100644 src/lib/os-release.coffee create mode 100644 src/lib/supervisor-version.coffee diff --git a/src/application.coffee b/src/application.coffee index 0b1395c1..909fec00 100644 --- a/src/application.coffee +++ b/src/application.coffee @@ -16,6 +16,7 @@ fs = Promise.promisifyAll(require('fs')) JSONStream = require 'JSONStream' proxyvisor = require './proxyvisor' { checkInt, checkTruthy } = require './lib/validation' +osRelease = require './lib/os-release' deviceConfig = require './device-config' class UpdatesLockedError extends TypedError @@ -236,7 +237,7 @@ shouldMountKmod = (image) -> device.isResinOSv1().then (isV1) -> return false if not isV1 Promise.using docker.imageRootDirMounted(image), (rootDir) -> - utils.getOSVersion(rootDir + '/etc/os-release') + osRelease.getOSVersion(rootDir + '/etc/os-release') .then (version) -> return version? and /^(Debian|Raspbian)/i.test(version) .catch (err) -> diff --git a/src/device.coffee b/src/device.coffee index b547f85b..46518149 100644 --- a/src/device.coffee +++ b/src/device.coffee @@ -11,6 +11,7 @@ execAsync = Promise.promisify(require('child_process').exec) fs = Promise.promisifyAll(require('fs')) bootstrap = require './bootstrap' { checkTruthy } = require './lib/validation' +osRelease = require './lib/os-release' memoizePromise = _.partial(memoizee, _, promise: true) @@ -224,7 +225,7 @@ do -> return exports.getOSVersion = memoizePromise -> - utils.getOSVersion(config.hostOsVersionPath) + osRelease.getOSVersion(config.hostOsVersionPath) exports.isResinOSv1 = memoizePromise -> exports.getOSVersion().then (osVersion) -> @@ -232,7 +233,4 @@ exports.isResinOSv1 = memoizePromise -> return false exports.getOSVariant = memoizePromise -> - utils.getOSReleaseField(config.hostOsVersionPath, 'VARIANT_ID') - .catch (err) -> - console.error('Failed to get OS variant', err, err.stack) - return undefined \ No newline at end of file + osRelease.getOSVariant(config.hostOsVersionPath) diff --git a/src/lib/os-release.coffee b/src/lib/os-release.coffee new file mode 100644 index 00000000..7821033e --- /dev/null +++ b/src/lib/os-release.coffee @@ -0,0 +1,32 @@ +Promise = require 'bluebird' +fs = require 'fs' +_ = require 'lodash' + +exports.getOSReleaseField = (path, field) -> + try + releaseData = fs.readFileSync(path) + lines = releaseData.toString().split('\n') + releaseItems = {} + for line in lines + [ key, val ] = line.split('=') + releaseItems[_.trim(key)] = _.trim(val) + # Remove enclosing quotes: http://stackoverflow.com/a/19156197/2549019 + return releaseItems[field].replace(/^"(.+(?="$))"$/, '$1') + catch err + console.log('Could not get OS release field: ', err, err.stack) + return undefined + + +exports.getOSVersionSync = (path) -> + exports.getOSReleaseField(path, 'PRETTY_NAME') + +exports.getOSVersion = (path) -> + Promise.try -> + exports.getOSVersionSync(path) + +exports.getOSVariantSync = (path) -> + exports.getOSReleaseField(path, 'VARIANT_ID') + +exports.getOSVariant = (path) -> + Promise.try -> + exports.getOSVariantSync(path) diff --git a/src/lib/supervisor-version.coffee b/src/lib/supervisor-version.coffee new file mode 100644 index 00000000..a4e596c6 --- /dev/null +++ b/src/lib/supervisor-version.coffee @@ -0,0 +1,6 @@ +# Parses package.json and returns resin-supervisor's version +_ = require 'lodash' +version = require('../../package.json').version +tagExtra = process.env.SUPERVISOR_TAG_EXTRA +version += '+' + tagExtra if !_.isEmpty(tagExtra) +module.exports = version diff --git a/src/request.coffee b/src/request.coffee index 316ebfd5..7702ff75 100644 --- a/src/request.coffee +++ b/src/request.coffee @@ -3,10 +3,24 @@ PlatformAPI = require 'pinejs-client' Promise = require 'bluebird' request = require 'request' url = require 'url' +osRelease = require './lib/os-release' + +osVersion = osRelease.getOSVersionSync(config.hostOsVersionPath) +osVariant = osRelease.getOSVariantSync(config.hostOsVersionPath) +supervisorVersion = require('./lib/supervisor-version') + +userAgent = "Supervisor/#{supervisorVersion}" +if osVersion? + if osVariant? + userAgent += " (Linux; #{osVersion}; #{osVariant})" + else + userAgent += " (Linux; #{osVersion})" requestOpts = gzip: true timeout: 30000 + headers: + 'User-Agent': userAgent PLATFORM_ENDPOINT = url.resolve(config.apiEndpoint, '/v2/') exports.resinApi = resinApi = new PlatformAPI diff --git a/src/utils.coffee b/src/utils.coffee index bef29c91..f78f87d1 100644 --- a/src/utils.coffee +++ b/src/utils.coffee @@ -15,11 +15,7 @@ execAsync = Promise.promisify(require('child_process').exec) device = require './device' { checkTruthy } = require './lib/validation' -# Parses package.json and returns resin-supervisor's version -version = require('../package.json').version -tagExtra = process.env.SUPERVISOR_TAG_EXTRA -version += '+' + tagExtra if !_.isEmpty(tagExtra) -exports.supervisorVersion = version +exports.supervisorVersion = require('./lib/supervisor-version') configJson = require('/boot/config.json') if Boolean(configJson.supervisorOfflineMode) @@ -230,23 +226,6 @@ exports.getKnexApp = (appId, columns) -> exports.getKnexApps = (columns) -> knex('app').select(columns) -exports.getOSReleaseField = (path, field) -> - fs.readFileAsync(path) - .then (releaseData) -> - lines = releaseData.toString().split('\n') - releaseItems = {} - for line in lines - [ key, val ] = line.split('=') - releaseItems[_.trim(key)] = _.trim(val) - # Remove enclosing quotes: http://stackoverflow.com/a/19156197/2549019 - return releaseItems[field].replace(/^"(.+(?="$))"$/, '$1') - -exports.getOSVersion = (path) -> - exports.getOSReleaseField(path, 'PRETTY_NAME') - .catch (err) -> - console.log('Could not get OS Version: ', err, err.stack) - return undefined - exports.defaultVolumes = (includeV1Volumes) -> volumes = { '/data': {}