diff --git a/lib/datasource/cargo/index.js b/lib/datasource/cargo/index.js
index 88c2fb8f4bd2ddba896c5b5121491e87e2fee579..d94685c12a562099278bd2ec34101a1d46b4483c 100644
--- a/lib/datasource/cargo/index.js
+++ b/lib/datasource/cargo/index.js
@@ -9,6 +9,7 @@ async function getPkgReleases({ lookupName }) {
   try {
     const res = (await got(crateUrl, {
       json: true,
+      platform: 'cargo',
     })).body;
     if (!(res && res.crate && res.crate.name && res.versions)) {
       logger.warn({ dependency: lookupName }, `Received invalid crate data`);
diff --git a/lib/datasource/github/index.js b/lib/datasource/github/index.js
index c5d1b97608909f379746d2320e0e2a96b62125e2..36873cca3746aaedd8b1c396b5af966fb73fa9d3 100644
--- a/lib/datasource/github/index.js
+++ b/lib/datasource/github/index.js
@@ -1,6 +1,5 @@
 const ghGot = require('../../platform/github/gh-got-wrapper');
 const got = require('../../util/got');
-const hostRules = require('../../util/host-rules');
 
 module.exports = {
   getPreset,
@@ -13,11 +12,8 @@ async function fetchJSONFile(repo, fileName) {
   const opts = {
     headers: { accept: 'application/vnd.github.v3+json' },
     json: true,
+    platform: 'github',
   };
-  const rules = hostRules.find({ platform: 'github', host: 'api.github.com' });
-  if (rules && rules.token) {
-    opts.headers.Authorization = `Bearer ${rules.token}`;
-  }
   let res;
   try {
     res = await got(url, opts);
diff --git a/lib/datasource/go/index.js b/lib/datasource/go/index.js
index 83843c1197b43c51695fa61771e1d87f41db3f45..f76ad4bac56c94e92c78133610f33fd30b4112cf 100644
--- a/lib/datasource/go/index.js
+++ b/lib/datasource/go/index.js
@@ -25,7 +25,7 @@ async function getDatasource(name) {
   const pkgUrl = `https://${name}?go-get=1`;
   try {
     const res = (await got(pkgUrl, {
-      retry: 5,
+      platform: 'go',
     })).body;
     const sourceMatch = res.match(
       new RegExp(`<meta name="go-source" content="${name}\\s+([^\\s]+)`)
diff --git a/lib/datasource/hex/index.js b/lib/datasource/hex/index.js
index 4b14939f58899c72cbfae100056bde479d99dc9f..fc78696fe8e60c8b9e87e527bba60740313d3014 100644
--- a/lib/datasource/hex/index.js
+++ b/lib/datasource/hex/index.js
@@ -1,20 +1,14 @@
-const URL = require('url');
-
 const got = require('../../util/got');
-const hostRules = require('../../util/host-rules');
 
 module.exports = {
   getPkgReleases,
 };
 
-function getHostOpts(url) {
-  const { host } = URL.parse(url);
-  const opts = hostRules.find({ platform: 'hex', host }, { json: true });
-  if (opts && opts.token) {
-    opts.hearders = { Authorization: opts.token };
-    delete opts.token;
-  }
-  return opts;
+function getHostOpts() {
+  return {
+    json: true,
+    platform: 'hex',
+  };
 }
 
 async function getPkgReleases({ lookupName }) {
diff --git a/lib/datasource/maven/index.js b/lib/datasource/maven/index.js
index ff6e23ea23170e6f1cc1f299843eb8425580d58c..ca7246f3c1951f3c6ff2a6034a2fb11f4c6351a8 100644
--- a/lib/datasource/maven/index.js
+++ b/lib/datasource/maven/index.js
@@ -133,7 +133,7 @@ async function downloadFileProtocol(pkgUrl) {
 async function downloadHttpProtocol(pkgUrl) {
   let raw;
   try {
-    raw = await got(pkgUrl);
+    raw = await got(pkgUrl, { platform: 'maven' });
   } catch (err) {
     if (isNotFoundError(err)) {
       logger.debug(`Url not found ${pkgUrl}`);
diff --git a/lib/datasource/nuget/get.js b/lib/datasource/nuget/get.js
deleted file mode 100644
index cdb2e735f5198323ef0b7a66c926cf5f9de5a7dd..0000000000000000000000000000000000000000
--- a/lib/datasource/nuget/get.js
+++ /dev/null
@@ -1,21 +0,0 @@
-const got = require('../../util/got');
-const hostRules = require('../../util/host-rules');
-
-module.exports = get;
-
-function get(url, options) {
-  const finalOptions = options || {};
-  const hostRule = hostRules.find({ platform: 'nuget', endpoint: url });
-  if (hostRule && hostRule.username && hostRule.password) {
-    const auth = Buffer.from(
-      `${hostRule.username}:${hostRule.password}`
-    ).toString('base64');
-    finalOptions.headers = finalOptions.headers || {};
-    finalOptions.headers.Authorization = `Basic ${auth}`;
-    logger.debug(
-      { url },
-      `Setting basic auth header as configured via host rule`
-    );
-  }
-  return got(url, finalOptions);
-}
diff --git a/lib/datasource/nuget/v2.js b/lib/datasource/nuget/v2.js
index 4c51e93800f10b7e62f2ef75e54e0f113c3339e3..5580462410fb830c17a9ae44ddee97dec3c55f82 100644
--- a/lib/datasource/nuget/v2.js
+++ b/lib/datasource/nuget/v2.js
@@ -1,6 +1,6 @@
 const parse = require('github-url-from-git');
 const { XmlDocument } = require('xmldoc');
-const get = require('./get');
+const got = require('../../util/got');
 
 module.exports = {
   getPkgReleases,
@@ -12,7 +12,7 @@ async function getPkgReleases(feedUrl, pkgName) {
     pkgName,
   };
   try {
-    const pkgVersionsListRaw = await get(pkgUrlList, { retry: 5 });
+    const pkgVersionsListRaw = await got(pkgUrlList, { platform: 'nuget' });
     if (pkgVersionsListRaw.statusCode !== 200) {
       logger.debug(
         { dependency: pkgName, pkgVersionsListRaw },
diff --git a/lib/datasource/nuget/v3.js b/lib/datasource/nuget/v3.js
index 5c8528e3c749c5c156d808b895e19f301304359d..dee96f9cfab4bb57aa5859754817474879f1d510 100644
--- a/lib/datasource/nuget/v3.js
+++ b/lib/datasource/nuget/v3.js
@@ -1,6 +1,6 @@
 const parse = require('github-url-from-git');
 const { XmlDocument } = require('xmldoc');
-const get = require('./get');
+const got = require('../../util/got');
 
 module.exports = {
   getQueryUrl,
@@ -18,10 +18,7 @@ function getDefaultFeed() {
 async function getQueryUrl(url) {
   // https://docs.microsoft.com/en-us/nuget/api/search-query-service-resource
   try {
-    const servicesIndexRaw = await get(url, {
-      retry: 5,
-      json: true,
-    });
+    const servicesIndexRaw = await got(url, { json: true, platform: 'nuget' });
     if (servicesIndexRaw.statusCode !== 200) {
       logger.debug(
         { dependency: url, servicesIndexRaw },
@@ -48,9 +45,9 @@ async function getPkgReleases(registryUrl, feedUrl, pkgName) {
     pkgName,
   };
   try {
-    const pkgUrlListRaw = await get(queryUrl, {
-      retry: 5,
+    const pkgUrlListRaw = await got(queryUrl, {
       json: true,
+      platform: 'nuget',
     });
     if (pkgUrlListRaw.statusCode !== 200) {
       logger.debug(
@@ -75,7 +72,7 @@ async function getPkgReleases(registryUrl, feedUrl, pkgName) {
         const nugetOrgApi = `https://api.nuget.org/v3-flatcontainer/${pkgName.toLowerCase()}/${
           [...dep.releases].pop().version
         }/${pkgName.toLowerCase()}.nuspec`;
-        const result = await get(nugetOrgApi);
+        const result = await got(nugetOrgApi, { platform: 'nuget' });
         const nuspec = new XmlDocument(result.body);
         if (nuspec) {
           const sourceUrl = parse(
diff --git a/lib/datasource/pypi/index.js b/lib/datasource/pypi/index.js
index 124eaefe86175f8c45709acac658678f1d24f857..8520ce123941dcbbe238e6888dd94346ce99f1e5 100644
--- a/lib/datasource/pypi/index.js
+++ b/lib/datasource/pypi/index.js
@@ -56,6 +56,7 @@ async function getDependency(depName, hostUrl, compatibility) {
     const dependency = {};
     const rep = await got(url.parse(lookupUrl), {
       json: true,
+      platform: 'pypi',
     });
     const dep = rep && rep.body;
     if (!dep) {
@@ -104,6 +105,7 @@ async function getSimpleDependency(depName, hostUrl) {
     const dependency = {};
     const response = await got(url.parse(lookupUrl), {
       json: false,
+      platform: 'pypi',
     });
     const dep = response && response.body;
     if (!dep) {
diff --git a/lib/datasource/rubygems/get.js b/lib/datasource/rubygems/get.js
index 3c7fd5699b80e382466cf9df31dff1e8b5c092fe..ca25bc202bc92c080d554fbeda7992f8db706b42 100644
--- a/lib/datasource/rubygems/get.js
+++ b/lib/datasource/rubygems/get.js
@@ -1,8 +1,5 @@
-const URL = require('url');
-
 const got = require('../../util/got');
 const { maskToken } = require('../../util/mask');
-const hostRules = require('../../util/host-rules');
 const retriable = require('./retriable');
 const { UNAUTHORIZED, FORBIDDEN, NOT_FOUND } = require('./errors');
 
@@ -33,11 +30,8 @@ const processError = ({ err, ...rest }) => {
   }
 };
 
-const getHeaders = url => {
-  const { host } = URL.parse(url.toString());
-  const { token } = hostRules.find({ host, platform: 'rubygems' }) || {};
-
-  return token ? { Authorization: token } : {};
+const getHeaders = () => {
+  return { platform: 'rubygems' };
 };
 
 const fetch = async ({ dependency, registry, path }) => {
diff --git a/lib/datasource/terraform/index.js b/lib/datasource/terraform/index.js
index aaa1410a74bf4fb2c5b1e8b16618fbe4af6918b7..1603303fff78b5884f920352300cf783916e5a9a 100644
--- a/lib/datasource/terraform/index.js
+++ b/lib/datasource/terraform/index.js
@@ -52,7 +52,7 @@ async function getPkgReleases({ lookupName, registryUrls }) {
   try {
     const res = (await got(pkgUrl, {
       json: true,
-      retry: 5,
+      platform: 'terraform',
     })).body;
     const returnedName = res.namespace + '/' + res.name + '/' + res.provider;
     if (returnedName !== repository) {
diff --git a/lib/util/got/host-rules.js b/lib/util/got/host-rules.js
new file mode 100644
index 0000000000000000000000000000000000000000..39862230da7294d7996f0a19202621edbb11fcab
--- /dev/null
+++ b/lib/util/got/host-rules.js
@@ -0,0 +1,41 @@
+const got = require('got');
+const hostRules = require('../host-rules');
+
+// Apply host rules to requests
+
+// istanbul ignore next
+module.exports = got.create({
+  options: {},
+  handler: (options, next) => {
+    const { platform, ...opts } = options;
+    if (!options.hostname) {
+      return next(opts);
+    }
+    const hostRule = hostRules.find({
+      host: options.hostname,
+      platform,
+    });
+    if (!hostRule) {
+      return next(opts);
+    }
+    if (!options.headers.authorization) {
+      if (hostRule.username && hostRule.password) {
+        logger.debug(
+          'Applying Basic authentication for host ' + options.hostname
+        );
+        const auth = Buffer.from(
+          `${hostRule.username}:${hostRule.password}`
+        ).toString('base64');
+        opts.headers.authorization = `Basic ${auth}`;
+      } else if (hostRule.token) {
+        logger.debug(
+          'Applying Bearer authentication for host ' + options.hostname
+        );
+        opts.headers.authorization = `Bearer ${hostRule.token}`;
+      }
+    }
+    // TODO: apply other options/headers
+    // istanbul ignore next
+    return next(opts);
+  },
+});
diff --git a/lib/util/got/index.js b/lib/util/got/index.js
index 70130c1ff85baa12faa979d76058a60dcd14b77a..38d24e7fb69d5d90232f9fb7f89f5c6dd1282df1 100644
--- a/lib/util/got/index.js
+++ b/lib/util/got/index.js
@@ -1,6 +1,7 @@
 const got = require('got');
 const cacheGet = require('./cache-get');
 const renovateAgent = require('./renovate-agent');
+const hostRules = require('./host-rules');
 
 /*
  * This is the default got instance for Renovate.
@@ -10,4 +11,4 @@ const renovateAgent = require('./renovate-agent');
  * Important: always put the renovateAgent one last, to make sure the correct user agent is used
  */
 
-module.exports = got.mergeInstances(cacheGet, renovateAgent);
+module.exports = got.mergeInstances(cacheGet, renovateAgent, hostRules);
diff --git a/test/datasource/__snapshots__/pypi.spec.js.snap b/test/datasource/__snapshots__/pypi.spec.js.snap
index 27ee1735f2f7c01db6c4381c4da9b1795c202afa..607b5894e6b9925f0de97e813ebb8f512a497842 100644
--- a/test/datasource/__snapshots__/pypi.spec.js.snap
+++ b/test/datasource/__snapshots__/pypi.spec.js.snap
@@ -181,6 +181,7 @@ Array [
     },
     Object {
       "json": true,
+      "platform": "pypi",
     },
   ],
 ]
@@ -205,6 +206,7 @@ Array [
     },
     Object {
       "json": true,
+      "platform": "pypi",
     },
   ],
 ]
@@ -229,6 +231,7 @@ Array [
     },
     Object {
       "json": true,
+      "platform": "pypi",
     },
   ],
   Array [
@@ -248,6 +251,7 @@ Array [
     },
     Object {
       "json": true,
+      "platform": "pypi",
     },
   ],
 ]
diff --git a/test/datasource/nuget.spec.js b/test/datasource/nuget.spec.js
index 4e39ae9069d59b7a61faa0d938eb4b6d0ebe6c65..7fc833df3624e9764083674fcc2c949f49637236 100644
--- a/test/datasource/nuget.spec.js
+++ b/test/datasource/nuget.spec.js
@@ -1,7 +1,6 @@
 const fs = require('fs');
 const got = require('../../lib/util/got');
 const datasource = require('../../lib/datasource');
-const hostRules = require('../../lib/util/host-rules');
 
 jest.mock('../../lib/util/got');
 jest.mock('../../lib/util/host-rules');
@@ -80,30 +79,6 @@ describe('datasource/nuget', () => {
       ).toBeNull();
     });
 
-    it('supports basic authentication', async () => {
-      got.mockReturnValueOnce({
-        body: JSON.parse(nugetIndexV3),
-        statusCode: 200,
-      });
-      got.mockReturnValueOnce({
-        body: JSON.parse('{"totalHits": 0}'),
-        statusCode: 200,
-      });
-
-      hostRules.find.mockReturnValue({
-        username: 'some-username',
-        password: 'some-password',
-      });
-
-      await datasource.getPkgReleases({
-        ...configV3,
-      });
-
-      expect(got.mock.calls[0][1].headers.Authorization).toBe(
-        'Basic c29tZS11c2VybmFtZTpzb21lLXBhc3N3b3Jk'
-      );
-    });
-
     it('queries the default nuget feed if no registries are supplied', async () => {
       await datasource.getPkgReleases({
         ...configNoRegistryUrls,