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

[Feature Request] Need baseURL for reverse proxy support #97

Open
1 task done
ddimick opened this issue May 21, 2022 · 45 comments
Open
1 task done

[Feature Request] Need baseURL for reverse proxy support #97

ddimick opened this issue May 21, 2022 · 45 comments
Labels
enhancement New feature or request

Comments

@ddimick
Copy link

ddimick commented May 21, 2022

Description

We need a baseURL setting (like Radarr and Sonarr have).

Desired Behavior

Allow Jellyseerr to run on https://my.url.com/jellyseerr/.

Additional Context

No response

Code of Conduct

  • I agree to follow Overseerr's Code of Conduct
@ddimick
Copy link
Author

ddimick commented May 21, 2022

Looks like there was a failed attempt to implement in sct/overseerr#2383.

@Fallenbagel Fallenbagel added the enhancement New feature or request label May 22, 2022
@Fallenbagel Fallenbagel changed the title Need baseURL for reverse proxy support [Feature Request] Need baseURL for reverse proxy support May 29, 2022
@danshilm
Copy link
Contributor

I wouldn't say failed really. It's just more hacky than we'd like since Next.js doesn't allow for changing the base URL after build time. But the PR worked just fine for as long as I was testing it.

There's a preview image for it if you guys wanna try it out (one image was accidentally made, so it's either this one or this one)

@Fallenbagel
Copy link
Owner

Hm someone on discord said they got baseurl working with swag

@Fallenbagel
Copy link
Owner

@ddimick I have the detailed instructions on how to get it to work as well if needed

@M-MDev
Copy link

M-MDev commented Sep 1, 2022

@Fallenbagel please post instructions for the baseurl mod

@Fallenbagel
Copy link
Owner

Fallenbagel commented Sep 1, 2022

So here's my conf. Mind you, this is just how I got it working, but there's other things you could fix if you wanted to, in my case, they are not running in the same docker network, so I had to pass it the .1.28 ip address, but you normally would just have the name overseerr in that spot. You can also change the /overseerr to /jellyseerr, I just left them as that.

location ^~ /overseerr {
   set $app 'overseerr';

   # Remove /overseerr path to pass to the app
   rewrite ^/overseerr/?(.*)$ /$1 break;
   proxy_pass http://192.168.1.28:5055; # NO TRAILING SLASH

   # Redirect location headers
   proxy_redirect ^ /$app;
   proxy_redirect /setup /$app/setup;
   proxy_redirect /login /$app/login;

   # Sub filters to replace hardcoded paths
   proxy_set_header Accept-Encoding "";
   sub_filter_once off;
   sub_filter_types *;
   sub_filter 'href="/"' 'href="/$app"';
   sub_filter 'href="/login"' 'href="/$app/login"';
   sub_filter 'href:"/"' 'href:"/$app"';
   sub_filter '/_next' '/$app/_next';
   sub_filter '/api/v1' '/$app/api/v1';
   sub_filter '/login/plex/loading' '/$app/login/plex/loading';
   sub_filter '/images/' '/$app/images/';
   sub_filter '/android-' '/$app/android-';
   sub_filter '/apple-' '/$app/apple-';
   sub_filter '/favicon' '/$app/favicon';
   sub_filter '/logo_' '/$app/logo_';
   sub_filter '/site.webmanifest' '/$app/site.webmanifest';
}

the only bug I have noticed is that if you go to another page such as settings, and reload, it won't recognize where you are because you'd now be under domain.com/settings etc. I'm 90% sure fixing the proxy_redirect or the $app variable to the IP address would fix that in my case
This is the settings in the app itself
unknown-24.png
Make sure your proxy is working because if you enable proxy support, you can still go to the app via IP and port, but it will not save anything, so you will have to go back and change the setting in the config file if you accidentally lock yourself out.

Hope this helps. I have not tried it myself so

@M-MDev
Copy link

M-MDev commented Oct 20, 2022

@Fallenbagel your config was working great until recently. Login screen just loops now.

@Fallenbagel
Copy link
Owner

@Fallenbagel your config was working great until recently. Login screen just loops now.

Since Overseerr 1.30.0 which is 1.2.0 of jellyseerr, the config is now different.

sct/overseerr#274 (comment)

@ajdunevent
Copy link

Why am I the last person still using Apache? Haha.
Anyone have any hints on getting Jellyseerr working with a baseurl in Apache?

@DuvelCorp
Copy link

You are not. I am stuck too, looking for an Apache solution

@Fallenbagel
Copy link
Owner

You are not. I am stuck too, looking for an Apache solution

In my limited knowledge of apache, isn't nginx and apache very similar in its configuration? 🤔
Maybe a translation to it could be achieved

@Yankees4life
Copy link

I hope to see this feature in future versions. There's no way to set a baseurl inside jellyseerr. Ombi has this but not jellyseerr

@ramkrishna757575
Copy link

I would also love to see this much needed feature added :)

@GNUGradyn
Copy link

Why cant the base URL just be implied from the application URL setting?

@timotheeandres
Copy link

I'd be interested in this! I don't know TS/React enough to make the change myself

@weirdal3333
Copy link

The current implementation disallows urls without a . in them. Why is the validity of a url being tested? This breaks local (and docker) functionality.

@ReadieFur
Copy link

I have made a workaround for Nginx thanks to the help of what has already been provided and some minor tweaks of my own.
This method makes use of the Overseerr Nginx proxy config as well as injecting HTML to the client to fix the path (this fixes relading the page).

Complete Nginx config

Below is what you would put within your Nginx config, it contains the Javascript that is to be injected into the clients webpage.

location ^~ /jellyseerr {
    set $app 'jellyseerr';

    # Remove /overseerr path to pass to the app
    rewrite ^/jellyseerr/?(.*)$ /$1 break;
    proxy_pass http://172.17.0.1:5055; # NO TRAILING SLASH

    # Redirect location headers
    proxy_redirect ^ /$app;
    proxy_redirect /setup /$app/setup;
    proxy_redirect /login /$app/login;

    # Sub filters to replace hardcoded paths
    proxy_set_header Accept-Encoding "";
    sub_filter_once off;
    sub_filter_types *;
    #https://stackoverflow.com/questions/19700871/how-to-inject-custom-content-via-nginx
    sub_filter '</head>' '<script language="javascript">(()=>{var t="$app";let e=history.pushState;history.pushState=function a(){arguments[2]&&!arguments[2].startsWith("/"+t)&&(arguments[2]="/"+t+arguments[2]);let s=e.apply(this,arguments);return window.dispatchEvent(new Event("pushstate")),s};let a=history.replaceState;history.replaceState=function e(){arguments[2]&&!arguments[2].startsWith("/"+t)&&(arguments[2]="/"+t+arguments[2]);let s=a.apply(this,arguments);return window.dispatchEvent(new Event("replacestate")),s},window.addEventListener("popstate",()=>{console.log("popstate")})})();</script></head>';
    sub_filter 'href="/"' 'href="/$app"';
    sub_filter 'href="/login"' 'href="/$app/login"';
    sub_filter 'href:"/"' 'href:"/$app"';
    sub_filter '\/_next' '\/$app\/_next';
    sub_filter '/_next' '/$app/_next';
    sub_filter '/api/v1' '/$app/api/v1';
    sub_filter '/login/plex/loading' '/$app/login/plex/loading';
    sub_filter '/images/' '/$app/images/';
    sub_filter '/android-' '/$app/android-';
    sub_filter '/apple-' '/$app/apple-';
    sub_filter '/favicon' '/$app/favicon';
    sub_filter '/logo_' '/$app/logo_';
    sub_filter '/site.webmanifest' '/$app/site.webmanifest';
}

Formatted Javascript:

Below is the formatted javascript for if you want to read how it works or modify it, you do not need to do anything with this if you have copied the config above.

//https://stackoverflow.com/questions/6390341/how-to-detect-if-url-has-changed-after-hash-in-javascript
(() => {
    let APP_PATH = "jellyseerr";

    let oldPushState = history.pushState;
    history.pushState = function pushState() {
        //Check if we need to fix the path (if it dosent start with /jellyseerr then we need to fix it)
        if (arguments[2] && !arguments[2].startsWith("/" + APP_PATH))
            arguments[2] = "/" + APP_PATH + arguments[2];

        let ret = oldPushState.apply(this, arguments);
        window.dispatchEvent(new Event('pushstate'));
        return ret;
    };

    let oldReplaceState = history.replaceState;
    history.replaceState = function replaceState() {
        //Check if we need to fix the path (if it dosent start with /jellyseerr then we need to fix it)
        if (arguments[2] && !arguments[2].startsWith("/" + APP_PATH))
            arguments[2] = "/" + APP_PATH + arguments[2];

        let ret = oldReplaceState.apply(this, arguments);
        window.dispatchEvent(new Event('replacestate'));
        return ret;
    };

    window.addEventListener('popstate', () => {
        console.log('popstate');
    });
})();

@OdinVex
Copy link

OdinVex commented Jan 13, 2024

I think proper support should simply be implemented. For those that host multiple services on a single domain needing different sub-paths this won't work (domain.com/radarr, domain.com/sonarr, etc.). The ability to override the useragent (if users request) would be nice too (Jellyfin still thinks it is Overseerr).

@ddimick
Copy link
Author

ddimick commented Jan 13, 2024

Although it is great (not to mention very helpful, thank you) to see a workaround with nginx via realtime rewrites, there are many other popular proxies. Apache, Caddy, Traefik, Cloudflare, etc. People who use OAuth may also find their configurations more complicated than would be otherwise necessary.

@Fallenbagel
Copy link
Owner

I think proper support should simply be implemented. For those that host multiple services on a single domain needing different sub-paths this won't work (domain.com/radarr, domain.com/sonarr, etc.). The ability to override the useragent (if users request) would be nice too (Jellyfin still thinks it is Overseerr).

The useragent is fixed in develop.
As for subpath thing it's been a bit hard to implement due to

Next.js not allowing to change the base URL after build time.

@OdinVex
Copy link

OdinVex commented Jan 13, 2024

Next.js not allowing to change the base URL after build time.

Well that bites. x_x;

@caio1007
Copy link

caio1007 commented Feb 5, 2024

I have made a workaround for Nginx thanks to the help of what has already been provided and some minor tweaks of my own.

This method makes use of the Overseerr Nginx proxy config as well as injecting HTML to the client to fix the path (this fixes relading the page).

Complete Nginx config

Below is what you would put within your Nginx config, it contains the Javascript that is to be injected into the clients webpage.

location ^~ /jellyseerr {

    set $app 'jellyseerr';



    # Remove /overseerr path to pass to the app

    rewrite ^/jellyseerr/?(.*)$ /$1 break;

    proxy_pass http://172.17.0.1:5055; # NO TRAILING SLASH



    # Redirect location headers

    proxy_redirect ^ /$app;

    proxy_redirect /setup /$app/setup;

    proxy_redirect /login /$app/login;



    # Sub filters to replace hardcoded paths

    proxy_set_header Accept-Encoding "";

    sub_filter_once off;

    sub_filter_types *;

    #https://stackoverflow.com/questions/19700871/how-to-inject-custom-content-via-nginx

    sub_filter '</head>' '<script language="javascript">(()=>{var t="$app";let e=history.pushState;history.pushState=function a(){arguments[2]&&!arguments[2].startsWith("/"+t)&&(arguments[2]="/"+t+arguments[2]);let s=e.apply(this,arguments);return window.dispatchEvent(new Event("pushstate")),s};let a=history.replaceState;history.replaceState=function e(){arguments[2]&&!arguments[2].startsWith("/"+t)&&(arguments[2]="/"+t+arguments[2]);let s=a.apply(this,arguments);return window.dispatchEvent(new Event("replacestate")),s},window.addEventListener("popstate",()=>{console.log("popstate")})})();</script></head>';

    sub_filter 'href="/"' 'href="/$app"';

    sub_filter 'href="/login"' 'href="/$app/login"';

    sub_filter 'href:"/"' 'href:"/$app"';

    sub_filter '\/_next' '\/$app\/_next';

    sub_filter '/_next' '/$app/_next';

    sub_filter '/api/v1' '/$app/api/v1';

    sub_filter '/login/plex/loading' '/$app/login/plex/loading';

    sub_filter '/images/' '/$app/images/';

    sub_filter '/android-' '/$app/android-';

    sub_filter '/apple-' '/$app/apple-';

    sub_filter '/favicon' '/$app/favicon';

    sub_filter '/logo_' '/$app/logo_';

    sub_filter '/site.webmanifest' '/$app/site.webmanifest';

}

Formatted Javascript:

