jellyfin / jellyfin-web

Web Client for Jellyfin
https://jellyfin.org
GNU General Public License v2.0
2.38k stars 1.27k forks source link

Plugin Config Pages Do Not Load (when using Webpack dev server) #851

Closed mark-monteiro closed 1 year ago

mark-monteiro commented 4 years ago

Describe the bug The page router does not use the correct URL when requesting the config page for a plugin, so the config pages cannot be loaded correctly.

To Reproduce

  1. Run Jellyfin server locally with Visual Studio (on master). This runs on port 8096 by default.
  2. Run jellyfin-web development server (runs on port 8080 by default) and connect to the back-end that is running from step 1.
  3. Install a plugin that has a configuration page (I have tested this with both the LDAP and Auto-Organize plugins)
  4. Attempt to navigate to the configuration page for the plugin

Expected behavior The configuration page HTML should be requested from the correct URL, but the wrong URL is used, which returns a 404 and the config page does not load.

expected URL (see screenshot below): http://localhost:8096/web/configurationpage?name=AutoOrganizeLog&v=24 actual URL used (see screenshot below): http://localhost:8080//configurationpage?name=AutoOrganizeLog&v=24

Note that the /web/ segment of the URL is missing. The webpack dev server port 8080 is also used instead of the backend server port 8096.

Screenshots The Expected URL Loads the HTML content correctly: image

The actual URL used returns a 404 image

System (please complete the following information):

