From d8df51f20ebf018cf827512ec9c4f0cc95a25541 Mon Sep 17 00:00:00 2001
From: Sergei Zharinov <zharinov@users.noreply.github.com>
Date: Wed, 9 Dec 2020 16:05:31 +0400
Subject: [PATCH] feat(util): Add resolveBaseUrl function (#7918)

---
 lib/util/url.spec.ts | 48 ++++++++++++++++++++++++++++++++++++++++++++
 lib/util/url.ts      | 16 +++++++++++++++
 2 files changed, 64 insertions(+)
 create mode 100644 lib/util/url.spec.ts

diff --git a/lib/util/url.spec.ts b/lib/util/url.spec.ts
new file mode 100644
index 0000000000..925319b127
--- /dev/null
+++ b/lib/util/url.spec.ts
@@ -0,0 +1,48 @@
+import { resolveBaseUrl } from './url';
+
+describe('util/url', () => {
+  test.each([
+    ['http://foo.io', '', 'http://foo.io'],
+    ['http://foo.io/', '', 'http://foo.io'],
+    ['http://foo.io', '/', 'http://foo.io/'],
+    ['http://foo.io/', '/', 'http://foo.io/'],
+
+    ['http://foo.io', '/aaa', 'http://foo.io/aaa'],
+    ['http://foo.io', 'aaa', 'http://foo.io/aaa'],
+    ['http://foo.io/', '/aaa', 'http://foo.io/aaa'],
+    ['http://foo.io/', 'aaa', 'http://foo.io/aaa'],
+    ['http://foo.io', '/aaa/', 'http://foo.io/aaa/'],
+    ['http://foo.io', 'aaa/', 'http://foo.io/aaa/'],
+    ['http://foo.io/', '/aaa/', 'http://foo.io/aaa/'],
+    ['http://foo.io/', 'aaa/', 'http://foo.io/aaa/'],
+
+    ['http://foo.io/aaa', '/bbb', 'http://foo.io/aaa/bbb'],
+    ['http://foo.io/aaa', 'bbb', 'http://foo.io/aaa/bbb'],
+    ['http://foo.io/aaa/', '/bbb', 'http://foo.io/aaa/bbb'],
+    ['http://foo.io/aaa/', 'bbb', 'http://foo.io/aaa/bbb'],
+
+    ['http://foo.io/aaa', '/bbb/', 'http://foo.io/aaa/bbb/'],
+    ['http://foo.io/aaa', 'bbb/', 'http://foo.io/aaa/bbb/'],
+    ['http://foo.io/aaa/', '/bbb/', 'http://foo.io/aaa/bbb/'],
+    ['http://foo.io/aaa/', 'bbb/', 'http://foo.io/aaa/bbb/'],
+
+    ['http://foo.io', 'http://bar.io/bbb', 'http://bar.io/bbb'],
+    ['http://foo.io/', 'http://bar.io/bbb', 'http://bar.io/bbb'],
+    ['http://foo.io/aaa', 'http://bar.io/bbb', 'http://bar.io/bbb'],
+    ['http://foo.io/aaa/', 'http://bar.io/bbb', 'http://bar.io/bbb'],
+
+    ['http://foo.io', 'http://bar.io/bbb/', 'http://bar.io/bbb/'],
+    ['http://foo.io/', 'http://bar.io/bbb/', 'http://bar.io/bbb/'],
+    ['http://foo.io/aaa', 'http://bar.io/bbb/', 'http://bar.io/bbb/'],
+    ['http://foo.io/aaa/', 'http://bar.io/bbb/', 'http://bar.io/bbb/'],
+
+    ['http://foo.io', 'aaa?bbb=z', 'http://foo.io/aaa?bbb=z'],
+    ['http://foo.io', '/aaa?bbb=z', 'http://foo.io/aaa?bbb=z'],
+    ['http://foo.io/', 'aaa?bbb=z', 'http://foo.io/aaa?bbb=z'],
+    ['http://foo.io/', '/aaa?bbb=z', 'http://foo.io/aaa?bbb=z'],
+
+    ['http://foo.io', 'aaa/?bbb=z', 'http://foo.io/aaa?bbb=z'],
+  ])('%s + %s => %s', (baseUrl, x, result) => {
+    expect(resolveBaseUrl(baseUrl, x)).toBe(result);
+  });
+});
diff --git a/lib/util/url.ts b/lib/util/url.ts
index 347fbcd9ad..0ca0938426 100644
--- a/lib/util/url.ts
+++ b/lib/util/url.ts
@@ -1,3 +1,19 @@
+import urlJoin from 'url-join';
+
 export function ensureTrailingSlash(url: string): string {
   return url.replace(/\/?$/, '/');
 }
+
+export function resolveBaseUrl(baseUrl: string, input: string | URL): string {
+  const inputString = input.toString();
+
+  let host;
+  let pathname;
+  try {
+    ({ host, pathname } = new URL(inputString));
+  } catch (e) {
+    pathname = inputString;
+  }
+
+  return host ? inputString : urlJoin(baseUrl, pathname || '');
+}
-- 
GitLab