FIX: Clicking on a URL with a different url prefix did not work (#13349)

Before this fix if your forum was set up with a subfolder and you
clicked on a link to a different subfolder it would not work. For
example:

   subfolder: /cool
   link is: /about-us

Previously it would try to resolve /about-us as /cool/about-us. With
this fix it redirects to /about-us correctly.
This commit is contained in:
Robin Ward
2021-06-10 21:44:30 -04:00
committed by GitHub
parent ef906fa1da
commit 052c841550
5 changed files with 60 additions and 15 deletions

View File

@@ -1,6 +1,13 @@
let cdn, baseUrl, baseUri, baseUriMatcher; let cdn, baseUrl, baseUri, baseUriMatcher;
let S3BaseUrl, S3CDN; let S3BaseUrl, S3CDN;
export function getBaseURI() {
if (baseUri === undefined) {
setPrefix($('meta[name="discourse-base-uri"]').attr("content") || "");
}
return baseUri || "/";
}
export default function getURL(url) { export default function getURL(url) {
if (baseUri === undefined) { if (baseUri === undefined) {
setPrefix($('meta[name="discourse-base-uri"]').attr("content") || ""); setPrefix($('meta[name="discourse-base-uri"]').attr("content") || "");

View File

@@ -4,7 +4,7 @@ import { Promise } from "rsvp";
import User from "discourse/models/user"; import User from "discourse/models/user";
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
import bootbox from "bootbox"; import bootbox from "bootbox";
import getURL from "discourse-common/lib/get-url"; import getURL, { getBaseURI } from "discourse-common/lib/get-url";
import { isTesting } from "discourse-common/config/environment"; import { isTesting } from "discourse-common/config/environment";
import { later } from "@ember/runloop"; import { later } from "@ember/runloop";
import { selectedText } from "discourse/lib/utilities"; import { selectedText } from "discourse/lib/utilities";
@@ -71,7 +71,7 @@ export function openLinkInNewTab(link) {
} }
export default { export default {
trackClick(e, siteSettings) { trackClick(e, siteSettings, { returnPromise = false } = {}) {
// right clicks are not tracked // right clicks are not tracked
if (e.which === 3) { if (e.which === 3) {
return true; return true;
@@ -162,17 +162,20 @@ export default {
openLinkInNewTab($link[0]); openLinkInNewTab($link[0]);
} else { } else {
trackPromise.finally(() => { trackPromise.finally(() => {
if (DiscourseURL.isInternal(href)) { if (
DiscourseURL.isInternal(href) &&
href.indexOf(getBaseURI()) === 0
) {
DiscourseURL.routeTo(href); DiscourseURL.routeTo(href);
} else { } else {
DiscourseURL.redirectTo(href); DiscourseURL.redirectAbsolute(href);
} }
}); });
} }
return false; return returnPromise ? trackPromise : false;
} }
return true; return returnPromise ? trackPromise : true;
}, },
}; };

View File

@@ -9,6 +9,7 @@ import { defaultHomepage } from "discourse/lib/utilities";
import { isEmpty } from "@ember/utils"; import { isEmpty } from "@ember/utils";
import offsetCalculator from "discourse/lib/offset-calculator"; import offsetCalculator from "discourse/lib/offset-calculator";
import { setOwner } from "@ember/application"; import { setOwner } from "@ember/application";
import { isTesting } from "discourse-common/config/environment";
const rewrites = []; const rewrites = [];
export const TOPIC_URL_REGEXP = /\/t\/([^\/]+)\/(\d+)\/?(\d+)?/; export const TOPIC_URL_REGEXP = /\/t\/([^\/]+)\/(\d+)\/?(\d+)?/;
@@ -226,7 +227,7 @@ const DiscourseURL = EmberObject.extend({
} }
if (Session.currentProp("requiresRefresh")) { if (Session.currentProp("requiresRefresh")) {
return this.redirectTo(getURL(path)); return this.redirectTo(path);
} }
const pathname = path.replace(/(https?\:)?\/\/[^\/]+/, ""); const pathname = path.replace(/(https?\:)?\/\/[^\/]+/, "");
@@ -308,17 +309,20 @@ const DiscourseURL = EmberObject.extend({
rewrites.push({ regexp, replacement, opts: opts || {} }); rewrites.push({ regexp, replacement, opts: opts || {} });
}, },
redirectTo(url) { redirectAbsolute(url) {
window.location = getURL(url); // Redirects will kill a test runner
if (isTesting()) {
return true;
}
window.location = url;
return true; return true;
}, },
/** redirectTo(url) {
* Determines whether a URL is internal or not return this.redirectAbsolute(getURL(url));
* },
* @method isInternal
* @param {String} url // Determines whether a URL is internal or not
**/
isInternal(url) { isInternal(url) {
if (url && url.length) { if (url && url.length) {
if (url.indexOf("//") === 0) { if (url.indexOf("//") === 0) {

View File

@@ -26,6 +26,14 @@
-o-transition: none !important; -o-transition: none !important;
transition: none !important; transition: none !important;
} }
#qunit-fixture {
position: absolute;
top: -10000px;
left: -10000px;
width: 1000px;
height: 1000px;
}
</style> </style>
<script src="{{rootURL}}assets/test-i18n.js"></script> <script src="{{rootURL}}assets/test-i18n.js"></script>

View File

@@ -6,6 +6,7 @@ import User from "discourse/models/user";
import { later } from "@ember/runloop"; import { later } from "@ember/runloop";
import pretender from "discourse/tests/helpers/create-pretender"; import pretender from "discourse/tests/helpers/create-pretender";
import sinon from "sinon"; import sinon from "sinon";
import { setPrefix } from "discourse-common/lib/get-url";
const track = ClickTrack.trackClick; const track = ClickTrack.trackClick;
@@ -47,6 +48,8 @@ module("Unit | Utility | click-track", function (hooks) {
<a href="https://discuss.domain.com/t/welcome-to-meta-discourse-org/1/30">foo</a> <a href="https://discuss.domain.com/t/welcome-to-meta-discourse-org/1/30">foo</a>
<a href="https://google.com">bar</a> <a href="https://google.com">bar</a>
</aside> </aside>
<a class="prefix-url" href="/forum/thing">prefix link</a>
<a class="diff-prefix-url" href="/thing">diff prefix link</a>
</article> </article>
</div>` </div>`
); );
@@ -85,6 +88,26 @@ module("Unit | Utility | click-track", function (hooks) {
); );
}); });
test("routes to internal urls", async function (assert) {
setPrefix("/forum");
pretender.post("/clicks/track", () => [200, {}, ""]);
await track(generateClickEventOn(".prefix-url"), null, {
returnPromise: true,
});
assert.ok(DiscourseURL.routeTo.calledWith("/forum/thing"));
});
test("redirects to internal urls with a different prefix", async function (assert) {
setPrefix("/forum");
sinon.stub(DiscourseURL, "redirectAbsolute");
pretender.post("/clicks/track", () => [200, {}, ""]);
await track(generateClickEventOn(".diff-prefix-url"), null, {
returnPromise: true,
});
assert.ok(DiscourseURL.redirectAbsolute.calledWith("/thing"));
});
skip("tracks external URLs", async function (assert) { skip("tracks external URLs", async function (assert) {
assert.expect(2); assert.expect(2);