From 163217dfcd28294438ea1c1c149cfaf66eec283e Mon Sep 17 00:00:00 2001
From: John Wesley Walker III <81404201+jww3@users.noreply.github.com>
Date: Fri, 18 Oct 2024 10:07:17 +0200
Subject: [PATCH] `url-helper.ts` now leverages well-known environment
 variables. (#1941)

* `utl-helper.ts` now leverages well-known environment variables.

---------
Co-authored-by: Erez Testiler <easyt@github.com>
---
 __test__/url-helper.test.ts | 55 ++++++++++++++++++++++++++++++++++
 dist/index.js               | 50 ++++++++++++++++++++++++-------
 src/url-helper.ts           | 59 +++++++++++++++++++++++++++++--------
 3 files changed, 141 insertions(+), 23 deletions(-)
 create mode 100644 __test__/url-helper.test.ts

diff --git a/__test__/url-helper.test.ts b/__test__/url-helper.test.ts
new file mode 100644
index 0000000..27f6606
--- /dev/null
+++ b/__test__/url-helper.test.ts
@@ -0,0 +1,55 @@
+import * as urlHelper from '../src/url-helper'
+
+describe('getServerUrl tests', () => {
+  it('basics', async () => {
+    // Note that URL::toString will append a trailing / when passed just a domain name ...
+    expect(urlHelper.getServerUrl().toString()).toBe('https://github.com/')
+    expect(urlHelper.getServerUrl(' ').toString()).toBe('https://github.com/')
+    expect(urlHelper.getServerUrl('   ').toString()).toBe('https://github.com/')
+    expect(urlHelper.getServerUrl('http://contoso.com').toString()).toBe(
+      'http://contoso.com/'
+    )
+    expect(urlHelper.getServerUrl('https://contoso.com').toString()).toBe(
+      'https://contoso.com/'
+    )
+    expect(urlHelper.getServerUrl('https://contoso.com/').toString()).toBe(
+      'https://contoso.com/'
+    )
+
+    // ... but can't make that same assumption when passed an URL that includes some deeper path.
+    expect(urlHelper.getServerUrl('https://contoso.com/a/b').toString()).toBe(
+      'https://contoso.com/a/b'
+    )
+  })
+})
+
+describe('isGhes tests', () => {
+  it('basics', async () => {
+    expect(urlHelper.isGhes()).toBeFalsy()
+    expect(urlHelper.isGhes('https://github.com')).toBeFalsy()
+    expect(urlHelper.isGhes('https://contoso.ghe.com')).toBeFalsy()
+    expect(urlHelper.isGhes('https://test.github.localhost')).toBeFalsy()
+    expect(urlHelper.isGhes('https://src.onpremise.fabrikam.com')).toBeTruthy()
+  })
+})
+
+describe('getServerApiUrl tests', () => {
+  it('basics', async () => {
+    expect(urlHelper.getServerApiUrl()).toBe('https://api.github.com')
+    expect(urlHelper.getServerApiUrl('https://github.com')).toBe(
+      'https://api.github.com'
+    )
+    expect(urlHelper.getServerApiUrl('https://GitHub.com')).toBe(
+      'https://api.github.com'
+    )
+    expect(urlHelper.getServerApiUrl('https://contoso.ghe.com')).toBe(
+      'https://api.contoso.ghe.com'
+    )
+    expect(urlHelper.getServerApiUrl('https://fabrikam.GHE.COM')).toBe(
+      'https://api.fabrikam.ghe.com'
+    )
+    expect(
+      urlHelper.getServerApiUrl('https://src.onpremise.fabrikam.com')
+    ).toBe('https://src.onpremise.fabrikam.com/api/v3')
+  })
+})
diff --git a/dist/index.js b/dist/index.js
index d86415e..b0db713 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -2454,22 +2454,50 @@ function getFetchUrl(settings) {
     return `${serviceUrl.origin}/${encodedOwner}/${encodedName}`;
 }
 function getServerUrl(url) {
-    let urlValue = url && url.trim().length > 0
-        ? url
-        : process.env['GITHUB_SERVER_URL'] || 'https://github.com';
-    return new url_1.URL(urlValue);
+    let resolvedUrl = process.env['GITHUB_SERVER_URL'] || 'https://github.com';
+    if (hasContent(url, WhitespaceMode.Trim)) {
+        resolvedUrl = url;
+    }
+    return new url_1.URL(resolvedUrl);
 }
 function getServerApiUrl(url) {
-    let apiUrl = 'https://api.github.com';
-    if (isGhes(url)) {
-        const serverUrl = getServerUrl(url);
-        apiUrl = new url_1.URL(`${serverUrl.origin}/api/v3`).toString();
+    if (hasContent(url, WhitespaceMode.Trim)) {
+        let serverUrl = getServerUrl(url);
+        if (isGhes(url)) {
+            serverUrl.pathname = 'api/v3';
+        }
+        else {
+            serverUrl.hostname = 'api.' + serverUrl.hostname;
+        }
+        return pruneSuffix(serverUrl.toString(), '/');
     }
-    return apiUrl;
+    return process.env['GITHUB_API_URL'] || 'https://api.github.com';
 }
 function isGhes(url) {
-    const ghUrl = getServerUrl(url);
-    return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM';
+    const ghUrl = new url_1.URL(url || process.env['GITHUB_SERVER_URL'] || 'https://github.com');
+    const hostname = ghUrl.hostname.trimEnd().toUpperCase();
+    const isGitHubHost = hostname === 'GITHUB.COM';
+    const isGitHubEnterpriseCloudHost = hostname.endsWith('.GHE.COM');
+    const isLocalHost = hostname.endsWith('.LOCALHOST');
+    return !isGitHubHost && !isGitHubEnterpriseCloudHost && !isLocalHost;
+}
+function pruneSuffix(text, suffix) {
+    if (hasContent(suffix, WhitespaceMode.Preserve) && (text === null || text === void 0 ? void 0 : text.endsWith(suffix))) {
+        return text.substring(0, text.length - suffix.length);
+    }
+    return text;
+}
+var WhitespaceMode;
+(function (WhitespaceMode) {
+    WhitespaceMode[WhitespaceMode["Trim"] = 0] = "Trim";
+    WhitespaceMode[WhitespaceMode["Preserve"] = 1] = "Preserve";
+})(WhitespaceMode || (WhitespaceMode = {}));
+function hasContent(text, whitespaceMode) {
+    let refinedText = text !== null && text !== void 0 ? text : '';
+    if (whitespaceMode == WhitespaceMode.Trim) {
+        refinedText = refinedText.trim();
+    }
+    return refinedText.length > 0;
 }
 
 
diff --git a/src/url-helper.ts b/src/url-helper.ts
index 64ecbf3..17a0842 100644
--- a/src/url-helper.ts
+++ b/src/url-helper.ts
@@ -21,26 +21,61 @@ export function getFetchUrl(settings: IGitSourceSettings): string {
 }
 
 export function getServerUrl(url?: string): URL {
-  let urlValue =
-    url && url.trim().length > 0
-      ? url
-      : process.env['GITHUB_SERVER_URL'] || 'https://github.com'
-  return new URL(urlValue)
+  let resolvedUrl = process.env['GITHUB_SERVER_URL'] || 'https://github.com'
+  if (hasContent(url, WhitespaceMode.Trim)) {
+    resolvedUrl = url!
+  }
+
+  return new URL(resolvedUrl)
 }
 
 export function getServerApiUrl(url?: string): string {
-  let apiUrl = 'https://api.github.com'
+  if (hasContent(url, WhitespaceMode.Trim)) {
+    let serverUrl = getServerUrl(url)
+    if (isGhes(url)) {
+      serverUrl.pathname = 'api/v3'
+    } else {
+      serverUrl.hostname = 'api.' + serverUrl.hostname
+    }
 
-  if (isGhes(url)) {
-    const serverUrl = getServerUrl(url)
-    apiUrl = new URL(`${serverUrl.origin}/api/v3`).toString()
+    return pruneSuffix(serverUrl.toString(), '/')
   }
 
-  return apiUrl
+  return process.env['GITHUB_API_URL'] || 'https://api.github.com'
 }
 
 export function isGhes(url?: string): boolean {
-  const ghUrl = getServerUrl(url)
+  const ghUrl = new URL(
+    url || process.env['GITHUB_SERVER_URL'] || 'https://github.com'
+  )
 
-  return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM'
+  const hostname = ghUrl.hostname.trimEnd().toUpperCase()
+  const isGitHubHost = hostname === 'GITHUB.COM'
+  const isGitHubEnterpriseCloudHost = hostname.endsWith('.GHE.COM')
+  const isLocalHost = hostname.endsWith('.LOCALHOST')
+
+  return !isGitHubHost && !isGitHubEnterpriseCloudHost && !isLocalHost
+}
+
+function pruneSuffix(text: string, suffix: string) {
+  if (hasContent(suffix, WhitespaceMode.Preserve) && text?.endsWith(suffix)) {
+    return text.substring(0, text.length - suffix.length)
+  }
+  return text
+}
+
+enum WhitespaceMode {
+  Trim,
+  Preserve
+}
+
+function hasContent(
+  text: string | undefined,
+  whitespaceMode: WhitespaceMode
+): boolean {
+  let refinedText = text ?? ''
+  if (whitespaceMode == WhitespaceMode.Trim) {
+    refinedText = refinedText.trim()
+  }
+  return refinedText.length > 0
 }