function parseOptions()

in lib/browser/api/net.ts [218:306]


function parseOptions (optionsIn: ClientRequestConstructorOptions | string): NodeJS.CreateURLLoaderOptions & { redirectPolicy: RedirectPolicy, headers: Record<string, { name: string, value: string | string[] }> } {
  const options: any = typeof optionsIn === 'string' ? url.parse(optionsIn) : { ...optionsIn };

  let urlStr: string = options.url;

  if (!urlStr) {
    const urlObj: url.UrlObject = {};
    const protocol = options.protocol || 'http:';
    if (!kSupportedProtocols.has(protocol)) {
      throw new Error('Protocol "' + protocol + '" not supported');
    }
    urlObj.protocol = protocol;

    if (options.host) {
      urlObj.host = options.host;
    } else {
      if (options.hostname) {
        urlObj.hostname = options.hostname;
      } else {
        urlObj.hostname = 'localhost';
      }

      if (options.port) {
        urlObj.port = options.port;
      }
    }

    if (options.path && / /.test(options.path)) {
      // The actual regex is more like /[^A-Za-z0-9\-._~!$&'()*+,;=/:@]/
      // with an additional rule for ignoring percentage-escaped characters
      // but that's a) hard to capture in a regular expression that performs
      // well, and b) possibly too restrictive for real-world usage. That's
      // why it only scans for spaces because those are guaranteed to create
      // an invalid request.
      throw new TypeError('Request path contains unescaped characters');
    }
    const pathObj = url.parse(options.path || '/');
    urlObj.pathname = pathObj.pathname;
    urlObj.search = pathObj.search;
    urlObj.hash = pathObj.hash;
    urlStr = url.format(urlObj);
  }

  const redirectPolicy = options.redirect || 'follow';
  if (!['follow', 'error', 'manual'].includes(redirectPolicy)) {
    throw new Error('redirect mode should be one of follow, error or manual');
  }

  if (options.headers != null && typeof options.headers !== 'object') {
    throw new TypeError('headers must be an object');
  }

  const urlLoaderOptions: NodeJS.CreateURLLoaderOptions & { redirectPolicy: RedirectPolicy, headers: Record<string, { name: string, value: string | string[] }> } = {
    method: (options.method || 'GET').toUpperCase(),
    url: urlStr,
    redirectPolicy,
    headers: {},
    body: null as any,
    useSessionCookies: options.useSessionCookies,
    credentials: options.credentials,
    origin: options.origin
  };
  const headers: Record<string, string | string[]> = options.headers || {};
  for (const [name, value] of Object.entries(headers)) {
    if (!isValidHeaderName(name)) {
      throw new Error(`Invalid header name: '${name}'`);
    }
    if (!isValidHeaderValue(value.toString())) {
      throw new Error(`Invalid value for header '${name}': '${value}'`);
    }
    const key = name.toLowerCase();
    urlLoaderOptions.headers[key] = { name, value };
  }
  if (options.session) {
    // Weak check, but it should be enough to catch 99% of accidental misuses.
    if (options.session.constructor && options.session.constructor.name === 'Session') {
      urlLoaderOptions.session = options.session;
    } else {
      throw new TypeError('`session` should be an instance of the Session class');
    }
  } else if (options.partition) {
    if (typeof options.partition === 'string') {
      urlLoaderOptions.partition = options.partition;
    } else {
      throw new TypeError('`partition` should be a string');
    }
  }
  return urlLoaderOptions;
}