Logs [WDS] Live Reloading enabled. client:52:9 [WDS] Live Reloading enabled. client:52:9 Begin ConnectionManager constructor connectionmanager.js:461:17 initAfterDependencies promises resolved site.js:484:25 app is hidden apphost.js:205:21 Using default fonts site.js:531:21 Loading installed plugins site.js:543:17 Loading plugin: components/playback/playaccessvalidation pluginManager.js:30:17 Loading plugin: components/playback/experimentalwarnings pluginManager.js:30:17 Loading plugin: components/htmlaudioplayer/plugin pluginManager.js:30:17 Loading plugin: components/htmlvideoplayer/plugin pluginManager.js:30:17 Loading plugin: components/photoplayer/plugin pluginManager.js:30:17 Loading plugin: components/youtubeplayer/plugin pluginManager.js:30:17 Loading plugin: components/backdropscreensaver/plugin pluginManager.js:30:17 Loading plugin: components/logoscreensaver/plugin pluginManager.js:30:17 Loading plugin: components/sessionplayer pluginManager.js:30:17 Setting page base to appRouter.js:675:17 keyboardnavigation keyboardnavigation.js:4:13 credentials initialized with: {"Servers":[{"ManualAddress":"http://localhost:8096","LastConnectionMode":2,"Name":"LAPTOP-CH36N487","Id":"bc9dca72e586406b8486a126f11f34a7","LocalAddress":"http://192.168.1.152:8096","DateLastAccessed":1582573822863,"UserId":"d1f09be462d74ef1a5391c0c31b5649c","AccessToken":"6c107671e7b84185bc5375bf3df103a2"}]} credentialprovider.js:7:21 ApiClient serverAddress: http://localhost:8096 apiclientcore.js:63:17 ApiClient appName: Jellyfin Web apiclientcore.js:63:75 ApiClient appVersion: 10.5.0 apiclientcore.js:63:121 ApiClient deviceName: Firefox apiclientcore.js:63:173 ApiClient deviceId: TW96aWxsYS81LjAgKFdpbmRvd3MgTlQgMTAuMDsgV2luNjQ7IHg2NDsgcnY6NzQuMCkgR2Vja28vMjAxMDAxMDEgRmlyZWZveC83NC4wfDE1ODI1NzM4MDgzMTQ1 apiclientcore.js:63:225 returning instance from getOrAddApiClient connectionmanager.js:553:21 Begin onAppReady site.js:585:17 onAppReady - loading dependencies site.js:591:21 defining core routes routes.js:24:13 defining route: /addplugin.html routes.js:19:17 defining route: /mypreferencesmenu.html routes.js:19:17 defining route: /myprofile.html routes.js:19:17 defining route: /addserver.html routes.js:19:17 defining route: /mypreferencesdisplay.html routes.js:19:17 defining route: /mypreferenceshome.html routes.js:19:17 defining route: /mypreferencesplayback.html routes.js:19:17 defining route: /mypreferencessubtitles.html routes.js:19:17 defining route: /dashboard.html routes.js:19:17 defining route: /dashboardgeneral.html routes.js:19:17 defining route: /networking.html routes.js:19:17 defining route: /devices.html routes.js:19:17 defining route: /device.html routes.js:19:17 defining route: /dlnaprofile.html routes.js:19:17 defining route: /dlnaprofiles.html routes.js:19:17 defining route: /dlnasettings.html routes.js:19:17 defining route: /edititemmetadata.html routes.js:19:17 defining route: /encodingsettings.html routes.js:19:17 defining route: /forgotpassword.html routes.js:19:17 defining route: /forgotpasswordpin.html routes.js:19:17 defining route: /home.html routes.js:19:17 defining route: /list.html routes.js:19:17 defining route: /index.html routes.js:19:17 defining route: /itemdetails.html routes.js:19:17 defining route: /library.html routes.js:19:17 defining route: /librarydisplay.html routes.js:19:17 defining route: /librarysettings.html routes.js:19:17 defining route: /livetv.html routes.js:19:17 defining route: /livetvguideprovider.html routes.js:19:17 defining route: /livetvsettings.html routes.js:19:17 defining route: /livetvstatus.html routes.js:19:17 defining route: /livetvtuner.html routes.js:19:17 defining route: /log.html routes.js:19:17 defining route: /login.html routes.js:19:17 defining route: /metadataimages.html routes.js:19:17 defining route: /metadatanfo.html routes.js:19:17 defining route: /movies.html routes.js:19:17 defining route: /music.html routes.js:19:17 defining route: /notificationsetting.html routes.js:19:17 defining route: /notificationsettings.html routes.js:19:17 defining route: /nowplaying.html routes.js:19:17 defining route: /playbackconfiguration.html routes.js:19:17 defining route: /availableplugins.html routes.js:19:17 defining route: /installedplugins.html routes.js:19:17 defining route: /scheduledtask.html routes.js:19:17 defining route: /scheduledtasks.html routes.js:19:17 defining route: /search.html routes.js:19:17 defining route: /selectserver.html routes.js:19:17 defining route: /serveractivity.html routes.js:19:17 defining route: /apikeys.html routes.js:19:17 defining route: /streamingsettings.html routes.js:19:17 defining route: /tv.html routes.js:19:17 defining route: /useredit.html routes.js:19:17 defining route: /userlibraryaccess.html routes.js:19:17 defining route: /usernew.html routes.js:19:17 defining route: /userparentalcontrol.html routes.js:19:17 defining route: /userpassword.html routes.js:19:17 defining route: /userprofiles.html routes.js:19:17 defining route: /wizardremoteaccess.html routes.js:19:17 defining route: /wizardfinish.html routes.js:19:17 defining route: /wizardlibrary.html routes.js:19:17 defining route: /wizardsettings.html routes.js:19:17 defining route: /wizardstart.html routes.js:19:17 defining route: /wizarduser.html routes.js:19:17 defining route: /videoosd.html routes.js:19:17 defining route: /configurationpage routes.js:19:17 defining route: / routes.js:19:17 returning instance from getOrAddApiClient connectionmanager.js:553:21 Begin connect connectionmanager.js:744:17 Begin getAvailableServers connectionmanager.js:631:21 Begin connectToServers, with 1 servers connectionmanager.js:647:21 begin connectToServer connectionmanager.js:668:21 tryReconnect: http://192.168.1.152:8096|http://localhost:8096 connectionmanager.js:394:21 getTryConnectPromise http://192.168.1.152:8096 connectionmanager.js:336:21 ConnectionManager requesting url: http://192.168.1.152:8096/system/info/public connectionmanager.js:121:17 fetchWithTimeout: timeoutMs: 20000, url: http://192.168.1.152:8096/system/info/public connectionmanager.js:98:17 fetchWithTimeout: succeeded connecting to url: http://192.168.1.152:8096/system/info/public connectionmanager.js:105:25 ConnectionManager response status: 200, url: http://192.168.1.152:8096/system/info/public connectionmanager.js:123:21 getTryConnectPromise http://localhost:8096 connectionmanager.js:336:21 ConnectionManager requesting url: http://localhost:8096/system/info/public connectionmanager.js:121:17 fetchWithTimeout: timeoutMs: 20000, url: http://localhost:8096/system/info/public connectionmanager.js:98:17 Reconnect succeeded to http://192.168.1.152:8096 connectionmanager.js:345:29 ConnectionManager requesting url: http://192.168.1.152:8096/System/Info connectionmanager.js:121:17 fetchWithTimeout: succeeded connecting to url: http://localhost:8096/system/info/public connectionmanager.js:105:25 ConnectionManager response status: 200, url: http://localhost:8096/system/info/public connectionmanager.js:123:21 ConnectionManager response status: 200, url: http://192.168.1.152:8096/System/Info connectionmanager.js:123:21 returning instance from getOrAddApiClient connectionmanager.js:553:21 Setting server address to http://192.168.1.152:8096 apiclientcore.js:390:17 Requesting url without automatic networking: http://192.168.1.152:8096/Sessions/Capabilities/Full apiclientcore.js:264:21 calling apiClient.ensureWebSocket connectionmanager.js:230:25 opening web socket with url: ws://192.168.1.152:8096/socket?api_key=6c107671e7b84185bc5375bf3df103a2&deviceId=TW96aWxsYS81LjAgKFdpbmRvd3MgTlQgMTAuMDsgV2luNjQ7IHg2NDsgcnY6NzQuMCkgR2Vja28vMjAxMDAxMDEgRmlyZWZveC83NC4wfDE1ODI1NzM4MDgzMTQ1 apiclientcore.js:351:225 Requesting http://192.168.1.152:8096/Users/d1f09be462d74ef1a5391c0c31b5649c apiclientcore.js:247:17 returning instance from getOrAddApiClient connectionmanager.js:553:21 Requesting http://192.168.1.152:8096/DisplayPreferences/usersettings?userId=d1f09be462d74ef1a5391c0c31b5649c&client=emby apiclientcore.js:247:17 web socket connection opened apiclientcore.js:142:17 resolving connectToServers with result.State: SignedIn connectionmanager.js:656:29 appRouter - processing path request /installedplugins.html appRouter.js:390:17 appRouter - user is authenticated appRouter.js:411:21 Requesting http://192.168.1.152:8096/web/configurationpages?pageType=PluginConfiguration&EnableInMainMenu=true apiclientcore.js:247:17 Requesting http://192.168.1.152:8096/Plugins apiclientcore.js:247:17 Requesting http://192.168.1.152:8096/web/configurationpages?pageType=PluginConfiguration apiclientcore.js:247:17 Requesting http://192.168.1.152:8096/System/Endpoint apiclientcore.js:247:17 triggering app resume event apphost.js:197:21 appRouter - processing path request /configurationpage appRouter.js:390:17 appRouter - user is authenticated appRouter.js:411:21 RequireJS error: TypeError: view is undefined. Failed modules: site.js:396:17 TypeError: view is undefined viewContainer.js:73:21 app is hidden apphost.js:205:21

