Skip to content

Commit

Permalink
fix: allow programmatic visits to go cross-origin (#410)
Browse files Browse the repository at this point in the history
* fix: allow visit to go cross-origin

* Extract locationIsVisitable

* Fix type

* Fix reference

* Add test

Co-authored-by: David Heinemeier Hansson <[email protected]>
  • Loading branch information
KonnorRogers and dhh authored Sep 28, 2021
1 parent 5982a67 commit acb003d
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 8 deletions.
8 changes: 6 additions & 2 deletions src/core/drive/navigator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Action, isAction } from "../types"
import { FetchMethod } from "../../http/fetch_request"
import { FetchResponse } from "../../http/fetch_response"
import { FormSubmission } from "./form_submission"
import { expandURL, getAnchor, getRequestURL, Locatable } from "../url"
import { expandURL, getAnchor, getRequestURL, Locatable, locationIsVisitable } from "../url"
import { Visit, VisitDelegate, VisitOptions } from "./visit"
import { PageSnapshot } from "./page_snapshot"

Expand All @@ -23,7 +23,11 @@ export class Navigator {

proposeVisit(location: URL, options: Partial<VisitOptions> = {}) {
if (this.delegate.allowsVisitingLocationWithAction(location, options.action)) {
this.delegate.visitProposedToLocation(location, options)
if (locationIsVisitable(location, this.view.snapshot.rootLocation)) {
this.delegate.visitProposedToLocation(location, options)
} else {
window.location.href = location.toString()
}
}
}

Expand Down
8 changes: 2 additions & 6 deletions src/core/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { FormSubmitObserver, FormSubmitObserverDelegate } from "../observers/for
import { FrameRedirector } from "./frames/frame_redirector"
import { History, HistoryDelegate } from "./drive/history"
import { LinkClickObserver, LinkClickObserverDelegate } from "../observers/link_click_observer"
import { expandURL, isPrefixedBy, isHTML, Locatable } from "./url"
import { expandURL, locationIsVisitable, Locatable } from "./url"
import { Navigator, NavigatorDelegate } from "./drive/navigator"
import { PageObserver, PageObserverDelegate } from "../observers/page_observer"
import { ScrollObserver } from "../observers/scroll_observer"
Expand Down Expand Up @@ -130,7 +130,7 @@ export class Session implements FormSubmitObserverDelegate, HistoryDelegate, Lin

willFollowLinkToLocation(link: Element, location: URL) {
return this.elementDriveEnabled(link)
&& this.locationIsVisitable(location)
&& locationIsVisitable(location, this.snapshot.rootLocation)
&& this.applicationAllowsFollowingLinkToLocation(link, location)
}

Expand Down Expand Up @@ -331,10 +331,6 @@ export class Session implements FormSubmitObserverDelegate, HistoryDelegate, Lin
return isAction(action) ? action : "advance"
}

locationIsVisitable(location: URL) {
return isPrefixedBy(location, this.snapshot.rootLocation) && isHTML(location)
}

get snapshot() {
return this.view.snapshot
}
Expand Down
4 changes: 4 additions & 0 deletions src/core/url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ export function isPrefixedBy(baseURL: URL, url: URL) {
return baseURL.href === expandURL(prefix).href || baseURL.href.startsWith(prefix)
}

export function locationIsVisitable(location: URL, rootLocation: URL) {
return isPrefixedBy(location, rootLocation) && isHTML(location)
}

export function getRequestURL(url: URL) {
const anchor = getAnchor(url)
return anchor != null
Expand Down
1 change: 1 addition & 0 deletions src/tests/fixtures/drive.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ <h1>Drive</h1>

<div>
<a id="drive_enabled" href="/src/tests/fixtures/drive.html">Drive enabled link</a>
<a id="drive_enabled_external" href="https://example.com">Drive enabled external link</a>
</div>

<div data-turbo="false">
Expand Down
8 changes: 8 additions & 0 deletions src/tests/functional/drive_tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ export class DriveTests extends TurboDriveTestCase {
this.assert.equal(await this.visitAction, "advance")
}

async "test drive to external link"() {
this.clickSelector("#drive_enabled_external")
await this.nextBody
this.assert.equal(
await this.remote.execute(() => window.location.href), "https://example.com/"
)
}

async "test drive enabled by default; click link inside data-turbo='false'"() {
this.clickSelector("#drive_disabled")
await this.nextBody
Expand Down

0 comments on commit acb003d

Please sign in to comment.