Below is the formatted javascript for if you want to read how it works or modify it, you do not need to do anything with this if you have copied the config above.

//https://stackoverflow.com/questions/6390341/how-to-detect-if-url-has-changed-after-hash-in-javascript

(() => {

    let APP_PATH = "jellyseerr";



    let oldPushState = history.pushState;

    history.pushState = function pushState() {

        //Check if we need to fix the path (if it dosent start with /jellyseerr then we need to fix it)

        if (arguments[2] && !arguments[2].startsWith("/" + APP_PATH))

            arguments[2] = "/" + APP_PATH + arguments[2];



        let ret = oldPushState.apply(this, arguments);

        window.dispatchEvent(new Event('pushstate'));

        return ret;

    };



    let oldReplaceState = history.replaceState;

    history.replaceState = function replaceState() {

        //Check if we need to fix the path (if it dosent start with /jellyseerr then we need to fix it)

        if (arguments[2] && !arguments[2].startsWith("/" + APP_PATH))

            arguments[2] = "/" + APP_PATH + arguments[2];



        let ret = oldReplaceState.apply(this, arguments);

        window.dispatchEvent(new Event('replacestate'));

        return ret;

    };



    window.addEventListener('popstate', () => {

        console.log('popstate');

    });

})();

Doesn't work for me, 404 error page not found. I installed it via Docker

@Fallenbagel
Copy link
Owner

@caio1007 the workaround is different now. You can find the latest updated one in the pinned thread on our discord.

@OdinVex
Copy link

OdinVex commented Feb 10, 2024

How about being able to change the links generated by the software? I can have a proxy fetch / and show others /Jellyseerr, can I simply get the base href altered by a variable? That'd solve it for me. It should be usable for everyone. Just have your proxy serve to / from a particular location and simply have Jellyseerr use base href in the template. That way no base url would be entirely necessary, a proxy could rewrite to / and Jellyseerr could set one html tag which can affect all relative links on a page. https://www.w3schools.com/tags/tag_base.asp The links are already relative, for what I can see. Just literally add a base tag and allow us to set the href. :)

@ReclinesMC
Copy link

Damn. I didn't expect it to be this hard. Code can be a bitch sometimes

@OdinVex
Copy link

OdinVex commented Feb 25, 2024

Damn. I didn't expect it to be this hard. Code can be a bitch sometimes

It's not hard at all, I already mentioned how to address it. Reverse-proxies can be setup to pull directly from / and you can simply set a base href with links not beginning with /, this'll cause them to be relative, so it'd work regardless.

@ReclinesMC
Copy link

Damn. I didn't expect it to be this hard. Code can be a bitch sometimes

It's not hard at all, I already mentioned how to address it. Reverse-proxies can be setup to pull directly from / and you can simply set a base href with links not beginning with /, this'll cause them to be relative, so it'd work regardless.

And what if my host does not allow that?

@OdinVex
Copy link

OdinVex commented Feb 26, 2024

And what if my host does not allow that?

Define that? The base href stuff and not writing links with / prefixed? That's a Jellyseerr issue that can be fixed easily. If you're talking about configuring your reverse-proxy I don't know how you mean that they don't "allow that". The fact you're using a r-proxy to begin with would be baffling if you can't actually configure it. ???

@ReclinesMC
Copy link

And what if my host does not allow that?

Define that? The base href stuff and not writing links with / prefixed? That's a Jellyseerr issue that can be fixed easily. If you're talking about configuring your reverse-proxy I don't know how you mean that they don't "allow that". The fact you're using a r-proxy to begin with would be baffling if you can't actually configure it. ???

Apologies, I am awful at explaining stuff. I use https://ultra.cc to host a Jellyfin server, I believe me trying to setup what you're describing would be against their TOS

@OdinVex
Copy link

OdinVex commented Feb 26, 2024

And what if my host does not allow that?

Define that? The base href stuff and not writing links with / prefixed? That's a Jellyseerr issue that can be fixed easily. If you're talking about configuring your reverse-proxy I don't know how you mean that they don't "allow that". The fact you're using a r-proxy to begin with would be baffling if you can't actually configure it. ???

Apologies, I am awful at explaining stuff. I use https://ultra.cc to host a Jellyfin server, I believe me trying to setup what you're describing would be against their TOS

