-
Notifications
You must be signed in to change notification settings - Fork 943
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Issue-1473: App Crash with Invalid scriptURL (#1476)
## Please verify the following: - [x] `yarn build-and-test:local` passes - [x] I have added tests for any new features, if relevant - [ ] `README.md` (or relevant documentation) has been updated with your changes ## Describe your PR Fixes #1473 where calling split on an invalid string throws a `TypeError`. In the event that the following line does not provide us with a valid URL: https://github.com/facebook/react-native/blob/b38f80aeb6ad986c64fd03f53b2e01a7990e1533/packages/react-native/React/CoreModules/RCTSourceCode.mm#L38 We should catch this and warn the user that we are falling back to the default host: ``` WARN getHost: "Invalid URL: null" for scriptURL - Falling back to localhost ``` ## How to Reproduce I was unable to reproduce this issue locally with my devices as it would not crash the application, but just throw the error. Due to the circumstances of the original issue and that applications configuration, this should allow that application to continue to boot. ## Additional Notes It is still possible to configure Reactotron with an invalid host. This will equally throw an error of `invalid url`. I'd like to create a new PR that allows the application to continue to function, keeps Reactotron is a disconnected state, and notifies the user.
- Loading branch information
Showing
4 changed files
with
106 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import { getHostFromUrl } from "./parseURL" | ||
|
||
describe("getHostFromUrl", () => { | ||
it("should throw when no host is found", () => { | ||
expect(() => { | ||
getHostFromUrl("") | ||
}).toThrow() | ||
}) | ||
|
||
it("should get host from URL without scheme", () => { | ||
Object.entries({ | ||
localhost: "localhost", | ||
"127.0.0.1": "127.0.0.1", | ||
"[::1]": "[::1]", | ||
}).forEach(([host, url]) => { | ||
expect(getHostFromUrl(url)).toEqual(host) | ||
}) | ||
expect(getHostFromUrl("localhost")).toEqual("localhost") | ||
expect(getHostFromUrl("127.0.0.1")).toEqual("127.0.0.1") | ||
}) | ||
|
||
it("should get the host from URL with http scheme", () => { | ||
Object.entries({ | ||
localhost: "http://localhost", | ||
"example.com": "http://example.com", | ||
}).forEach(([host, url]) => { | ||
expect(getHostFromUrl(url)).toEqual(host) | ||
}) | ||
}) | ||
|
||
it("should get the host from URL with https scheme", () => { | ||
Object.entries({ | ||
localhost: "https://localhost", | ||
"example.com": "https://example.com", | ||
}).forEach(([host, url]) => { | ||
expect(getHostFromUrl(url)).toEqual(host) | ||
}) | ||
}) | ||
|
||
it("should get the host from URL and ignore path, port, and query params", () => { | ||
Object.entries({ | ||
localhost: | ||
"http://localhost:8081/.expo/.virtual-metro-entry.bundle?platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&app=com.reactotronapp", | ||
"192.168.1.141": | ||
"https://192.168.1.141:8081/.expo/.virtual-metro-entry.bundle?platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&app=com.reactotronapp", | ||
}).forEach(([host, url]) => { | ||
expect(getHostFromUrl(url)).toEqual(host) | ||
}) | ||
}) | ||
|
||
it("should get the host from an IPv6 URL and ignore path, port, and query params", () => { | ||
Object.entries({ | ||
"[::1]": | ||
"http://[::1]:8081/.expo/.virtual-metro-entry.bundle?platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&app=com.reactotronapp", | ||
"[2001:0db8:85a3:0000:0000:8a2e:0370:7334]": | ||
"https://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:8081/.expo/.virtual-metro-entry.bundle?platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&app=com.reactotronapp", | ||
}).forEach(([host, url]) => { | ||
expect(getHostFromUrl(url)).toEqual(host) | ||
}) | ||
}) | ||
|
||
it("should get the host from URL with hyphens", () => { | ||
expect(getHostFromUrl("https://example-app.com")).toEqual("example-app.com") | ||
}) | ||
|
||
it("should throw when the URL is an unsupported scheme", () => { | ||
expect(() => { | ||
getHostFromUrl("file:///Users/tron") | ||
}).toThrow() | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/** | ||
* Given a valid http(s) URL, the host for the given URL | ||
* is returned. | ||
* | ||
* @param url {string} URL to extract the host from | ||
* @returns {string} host of given URL or throws | ||
*/ | ||
// Using a capture group to extract the hostname from a URL | ||
export function getHostFromUrl(url: string) { | ||
// Group 1: http(s):// | ||
// Group 2: host | ||
// Group 3: port | ||
// Group 4: rest | ||
const host = url.match(/^(?:https?:\/\/)?(\[[^\]]+\]|[^/:\s]+)(?::\d+)?(?:[/?#]|$)/)?.[1] | ||
|
||
if (typeof host !== "string") throw new Error("Invalid URL - host not found") | ||
|
||
return host | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters