docs: def ensembl_request(self, ext, headers):
          """ obtain sequence via the ensembl REST API
          """
          
          self.attempt += 1
          if self.attempt > 5:
              raise ValueError("too many attempts, figure out why its failing")
          
          response, status, requested_headers = self.open_url(self.server + ext, headers=headers)
          
          # we might end up passing too many simultaneous requests, or too many
          # requests per hour, just wait until the period is finished before
          # retrying
          if status == 429:
              if "retry-after" in requested_headers:
                  time.sleep(float(requested_headers["retry-after"]))
              elif "x-ratelimit-reset" in requested_headers:
                  time.sleep(int(requested_headers["x-ratelimit-reset"]))
              
              return self.ensembl_request(ext, headers)
          # retry after 30 seconds if we get service unavailable error
          elif status in [500, 503, 504]:
              time.sleep(30)
              return self.ensembl_request(ext, headers)
          elif status != 200:
              raise ValueError("Invalid Ensembl response for {}\nheaders: {}\nresponse: {}".format(\
                      self.server + ext, requested_headers, response))
          
          # sometimes ensembl returns odd data. I don't know what it is, but the
          # json interpreter can't handle it. Rather than trying to catch it,
          # simply re-request the data
          if requested_headers["content-type"] == "application/json":
              try:
                  json.loads(response)
              except ValueError:
                  now = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
                  logging.warning("{}\t{}\t{}\t{}\t{}".format(now,
                      status, self.server + ext,
                      "cannot obtain json output"))
                  return self.ensembl_request(ext, requested_headers)
          
          self.cache.cache_url_data(self.server + ext, response)
          
          return response