??? What does your host have to do with anything? This thread is about Jellyseerr and using a subpath instead of accessing via 80, 443, or some other port while using a reverse-proxy to provide a clean subpath instead.

@ReclinesMC
Copy link

And what if my host does not allow that?

Define that? The base href stuff and not writing links with / prefixed? That's a Jellyseerr issue that can be fixed easily. If you're talking about configuring your reverse-proxy I don't know how you mean that they don't "allow that". The fact you're using a r-proxy to begin with would be baffling if you can't actually configure it. ???

Apologies, I am awful at explaining stuff. I use https://ultra.cc to host a Jellyfin server, I believe me trying to setup what you're describing would be against their TOS

??? What does your host have to do with anything? This thread is about Jellyseerr and using a subpath instead of accessing via 80, 443, or some other port while using a reverse-proxy to provide a clean subpath instead.

Ultra.cc manages jellyseerr and creates the sub path by itself

@OdinVex
Copy link

OdinVex commented Feb 26, 2024

Ultra.cc manages jellyseerr and creates the sub path by itself

...So what are you here for then?

@ReclinesMC
Copy link

Ultra.cc manages jellyseerr and creates the sub path by itself

...So what are you here for then?

They manage the web proxy not me, so the solution is impossible to implement for me until someone fixes in in the actual code of jellyseerr #669 was my first post, but then I was redirected to here since im blind and didn't see this one

@OdinVex
Copy link

OdinVex commented Feb 26, 2024

Ultra.cc manages jellyseerr and creates the sub path by itself

...So what are you here for then?

They manage the web proxy not me, so the solution is impossible to implement for me until someone fixes in in the actual code of jellyseerr #669 was my first post, but then I was redirected to here since im blind and didn't see this one

Edit: Removed post after seeing #669 which was not at all obvious or known. There is nothing you can do, but my solution would fix that. All links need to be updated to remove / and that includes generated links. Then a setting needs to be configurable to edit base href, this would be set to whatever public endpoint you want. You'll need to wait. I doubt your host set up Jellyseerr under a subpath without knowing about that so I'm thinking you did that. Just move it back to a port for now.

@ReclinesMC
Copy link

ReclinesMC commented Feb 26, 2024

Ultra.cc manages jellyseerr and creates the sub path by itself

...So what are you here for then?

They manage the web proxy not me, so the solution is impossible to implement for me until someone fixes in in the actual code of jellyseerr #669 was my first post, but then I was redirected to here since im blind and didn't see this one

Edit: Removed post after seeing #669 which was not at all obvious or known. There is nothing you can do, but my solution would fix that. All links need to be updated to remove / and that includes generated links. Then a setting needs to be configurable to edit base href, this would be set to whatever public endpoint you want. You'll need to wait. I doubt your host set up Jellyseerr under a subpath without knowing about that so I'm thinking you did that. Just move it back to a port for now.

I will simply show you this doc, which shows that it will come pre-installed under a subpath

https://docs.ultra.cc/books/jellyseerr/page/jellyseerr

Edit: ah, It seems they also have their own janky fix:

image

@weirdal3333
Copy link

That's not a subpath. That's a subdomin.

@Fallenbagel
Copy link
Owner

Edit: Removed post after seeing #669 which was not at all obvious or known. There is nothing you can do, but my solution would fix that. All links need to be updated to remove / and that includes generated links. Then a setting needs to be configurable to edit base href, this would be set to whatever public endpoint you want. You'll need to wait. I doubt your host set up Jellyseerr under a subpath without knowing about that so I'm thinking you did that. Just move it back to a port for now.

Imo I don't think using base href would be good for a nextjs app. I have looked into a way to make subpath possible and I have found a solution. It's less hacky than the method that was tried before.

Basically using a dynamic segment that houses all the pages and using a middleware that looks for a subpath using the serverRuntimeConfig and redirecting. I have tried it on a fresh nextjs project but haven't yet looked into how viable it would be for a jellyseerr/overseerr rewrite to support it.

@ReclinesMC
Copy link

ReclinesMC commented Feb 26, 2024

That's not a subpath. That's a subdomin.

I'm not sure if you're talking about the host I'm using, but if so, it is a subpath.

a subdomain would be "jellyseerr.example.com" whereas a subpath is "example.com/jellyseerr"