mark-monteiro commented 4 years ago

Upon further testing, the config pages load correctly if I use yarn build and then copy the front-end build output to be hosted by the back-end Jellyfin server. Is it a supported scenario to host the front-end web client separately from the back-end server?

dkanada commented 4 years ago

@mark-monteiro I really want to make that work but haven't had the time yet. Basically, we need to make a few minor changes to the server to ignore any web requests when the fronend isn't bundled as well.

mark-monteiro commented 4 years ago

@dkanada Right, well even after those changes are made server-side I think there will still need to be additional changes to make the routing for the plugin config pages work correctly. I've looked at this a bit more and here's what I found:

The plugin config pages are loaded in the client using require() instead of a call to the API (I guess for convenience so they load in the same way as all the other HTML pages). Obviously this works when the backend server is hosting everything because the call to require() sends a request for the content to the backend server, as required (the route in the backend server is defined as /web/ConfigurationPage). But when running a standalone Webpack dev server, the request goes to the webpack dev server instead of the backend server and returns a 404.

I can think of two options to address this:

  1. Load the plugin config pages using a direct call to the API instead of using require() so that the request goes to the back-end server correctly.
  2. Continue to use require() but add a flag or something to the URL that indicates the request should go to the back-end server instead of using the base url of the site. Perhaps the handling of this flag could go into requiretext.js?

Only my second day looking at the codebase for jellyfin-web so take everything here with a grain of salt I'm probably missing some context 😅

JustAMan commented 4 years ago

cc @MrTimscampi

stale[bot] commented 4 years ago

Issues go stale after 90d of inactivity. Mark the issue as fresh by adding a comment or commit. Stale issues close after an additional 14d of inactivity. If this issue is safe to close now please do so. If you have any questions you can reach us on Matrix or Social Media.

thornbill commented 1 year ago

This appears to have been fixed at some point...

kimboslice99 commented 9 months ago

This appears to have been fixed at some point...

Are you sure? I'm seeing this exact issue on the production build

Should I open a new issue?

kevincox commented 5 months ago

I have the same issue. The frontend is making a request for /web/configurationpages?pageType=PluginConfiguration but this configurationpages file doesn't exist in the fontend. It raises a 404 and the loader spins forever (another bug).

thornbill commented 5 months ago

This issue is only relevant if you are running developing the web project and running the npm start script. If you are not, then it is not the same issue.