mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-06-05 13:38:27 +01:00
fix: improved server check
Included timeout, check url even if http is included, doc strings
This commit is contained in:
115
app/login.tsx
115
app/login.tsx
@@ -80,40 +80,92 @@ const Login: React.FC = () => {
|
|||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
async function checkUrl(url: string) {
|
|
||||||
// remove trailing / so we don't double add double / in my checker
|
|
||||||
if (url.endsWith("/")) {
|
|
||||||
url = url.slice(0, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if( await fetch("https://" + url + "/System/Info/Public", {mode: 'cors'}).then((response) => {
|
const [loadingServerCheck, setLoadingServerCheck] = useState<boolean>(false);
|
||||||
return response.status;
|
|
||||||
}).catch((error) => {
|
/**
|
||||||
console.log(error)
|
* Checks the availability and validity of a Jellyfin server URL.
|
||||||
}) === 200) {
|
*
|
||||||
return "https://"+url
|
* This function attempts to connect to a Jellyfin server using the provided URL.
|
||||||
} else if (await fetch("http://" + url + "/System/Info/Public", {mode: 'cors'}).then((response) => {
|
* It tries both HTTPS and HTTP protocols, with a timeout to handle long 404 responses.
|
||||||
return response.status;
|
*
|
||||||
}).catch((error) => {
|
* @param {string} url - The base URL of the Jellyfin server to check.
|
||||||
console.log(error)
|
* @returns {Promise<string | undefined>} A Promise that resolves to:
|
||||||
}) === 200) {
|
* - The full URL (including protocol) if a valid Jellyfin server is found.
|
||||||
return "http://"+url
|
* - undefined if no valid server is found at the given URL.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* - Sets loadingServerCheck state to true at the beginning and false at the end.
|
||||||
|
* - Logs errors and timeout information to the console.
|
||||||
|
*/
|
||||||
|
async function checkUrl(url: string) {
|
||||||
|
url = url.endsWith("/") ? url.slice(0, -1) : url;
|
||||||
|
setLoadingServerCheck(true);
|
||||||
|
|
||||||
|
const protocols = ["https://", "http://"];
|
||||||
|
const timeout = 2000; // 2 seconds timeout for long 404 responses
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (const protocol of protocols) {
|
||||||
|
const controller = new AbortController();
|
||||||
|
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${protocol}${url}/System/Info/Public`, {
|
||||||
|
mode: "cors",
|
||||||
|
signal: controller.signal,
|
||||||
|
});
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
if (response.ok) {
|
||||||
|
return `${protocol}${url}`;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
const error = e as Error;
|
||||||
|
if (error.name === "AbortError") {
|
||||||
|
console.log(`Request to ${protocol}${url} timed out`);
|
||||||
|
} else {
|
||||||
|
console.error(`Error checking ${protocol}${url}:`, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
} finally {
|
||||||
|
setLoadingServerCheck(false);
|
||||||
}
|
}
|
||||||
return undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the connection attempt to a Jellyfin server.
|
||||||
|
*
|
||||||
|
* This function trims the input URL, checks its validity using the `checkUrl` function,
|
||||||
|
* and sets the server address if a valid connection is established.
|
||||||
|
*
|
||||||
|
* @param {string} url - The URL of the Jellyfin server to connect to.
|
||||||
|
*
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* - Calls `checkUrl` to validate the server URL.
|
||||||
|
* - Shows an alert if the connection fails.
|
||||||
|
* - Sets the server address using `setServer` if the connection is successful.
|
||||||
|
*
|
||||||
|
*/
|
||||||
const handleConnect = async (url: string) => {
|
const handleConnect = async (url: string) => {
|
||||||
url = url.trim();
|
url = url.trim();
|
||||||
if (!url.startsWith("http")) {
|
|
||||||
const result = await checkUrl(url);
|
const result = await checkUrl(
|
||||||
if (result === undefined){
|
url.startsWith("http") ? new URL(url).host : url
|
||||||
Alert.alert("Invalid URL", "Please enter a valid URL");
|
);
|
||||||
return;
|
|
||||||
}
|
if (result === undefined) {
|
||||||
url = result;
|
Alert.alert(
|
||||||
|
"Connection failed",
|
||||||
|
"Could not connect to the server. Please check the URL and your network connection."
|
||||||
|
);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
console.log(url);
|
|
||||||
setServer({ address: url });
|
setServer({ address: result });
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleQuickConnect = async () => {
|
const handleQuickConnect = async () => {
|
||||||
@@ -150,7 +202,6 @@ const Login: React.FC = () => {
|
|||||||
color="black"
|
color="black"
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
removeServer();
|
removeServer();
|
||||||
setServerURL("");
|
|
||||||
}}
|
}}
|
||||||
justify="between"
|
justify="between"
|
||||||
iconLeft={
|
iconLeft={
|
||||||
@@ -248,7 +299,12 @@ const Login: React.FC = () => {
|
|||||||
maxLength={500}
|
maxLength={500}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
<Button onPress={ async () => await handleConnect(serverURL)} className="mb-2">
|
<Button
|
||||||
|
loading={loadingServerCheck}
|
||||||
|
disabled={loadingServerCheck}
|
||||||
|
onPress={async () => await handleConnect(serverURL)}
|
||||||
|
className="mb-2"
|
||||||
|
>
|
||||||
Connect
|
Connect
|
||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
@@ -258,4 +314,3 @@ const Login: React.FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default Login;
|
export default Login;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user