isValidHost(headers, headerToCheck, validateHost = true) {
    if (this.options.allowedHosts === "all") {
      return true;
    }

    // get the Host header and extract hostname
    // we don't care about port not matching
    const header = headers[headerToCheck];

    if (!header) {
      return false;
    }

    if (DEFAULT_ALLOWED_PROTOCOLS.test(header)) {
      return true;
    }

    // use the node url-parser to retrieve the hostname from the host-header.
    const hostname = url.parse(
      // if header doesn't have scheme, add // for parsing.
      /^(.+:)?\/\//.test(header) ? header : `//${header}`,
      false,
      true,
    ).hostname;

    if (hostname === null) {
      return false;
    }

    if (this.isHostAllowed(hostname)) {
      return true;
    }

    // always allow requests with explicit IPv4 or IPv6-address.
    // A note on IPv6 addresses:
    // header will always contain the brackets denoting
    // an IPv6-address in URLs,
    // these are removed from the hostname in url.parse(),
    // so we have the pure IPv6-address in hostname.
    // For convenience, always allow localhost (hostname === 'localhost')
    // and its subdomains (hostname.endsWith(".localhost")).
    // allow hostname of listening address  (hostname === this.options.host)
    const isValidHostname = validateHost
      ? ipaddr.IPv4.isValid(hostname) ||
        ipaddr.IPv6.isValid(hostname) ||
        hostname === "localhost" ||
        hostname.endsWith(".localhost") ||
        hostname === this.options.host
      : false;

    return isValidHostname;
  }
@private
@param {{ [key: string]: string | undefined }} headers
@param {string} headerToCheck
@param {boolean} validateHost
@returns {boolean}