code: function fullRequestUrl(opts) {
      assert.object(opts, 'opts');
  
      // the incoming opts.path value is the value on the request:
      // i.e., client.get(`opts.path`, function() { ... });
      // This path value includes any query params as well. the url module calls
      // this value `pathname`. use a new object so as not to reuse any of the
      // now mutated values on opts. combine with a select few existing options
      // to get the fullurl object.
      var urlObj = _.assign({}, url.parse(opts.path), {
          protocol: opts.protocol,
          host: opts.host,
          port: opts.port
      });
  
      return url.format(urlObj);
  }
docs: /*------------------------------------------------------------------------------
  private methods
  ------------------------------------------------------------------------------ 
  given options object for a request, build the fully qualified url. this
  method needs to exist primarily a result of the inconsistencies in the
  options between node core's API:
  http.request()
  url.parse()
  this is not strictly a node issue perse, but rather that this module uses
  url.parse() to create the initial "state" of options for http.request(),
  then modifies them in a way such that they're no longer compatible with
  url modules methods. this is ripe for revisiting at some point later in
  time. For reference in the meantime:
  https://nodejs.org/api/url.html#url_url_strings_and_url_objects
  
  the value returned by this function is used only for error
  logging/visibility.
  @private
  @function fullRequestUrl
  @param {Object} opts request options
  @param {String} opts.path the requested path as set by the user
  @param {String} opts.protocol http/https
  @param {String} opts.host hostname of the request
  @param {String} opts.port port number of the request
  @returns {String}