The host I use uses this format for domains

"username.servername.usbx.me/appname"

Which is a subpath, not a subdomain.

Is there a technical explanation on why it's so hard to set the baseURI. Can there be a settings option for it that applies after restart? Pretty much every other application I use does it just fine. Sonarr, Radarr, qBittorrent, Jellyfin, Autobrr, file browser, etc.

@OdinVex
Copy link

OdinVex commented Feb 26, 2024

Edit: Removed post after seeing #669 which was not at all obvious or known. There is nothing you can do, but my solution would fix that. All links need to be updated to remove / and that includes generated links. Then a setting needs to be configurable to edit base href, this would be set to whatever public endpoint you want. You'll need to wait. I doubt your host set up Jellyseerr under a subpath without knowing about that so I'm thinking you did that. Just move it back to a port for now.

Imo I don't think using base href would be good for a nextjs app. I have looked into a way to make subpath possible and I have found a solution. It's less hacky than the method that was tried before.

Basically using a dynamic segment that houses all the pages and using a middleware that looks for a subpath using the serverRuntimeConfig and redirecting. I have tried it on a fresh nextjs project but haven't yet looked into how viable it would be for a jellyseerr/overseerr rewrite to support it.

In other words routing processing. The expressed lack of possibility of that is what led me to base href. Base href would be much easier and much more compatible across any configurations, two-cents. Base href would work under all scenarios, especially since it too can be relative. Eg "/jellyseerr" would would make any/all links relative to jellyseerr under any domain or subdomain or port configuration. Base href is the way these should be addressed, but whatever solution is accepted is fine with me.

That's not a subpath. That's a subdomin.

I'm not sure if you're talking about the host I'm using, but if so, it is a subpath.

a subdomain would be "jellyseerr.example.com" whereas a subpath is "example.com/jellyseerr"

The host I use uses this format for domains

"username.servername.usbx.me/appname"

Which is a subpath, not a subdomain.

Is there a technical explanation on why it's so hard to set the baseURI. Can there be a settings option for it that applies after restart? Pretty much every other application I use does it just fine. Sonarr, Radarr, qBittorrent, Jellyfin, Autobrr, file browser, etc.

...No that's a subdomain and a subpath. ... If you bothered to read the thread you'd have already seen the technical explanation.

@bertho-zero
Copy link

bertho-zero commented Mar 2, 2024

I added a part that monitors the DOM to modify the href attributes, which means that the links displayed by the browser on hover are correct and opening in a new tab via click + wheel or ctrl + click works.

Nginx sub filter:

sub_filter '</head>' '<script language="javascript">(()=>{let t="/$app",e=history.pushState;history.pushState=function r(){arguments[2]&&!arguments[2].startsWith(t)&&(arguments[2]=t+arguments[2]);let s=e.apply(this,arguments);return window.dispatchEvent(new Event("pushstate")),s};let r=history.replaceState;function s(){document.querySelectorAll("a[href]").forEach(e=>{let r=e.getAttribute("href");r.startsWith("/")&&!r.startsWith(t)&&e.setAttribute("href",t+r)})}history.replaceState=function e(){arguments[2]&&!arguments[2].startsWith(t)&&(arguments[2]=t+arguments[2]);let s=r.apply(this,arguments);return window.dispatchEvent(new Event("replacestate")),s},document.addEventListener("DOMContentLoaded",function(){let t=new MutationObserver(t=>{t.forEach(t=>{t.addedNodes.length&&s()})});t.observe(document.body,{childList:!0,subtree:!0}),s()})})();</script></head>';

Formatted script:

