Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make web app use relative paths so that reverse proxying is more straightforward #1054

Open
mdsteveb opened this issue Mar 6, 2025 · 4 comments
Assignees

Comments

@mdsteveb
Copy link

mdsteveb commented Mar 6, 2025

Is your feature request related to a problem? Please describe.
It is very difficult to set up a reverse proxy for the web app. I had it working with mythweb without too much trouble, but it broke when mythweb went away. That said, I was able to get it working, but it's pretty ugly. I think with some refactoring of the web app this could be made much simpler.

The issue is that the web app seems to make the assumption that its URI path prefix is always / ... so if you are trying to put it behind a reverse proxy, it still needs a set of API paths hardcoded to a root prefix. I'm not 100% sure but I think it's javascript generating those paths on the fly, because no amount of response filtering with sub_filter seemed to solve the problem.

Describe the solution you'd like
Eliminate the hard URI path prefix requirement from the webapp. Make it use relative paths so that a reverse proxy can relocate it as needed.

Describe alternatives you've considered
The following is a set of nginx location stanzas that seem to work for me, after many hours of messing around with it. I don't claim that they're complete or correct, but in simple testing I haven't found anything yet that doesn't work. But you can see the workarounds I had to apply, with rewriting the hrefs and srcs in the response body, and in the end I had to actually accept set of fixed root-level URIs used by the web app because it appears those paths are generated in-browser and no amount of remapping on the proxy would fix them. (If I'm wrong please let me know!)

I was able to identify all the hardcoded paths by watching the errors in my browser's console log.

        ###
        ### For reverse proxying MythTV web app
        ###
        location /mythweb/ {
                auth_basic      "Restricted Content";
                auth_basic_user_file /etc/nginx/htpasswd-mythweb;
                proxy_set_header Host www.example.com;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_set_header Accept-Encoding "";
                proxy_pass      http://mythtv.localdomain:6544/;
                sub_filter      'mythtv:6544/' 'www.example.com/mythweb/';
                sub_filter      'mythtv.localdomain:6544/' 'www.example.com/mythweb/';
                sub_filter      'href="/' 'href="/mythweb/';
                sub_filter      'href="https://www.example.com/assets/' 'href="/mythweb/assets/';
                sub_filter      'href="assets/' 'href="/mythweb/assets/';
                sub_filter      'href="https://www.example.com/Config/' 'href="/mythweb/Config/';
                sub_filter      'href="Config/' 'href="/mythweb/Config/';
                sub_filter      'href="https://www.example.com/Myth/' 'href="/mythweb/Myth/';
                sub_filter      'href="Myth/' 'href="/mythweb/Myth/';
                sub_filter      'href="https://www.example.com/Status/' 'href="/mythweb/Status/';
                sub_filter      'href="Status/' 'href="/mythweb/Status/';
                sub_filter      'href="https://www.example.com/Capture/' 'href="/mythweb/Capture/';
                sub_filter      'href="Capture/' 'href="/mythweb/Capture/';
                sub_filter      'href="https://www.example.com/Guide/' 'href="/mythweb/Guide/';
                sub_filter      'href="Guide/' 'href="/mythweb/Guide/';
                sub_filter      'href="https://www.example.com/Dvr/' 'href="/mythweb/Dvr/';
                sub_filter      'href="Dvr/' 'href="/mythweb/Dvr/';
                sub_filter      'href="https://www.example.com/Video/' 'href="/mythweb/Video/';
                sub_filter      'href="Video/' 'href="/mythweb/Video/';
                sub_filter      'href="https://www.example.com/Channel/' 'href="/mythweb/Channel/';
                sub_filter      'href="Channel/' 'href="/mythweb/Channel/';
                sub_filter      '<script src="/' '<script src="/mythweb/';
                sub_filter      '<script src="' '<script src="/mythweb/';
                sub_filter_types text/css text/javascript;
                sub_filter_last_modified on;
                sub_filter_once off;
        }
        location ~ ^/(assets|Config|Myth|Status|Capture|Guide|Dvr|Video|Channel)/(.*) {
                auth_basic      "Restricted Content";
                auth_basic_user_file /etc/nginx/htpasswd-mythweb;
                proxy_set_header Host www.example.com;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_set_header Accept-Encoding "";
                proxy_pass      http://mythtv.localdomain:6544/$1/$2$is_args$args;
        }

Furthermore, I must be missing something, but I was unable to find a way to register a wiki account so I could post that info to the wiki, and the forum blocked me from posting it because of the apparent external URLs, even if I put them inside a nowiki block. I think this is good information for people to find but I would rather see the web app fixed to make this easier so that all these hardcoded path workarounds aren't necessary. However if this seems useful in the mean time, feel free to put it up somewhere.

@mdsteveb
Copy link
Author

mdsteveb commented Mar 6, 2025

I should add that another potential solution would be a way to configure the hard path prefixes generated by the scripts so that it could be made to at least match the proxy's prefix settings, if it's not possible to make it 100% relative paths.

@bennettpeter bennettpeter self-assigned this Mar 6, 2025
@bennettpeter
Copy link
Member

You are missing a few: /3rdParty /images /Content

As I see it, to use relative URLS I would have to change all URLs like /Capture/GetCaptureCardList to ../Capture/GetCaptureCardList assuming that all pages have a top URL of the form http://server:6544/something1/something2

@mdsteveb
Copy link
Author

mdsteveb commented Mar 7, 2025

Oh great, thanks for the missing endpoints, I'll add them to my config.

I'm honestly not sure what the best practice is for doing this, and I haven't looked at how you have the web app laid out, but I would think that if your base HTML page that loads the javascript is in the "root" of the web app (probably index.html or similar), you could then just generate URIs like ... href="Capture/GetCaptureCardList" ? Then the user's browser will tack on the "root" path (same as the html page's path). If the base page loading the scripts is in a subdirectory then it would become href="../Capture/GetCaptureCardList", etc. etc. Someone correct me if I'm off base here but I think that's how it works. If you can be consistent and avoid absolute paths throughout in all the href= and src= parameters, that ought to do it, no?

@bennettpeter
Copy link
Member

Yes, I think you are correct.

The app does not actually have directories with pages, the browser URLs are generated by javascript in a way that is not clear to me, so this needs to be tested. It will be either ../Capture/GetCaptureCardList or Capture/GetCaptureCardList.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants