xref: /expo/packages/@expo/cli/src/utils/url.ts (revision 023bc8ea)
1import dns from 'dns';
2import { URL } from 'url';
3
4import { fetchAsync } from '../api/rest/client';
5
6/** Check if a server is available based on the URL. */
7export function isUrlAvailableAsync(url: string): Promise<boolean> {
8  return new Promise<boolean>((resolve) => {
9    dns.lookup(url, (err) => {
10      resolve(!err);
11    });
12  });
13}
14
15/** Check if a request to the given URL is `ok` (status 200). */
16export async function isUrlOk(url: string): Promise<boolean> {
17  try {
18    const res = await fetchAsync(url);
19    return res.ok;
20  } catch {
21    return false;
22  }
23}
24
25/** Determine if a string is a valid URL, can optionally ensure certain protocols (like `https` or `exp`) are adhered to. */
26export function validateUrl(
27  urlString: string,
28  {
29    protocols,
30    requireProtocol,
31  }: {
32    /** Set of allowed protocols for the string to adhere to. @example ['exp', 'https'] */
33    protocols?: string[];
34    /** Ensure the URL has a protocol component (prefix before `://`). */
35    requireProtocol?: boolean;
36  } = {}
37) {
38  try {
39    const results = new URL(urlString);
40    if (!results.protocol && !requireProtocol) {
41      return true;
42    }
43    return protocols
44      ? results.protocol
45        ? protocols.map((x) => `${x.toLowerCase()}:`).includes(results.protocol)
46        : false
47      : true;
48  } catch {
49    return false;
50  }
51}
52
53/** Remove the port from a given `host` URL string. */
54export function stripPort(host?: string): string | null {
55  return coerceUrl(host)?.hostname ?? null;
56}
57
58function coerceUrl(urlString?: string): URL | null {
59  if (!urlString) {
60    return null;
61  }
62  try {
63    return new URL('/', urlString);
64  } catch (error: any) {
65    if (error.code !== 'ERR_INVALID_URL') {
66      throw error;
67    }
68    return new URL('/', `http://${urlString}`);
69  }
70}
71
72/** Strip a given extension from a URL string. */
73export function stripExtension(url: string, extension: string): string {
74  return url.replace(new RegExp(`.${extension}$`), '');
75}
76