(() => {
  const APP_PATH = "/jellyseerr";

  const oldPushState = history.pushState;
  history.pushState = function pushState() {
    //Check if we need to fix the path (if it dosent start with /jellyseerr then we need to fix it)
    if (arguments[2] && !arguments[2].startsWith(APP_PATH))
      arguments[2] = APP_PATH + arguments[2];

    const ret = oldPushState.apply(this, arguments);
    window.dispatchEvent(new Event("pushstate"));
    return ret;
  };

  const oldReplaceState = history.replaceState;
  history.replaceState = function replaceState() {
    //Check if we need to fix the path (if it dosent start with /jellyseerr then we need to fix it)
    if (arguments[2] && !arguments[2].startsWith(APP_PATH))
      arguments[2] = APP_PATH + arguments[2];

    const ret = oldReplaceState.apply(this, arguments);
    window.dispatchEvent(new Event("replacestate"));
    return ret;
  };

  function addPrefixToLinks() {
    document.querySelectorAll("a[href]").forEach((link) => {
      const href = link.getAttribute("href");
      if (href.startsWith("/") && !href.startsWith(APP_PATH)) {
        link.setAttribute("href", APP_PATH + href);
      }
    });
  }

  document.addEventListener("DOMContentLoaded", function () {
    const observer = new MutationObserver((mutations) => {
      mutations.forEach((mutation) => {
        if (mutation.addedNodes.length) {
          addPrefixToLinks();
        }
      });
    });

    observer.observe(document.body, {
      childList: true,
      subtree: true,
    });

    addPrefixToLinks();
  });
})();

@OdinVex
Copy link

OdinVex commented Mar 2, 2024

I did a binary patch of _app.js and one other 5-something.js (fixed _next links added) to replace "href="/" with "href="" and removed a _app.js tag so I could inject a base href, it worked too. (In short, the links generated need to not have a forward-slash and a base href set to applicationUrl (was just using a pre-existing variable for the sake of testing). The router needs adjusting to prepend a process.ENV if need-be, I'd settle for that kind of configurability and the links generated need adjustment, it's entirely possible, but I don't like working in this kind of language. I did it this way so that the proxy wouldn't need to process anything, it's also cross-server.

@shaumux
Copy link

shaumux commented Mar 30, 2024

I was setting up jellyseerr and am using traefik and spent the last day to get the rules to run it behind traefik.
I have not seen any issues till now with the below rules, but haven't used it fro too long yet so can't really be sure.
Maybe this helps further.

      - "traefik.http.routers.jellyseer.rule=PathPrefix(`/jellyseer`)"
      - "traefik.http.middlewares.jellyseerr-stripprefix.stripprefix.prefixes=/jellyseerr"
      - "traefik.http.middlewares.jellyseerr-rewriterelativelocation.plugin.traefik-plugin-rewrite-response-headers.rewrites.header=Location"
      - "traefik.http.middlewares.jellyseerr-rewriterelativelocation.plugin.traefik-plugin-rewrite-response-headers.rewrites.regex=^/(.+)$"
      - "traefik.http.middlewares.jellyseerr-rewriterelativelocation.plugin.traefik-plugin-rewrite-response-headers.rewrites.replacement=/jellyseerr/$1"

      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[0].regex=href=\"/(.+?)?\""
      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[0].replacement=href=\"/jellyseerr/$1\""
      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[1].regex=src=\"/(.+?)?\""
      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[1].replacement=src=\"/jellyseerr/$1\""

      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[2].regex=href:\"/(.*?)\""
      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[2].replacement=href:\"/jellyseerr/$1\""

      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[3].regex=\"/api/(.*?)\""
      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[3].replacement=\"/jellyseerr/api/$1\""

      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[4].regex=\"/_next/(.*?)\""
      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[4].replacement=\"/jellyseerr/_next/$1\""

      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[5].regex=\"/images/(.*?)\""
      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[5].replacement=\"/jellyseerr/images/$1\""

      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[6].regex=src:\"/(.*?)\""
      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[6].replacement=src:\"/jellyseerr/$1\""

      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[7].regex=linkUrl:\"/(.*?)\""
      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[7].replacement=linkUrl:\"/jellyseerr/$1\""

      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.lastModified=true"
      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.monitoring.types[0]=text/html"
      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.monitoring.types[1]=application/javascript" 
      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.monitoring.types[2]=*/*" 

This is ofcourse running in docker and from my compose file

EDIT: added the top 2 lines in the example

@MohamedAliRashad
Copy link

Any final solutions for this issue ?
(I want to put jellyseerr on /jellyseerr/ endpoint in nginx)

@Fallenbagel
Copy link
Owner

Any final solutions for this issue ?
(I want to put jellyseerr on /jellyseerr/ endpoint in nginx)

We don't support subfolders. Discord has the working workaround for it

@MohamedAliRashad
Copy link

@Fallenbagel I managed to succeed in doing it using this guide:
https://docs.overseerr.dev/extending-overseerr/reverse-proxy

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

No branches or pull requests