Skip to content

Commit

Permalink
Refactor hostname helper function (#1735)
Browse files Browse the repository at this point in the history
Related tiny-pilot/tinypilot-pro#1162
Resolves #771

This PR refactors the `futureLocation` function to
`app/static/js/hostname.js` and renames it to `determineFutureOrigin`.
This change is needed to allow the function to be reused by
tiny-pilot/tinypilot-pro#1169

This is mostly a non-functional change with the following caveats:
1. Name change
    * Before
        `futureLocation`
    * After
        `determineFutureOrigin`
3. Docstring change
    * Before

https://github.com/tiny-pilot/tinypilot/blob/34161c3c450f5bc3c99cffbd3cd0a778aaeed6dd/app/templates/custom-elements/change-hostname-dialog.html#L100-L107
    * After

https://github.com/tiny-pilot/tinypilot/blob/d889c24044a510a5ba91464ac229dcd3c08bd578/app/static/js/hostname.js#L1-L8
5. Added guard on `oldHostname` variable
    * Before

https://github.com/tiny-pilot/tinypilot/blob/34161c3c450f5bc3c99cffbd3cd0a778aaeed6dd/app/templates/custom-elements/change-hostname-dialog.html#L111
    * After

https://github.com/tiny-pilot/tinypilot/blob/d889c24044a510a5ba91464ac229dcd3c08bd578/app/static/js/hostname.js#L16
7. Added tests
*
[app/static/js/hostname.test.js](https://github.com/tiny-pilot/tinypilot/blob/d889c24044a510a5ba91464ac229dcd3c08bd578/app/static/js/hostname.test.js)

<a data-ca-tag
href="https://codeapprove.com/pr/tiny-pilot/tinypilot/1735"><img
src="https://codeapprove.com/external/github-tag-allbg.png" alt="Review
on CodeApprove" /></a>
  • Loading branch information
jdeanwallace authored Feb 6, 2024
1 parent 34161c3 commit dc9d8cc
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 29 deletions.
38 changes: 38 additions & 0 deletions app/static/js/hostname.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* Determines the new base URL (i.e., the origin of the URL, without the
* pathname or search parameters) of the TinyPilot device, given a new hostname.
*
* @example
* // returns 'https://new-hostname.local'
* determineFutureOrigin(
* new URL('https://old-hostname.local/some-path/'),
* 'old-hostname',
* 'new-hostname'
* );
*
* @param {URL} currentLocation
* @param {string} oldHostname
* @param {string} newHostname
* @returns {string}
*/
export function determineFutureOrigin(
currentLocation,
oldHostname,
newHostname
) {
const protocol = currentLocation.protocol + "//";
let fqdn = currentLocation.hostname;
if (oldHostname && fqdn.startsWith(oldHostname + ".")) {
// When the fqdn (fully qualified domain name) starts with the old
// hostname followed by a dot, then we replace the old one by the
// new one in order to preserve the domain part.
// E.g.: "oldtinypilot.home.local" => "newtinypilot.home.local"
fqdn = fqdn.replace(oldHostname, newHostname);
} else {
// Otherwise we just assume the new hostname to be a fully qualified
// one. That might not be correct, but it’s the best possible guess.
fqdn = newHostname;
}
const port = currentLocation.port === "" ? "" : `:${currentLocation.port}`;
return protocol + fqdn + port;
}
96 changes: 96 additions & 0 deletions app/static/js/hostname.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { determineFutureOrigin } from "./hostname.js";
import { describe, it } from "mocha";
import assert from "assert";

describe("determineFutureOrigin", () => {
it("returns origin by replacing old hostname with new hostname", () => {
assert.strictEqual(
determineFutureOrigin(
new URL("https://old-tinypilot/"),
"old-tinypilot",
"new-tinypilot"
),
"https://new-tinypilot"
);
assert.strictEqual(
determineFutureOrigin(
new URL("https://old-tinypilot.local/"),
"old-tinypilot",
"new-tinypilot"
),
"https://new-tinypilot.local"
);
assert.strictEqual(
determineFutureOrigin(
new URL("https://old-tinypilot.domain.local/"),
"old-tinypilot",
"new-tinypilot"
),
"https://new-tinypilot.domain.local"
);
});
it("returns origin using only new hostname", () => {
assert.strictEqual(
determineFutureOrigin(
new URL("https://old-tinypilot/"),
undefined,
"new-tinypilot"
),
"https://new-tinypilot"
);
assert.strictEqual(
determineFutureOrigin(
new URL("https://old-tinypilot.local/"),
undefined,
"new-tinypilot"
),
"https://new-tinypilot"
);
assert.strictEqual(
determineFutureOrigin(
new URL("https://old-tinypilot.domain.local/"),
undefined,
"new-tinypilot"
),
"https://new-tinypilot"
);
});
it("maintains port number", () => {
assert.strictEqual(
determineFutureOrigin(
new URL("https://old-tinypilot:8080/"),
"old-tinypilot",
"new-tinypilot"
),
"https://new-tinypilot:8080"
);
});
it("maintains protocol", () => {
assert.strictEqual(
determineFutureOrigin(
new URL("http://old-tinypilot/"),
"old-tinypilot",
"new-tinypilot"
),
"http://new-tinypilot"
);
assert.strictEqual(
determineFutureOrigin(
new URL("ftp://old-tinypilot/"),
"old-tinypilot",
"new-tinypilot"
),
"ftp://new-tinypilot"
);
});
it("strips pathname", () => {
assert.strictEqual(
determineFutureOrigin(
new URL("http://old-tinypilot/some-path/"),
"old-tinypilot",
"new-tinypilot"
),
"http://new-tinypilot"
);
});
});
32 changes: 3 additions & 29 deletions app/templates/custom-elements/change-hostname-dialog.html
Original file line number Diff line number Diff line change
Expand Up @@ -93,37 +93,11 @@ <h3>Changing Hostname</h3>
determineHostname,
shutdown,
} from "/js/controllers.js";
import { determineFutureOrigin } from "/js/hostname.js";

(function () {
const template = document.querySelector("#change-hostname-template");

/**
* Figure out the new URL under which TinyPilot will become
* available after rebooting.
* @param {Location} currentLocation
* @param {string} oldHostname
* @param {string} newHostname
* @returns {string}
*/
function futureLocation(currentLocation, oldHostname, newHostname) {
const protocol = currentLocation.protocol + "//";
let fqdn = currentLocation.hostname;
if (fqdn.startsWith(oldHostname + ".")) {
// When the fqdn (fully qualified domain name) starts with the old
// hostname followed by a dot, then we replace the old one by the
// new one in order to preserve the domain part.
// E.g.: "oldtinypilot.home.local" => "newtinypilot.home.local"
fqdn = fqdn.replace(oldHostname, newHostname);
} else {
// Otherwise we just assume the new hostname to be a fully qualified
// one. That might not be correct, but it’s the best possible guess.
fqdn = newHostname;
}
const port =
currentLocation.port === "" ? "" : `:${currentLocation.port}`;
return protocol + fqdn + port;
}

customElements.define(
"change-hostname-dialog",
class extends HTMLElement {
Expand Down Expand Up @@ -224,8 +198,8 @@ <h3>Changing Hostname</h3>
return shutdown(/*restart=*/ true).then(() => newHostname);
})
.then((newHostname) => {
return futureLocation(
window.location,
return determineFutureOrigin(
new URL(window.location),
this.initialHostname,
newHostname
);
Expand Down

0 comments on commit dc9d8cc

Please sign in to comment.