diff --git a/app/Http/Request.php b/app/Http/Request.php
index c5b38f1c1..13892603d 100644
--- a/app/Http/Request.php
+++ b/app/Http/Request.php
@@ -8,20 +8,36 @@ class Request extends LaravelRequest
 {
     /**
      * Override the default request methods to get the scheme and host
-     * to set the custom APP_URL, if set.
+     * to directly use the custom APP_URL, if set.
      *
-     * @return \Illuminate\Config\Repository|mixed|string
+     * @return string
      */
     public function getSchemeAndHttpHost()
     {
-        $base = config('app.url', null);
+        $appUrl = config('app.url', null);
 
-        if ($base) {
-            $base = trim($base, '/');
-        } else {
-            $base = $this->getScheme() . '://' . $this->getHttpHost();
+        if ($appUrl) {
+            return implode('/', array_slice(explode('/', $appUrl), 0, 3));
         }
 
-        return $base;
+        return parent::getSchemeAndHttpHost();
+    }
+
+    /**
+     * Override the default request methods to get the base URL
+     * to directly use the custom APP_URL, if set.
+     * The base URL never ends with a / but should start with one if not empty.
+     *
+     * @return string
+     */
+    public function getBaseUrl()
+    {
+        $appUrl = config('app.url', null);
+
+        if ($appUrl) {
+            return '/' . rtrim(implode('/', array_slice(explode('/', $appUrl), 3)), '/');
+        }
+
+        return parent::getBaseUrl();
     }
 }
diff --git a/tests/Unit/UrlTest.php b/tests/Unit/UrlTest.php
deleted file mode 100644
index fff5414f2..000000000
--- a/tests/Unit/UrlTest.php
+++ /dev/null
@@ -1,22 +0,0 @@
-<?php
-
-namespace Tests\Unit;
-
-use Tests\TestCase;
-
-class UrlTest extends TestCase
-{
-    public function test_url_helper_takes_custom_url_into_account()
-    {
-        $this->runWithEnv('APP_URL', 'http://example.com/bookstack', function () {
-            $this->assertEquals('http://example.com/bookstack/books', url('/books'));
-        });
-    }
-
-    public function test_url_helper_sets_correct_scheme_even_when_request_scheme_is_different()
-    {
-        $this->runWithEnv('APP_URL', 'https://example.com/', function () {
-            $this->get('http://example.com/login')->assertSee('https://example.com/dist/styles.css');
-        });
-    }
-}
diff --git a/tests/UrlTest.php b/tests/UrlTest.php
new file mode 100644
index 000000000..b9f1acf4b
--- /dev/null
+++ b/tests/UrlTest.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace Tests;
+
+use BookStack\Http\Request;
+use function url;
+use function request;
+
+class UrlTest extends TestCase
+{
+    public function test_url_helper_takes_custom_url_into_account()
+    {
+        $this->runWithEnv('APP_URL', 'http://example.com/bookstack', function () {
+            $this->assertEquals('http://example.com/bookstack/books', url('/books'));
+        });
+    }
+
+    public function test_url_helper_sets_correct_scheme_even_when_request_scheme_is_different()
+    {
+        $this->runWithEnv('APP_URL', 'https://example.com/', function () {
+            $this->get('http://example.com/login')->assertSee('https://example.com/dist/styles.css');
+        });
+    }
+
+    public function test_app_url_forces_overrides_on_base_request()
+    {
+        config()->set('app.url', 'https://donkey.example.com:8091/cool/docs');
+
+        // Have to manually get and wrap request in our custom type due to testing mechanics
+        $this->get('/login');
+        $bsRequest = Request::createFrom(request());
+
+        $this->assertEquals('https://donkey.example.com:8091', $bsRequest->getSchemeAndHttpHost());
+        $this->assertEquals('/cool/docs', $bsRequest->getBaseUrl());
+        $this->assertEquals('https://donkey.example.com:8091/cool/docs/login', $bsRequest->getUri());
+    }
+}