Added multiple webui endpoints to ensure reachability

- Added Multiple webui endpoints
- g_webuiUrls functions as priority list, index 0 highest priority
- Status is checked in separate thread after webview initialization
This commit is contained in:
Zarg 2025-01-31 20:33:32 +01:00
parent a6438d97b9
commit 26ca7c6368
8 changed files with 110 additions and 5 deletions

View file

@ -62,6 +62,7 @@ target_link_libraries(${PROJECT_NAME} PRIVATE
dwmapi.lib
Shcore.lib
Msimg32.lib
winhttp.lib
nlohmann_json::nlohmann_json
unofficial::webview2::webview2
OpenSSL::SSL

View file

@ -10,7 +10,11 @@ HBRUSH g_darkBrush = nullptr;
HANDLE g_hMutex = nullptr;
HHOOK g_hMouseHook = nullptr;
std::wstring g_webuiUrl = L"https://stremio.zarg.me/";
std::vector<std::wstring> g_webuiUrls = {
L"https://stremio.zarg.me/",
L"https://zaarrg.github.io/stremio-web-shell-fixes/",
L"https://web.stremio.com/"
};
std::string g_updateUrl= "https://raw.githubusercontent.com/Zaarrg/stremio-desktop-v5/refs/heads/webview-windows/version/version.json";
// Command-line args

View file

@ -41,7 +41,7 @@ extern HBRUSH g_darkBrush;
extern HANDLE g_hMutex;
extern HHOOK g_hMouseHook;
extern std::wstring g_webuiUrl;
extern std::vector<std::wstring> g_webuiUrls;
extern std::string g_updateUrl;
// Args
@ -123,6 +123,7 @@ extern ULONG_PTR g_gdiplusToken;
// App Ready and Event Queue
#define WM_NOTIFY_FLUSH (WM_USER + 101)
#define WM_REACHABILITY_DONE (WM_USER + 200)
extern std::vector<nlohmann::json> g_outboundMessages;
extern std::wstring g_launchProtocol;
extern std::atomic<bool> g_isAppReady;

View file

@ -50,7 +50,7 @@ int main(int argc, char* argv[])
for(int i=1; i<argc; i++){
std::string arg(argv[i]);
if(arg.rfind("--webui-url=", 0)==0){
g_webuiUrl = Utf8ToWstring(arg.substr(12));
g_webuiUrls.insert(g_webuiUrls.begin(), Utf8ToWstring(arg.substr(12)));
} else if(arg.rfind("--autoupdater-endpoint=",0)==0){
g_updateUrl = arg.substr(23);
} else if(arg=="--streaming-server-disabled"){

View file

@ -351,6 +351,27 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
}
break;
}
case WM_REACHABILITY_DONE: {
// wParam is a pointer to a std::wstring we allocated in the thread
std::wstring* pUrl = reinterpret_cast<std::wstring*>(wParam);
if(pUrl)
{
if (!pUrl->empty() && g_webview)
{
std::wcout << L"[WEBVIEW]: Navigating to " << *pUrl << std::endl;
g_webview->Navigate(pUrl->c_str());
}
else
{
MessageBoxW(nullptr,
L"All endpoints are unreachable",
L"WebView2 Initialization Error",
MB_ICONERROR | MB_OK);
}
delete pUrl;
}
break;
}
case WM_SETTINGCHANGE:
{
UpdateTheme(hWnd);

View file

@ -1,5 +1,6 @@
#include "helpers.h"
#include <tlhelp32.h>
#include <winhttp.h>
#include "../core/globals.h"
std::string WStringToUtf8(const std::wstring &wstr)
@ -116,4 +117,76 @@ bool isSubtitle(const std::wstring& filePath) {
std::transform(lowerFilePath.begin(), lowerFilePath.end(), lowerFilePath.begin(), towlower);
return std::any_of(g_subtitleExtensions.begin(), g_subtitleExtensions.end(),
[&](const std::wstring& ext) { return lowerFilePath.ends_with(ext); });
}
bool IsEndpointReachable(const std::wstring& url) {
HINTERNET hSession = WinHttpOpen(L"Reachability Check",
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, NULL, NULL, 0);
if (!hSession) return false;
// Set timeouts
WinHttpSetTimeouts(hSession, 3000, 3000, 3000, 3000);
URL_COMPONENTS urlComp = { sizeof(URL_COMPONENTS) };
urlComp.dwHostNameLength = (DWORD)-1;
urlComp.dwUrlPathLength = (DWORD)-1;
urlComp.dwSchemeLength = (DWORD)-1;
if (!WinHttpCrackUrl(url.c_str(), (DWORD)url.length(), 0, &urlComp)) {
WinHttpCloseHandle(hSession);
return false;
}
std::wstring host(urlComp.lpszHostName, urlComp.dwHostNameLength);
std::wstring path(urlComp.lpszUrlPath, urlComp.dwUrlPathLength);
INTERNET_PORT port = urlComp.nPort;
bool useSSL = (urlComp.nScheme == INTERNET_SCHEME_HTTPS);
HINTERNET hConnect = WinHttpConnect(hSession, host.c_str(), port, 0);
if (!hConnect) {
WinHttpCloseHandle(hSession);
return false;
}
HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"HEAD", path.c_str(),
NULL, NULL, NULL, useSSL ? WINHTTP_FLAG_SECURE : 0);
if (!hRequest) {
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
return false;
}
BOOL sent = WinHttpSendRequest(hRequest, NULL, 0, NULL, 0, 0, 0);
if (!sent) {
WinHttpCloseHandle(hRequest);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
return false;
}
BOOL received = WinHttpReceiveResponse(hRequest, NULL);
DWORD statusCode = 0;
DWORD statusSize = sizeof(statusCode);
if (received) {
WinHttpQueryHeaders(hRequest,
WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
NULL, &statusCode, &statusSize, NULL);
}
WinHttpCloseHandle(hRequest);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
return received && (statusCode >= 200 && statusCode < 300);
}
std::wstring GetFirstReachableUrl() {
for (const auto& url : g_webuiUrls) {
if (IsEndpointReachable(url)) {
return url;
}
}
// Fallback to first URL or handle error
return g_webuiUrls.empty() ? L"" : g_webuiUrls[0];
}

View file

@ -10,6 +10,7 @@ std::string WStringToUtf8(const std::wstring &wstr);
std::wstring Utf8ToWstring(const std::string& utf8Str);
std::string decodeURIComponent(const std::string& encoded);
std::wstring GetExeDirectory();
std::wstring GetFirstReachableUrl();
bool FileExists(const std::wstring& path);
bool DirectoryExists(const std::wstring& dirPath);
bool IsDuplicateProcessRunning(const std::vector<std::wstring>& targetProcesses);

View file

@ -218,8 +218,12 @@ void InitWebView2(HWND hWnd)
SetupExtensions();
SetupWebMessageHandler();
std::wcout << L"[WEBVIEW]: Navigating to " << g_webuiUrl << std::endl;
g_webview->Navigate(g_webuiUrl.c_str());
std::thread([](){
std::wcout << L"[WEBVIEW]: Checking web ui endpoints..." << std::endl;
std::wstring foundUrl = GetFirstReachableUrl();
std::wstring* pResult = new std::wstring(foundUrl);
PostMessage(g_hWnd, WM_REACHABILITY_DONE, (WPARAM)pResult, 0);
}).detach();
return S_OK;
}).Get()
);