Open MauriceNino opened 1 year ago
This would require setting a base-href in the frontend to have the correct urls in the frontend.
So having dashdot running at a subroute /dashdot, the index.html would require having <base href="/dashdot/">
. However the socket.io URL is still wrong, so it has also to be adjusted.
Quickfix would be checking an env variable in a start script and update the files accordingly.
I was able to make it work.
Here is the diff of the fix:
diff --git a/apps/view/project.json b/apps/view/project.json
index d71c92ad..cc32fb11 100644
--- a/apps/view/project.json
+++ b/apps/view/project.json
@@ -11,7 +11,7 @@
"compiler": "babel",
"outputPath": "dist/apps/view",
"index": "apps/view/src/index.html",
- "baseHref": "/",
+ "baseHref": "",
"main": "apps/view/src/index.tsx",
"tsConfig": "apps/view/tsconfig.json",
"assets": [
diff --git a/apps/view/src/index.css b/apps/view/src/index.css
index 7f87b5cf..38843217 100644
--- a/apps/view/src/index.css
+++ b/apps/view/src/index.css
@@ -2,7 +2,7 @@
font-family: 'Inter';
font-style: normal;
font-display: swap;
- src: url(/assets/Inter.ttf) format('woff2');
+ src: url(assets/Inter.ttf) format('woff2');
}
body {
diff --git a/apps/view/src/services/page-data.ts b/apps/view/src/services/page-data.ts
index f19c50cc..1711a762 100644
--- a/apps/view/src/services/page-data.ts
+++ b/apps/view/src/services/page-data.ts
@@ -23,7 +23,7 @@ export const usePageData = () => {
const config = serverInfo?.config;
useEffect(() => {
- const socket = io(environment.backendUrl);
+ const socket = io(window.location.origin, { path: `${window.location.pathname}/socket.io/` });
socket.on('static-info', data => {
setServerInfo(data);
@@ -45,7 +45,7 @@ export const usePageData = () => {
useEffect(() => {
let socket: Socket | undefined;
if (config) {
- socket = io(environment.backendUrl);
+ socket = io(window.location.origin, { path: `${window.location.pathname}/socket.io/` });
socket.on('cpu-load', data => {
setCpuLoad(oldData => {
I tested it behind an nginx reverse proxy with the following config:
events {
# defaults
}
http {
server {
listen 80;
location /dashdot/ {
proxy_pass http://dashdot:3001/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
}
And ran with docker compose using this compose.yaml file:
services:
dashdot:
build: .
networks:
- common
nginx:
image: nginx:latest
networks:
- common
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
ports:
- 80:80
networks:
common:
@theyurii
Hi there, thanks for your work. I have already started implementing this feature on my own on the branch feature/subpath-hosting, but did not get to testing it thoroughly yet.
What I can see is that the difference in your solution is that you are not changing any backend code to accept requests from the sub-url. Why is that, and how is it still working? When I tested that with traefik, it didn't work.
Can you maybe check out the image for that branch and see if that works for your setup?
@MauriceNino the problem here is not in the backend but in the frontend, and is very well described by @btxtiger . Shortly, frontend has a lot of hardcoded absolute paths of loading resources instead of relative. I.e., browser always tries to make all requests to root /
path instead of current relative path.
Ideally, backend should not care at all where it is hosted, at root path or subdirectory. Backend's purpose is to merely receive a request from a client at any location it listens and generate a response. It can load any needed module relatively to its location on a host. With a frontend, the situation is slightly different. Frontend serves a client with an initial document which later asks browser to load additional resources via separate requests. This is where everything fails.
If you put dashdot behind a reverse proxy and open inspection in any browser, you will quickly find out that the white screen you see is because of browser failing to load resources. This happens because dashdot asks the browser to load them from the root /
path instead of a path relative to the current location (e.g, /dashdot/
). So the solution is pretty simple: ask the browser to make requests to relative paths.
First, I fixed the <base href="/">
tag. It tells browser to load all links in a document relatively to the root path instead of the actual path. This is fixed by modifying baseHref
value in apps/view/project.json
. This makes <base>
tag to have href
attribute set to an empty string which tells browser to load all resources referenced in href
and src
relatively to the current path instead of root path.
Next, I fixed a hardcoded absolute path to Inter.ttf
asset. Instead of loading it from the root path all the time, it's now being loaded relatively to the current path opened in the browser.
Lastly, there is another bug in opening an io socket in apps/view/src/services/page-data.ts
. Official documentation says that new sockets always are pointed to an absolute /socket.io/
path no matter where exactly it is actually hosted. So I override this default value by appending an actual current path of an open browser window which makes io.socket communicating with the right endpoint.
After applying these fixes, the browser now makes all requests to dashdot backend correctly using a relative path instead of absolute root /
path. Dashdot renders correctly and displays all widgets.
P.S.: imho, these problems should be fixed regardless of the goal. Using absolute paths is not good and makes code less flexible and less maintainable.
@theyurii I think there is a misunderstanding. It's pretty clear why the frontend didn't work (absolute paths), but in my testing (on the other branch I mentioned), the backend also required to be served from the sub-url. Which, in hindsight, makes no sense - but it worked. So now I am wondering why we have two different solutions that both work in some scenario.
I will take your comment into consideration, when I look over this issue again (currently short on time), but for now I can't, in good conscience, push this update to main branch.
[...] Using absolute paths is not good [...]
Unfortunately, it's not so simple, and you will find that most resources actually advise against using a relative base href
.
@MauriceNino, any chance of rebasing your feature branch and publishing a new image? I'd love to try it out, but it's 200+ commits behind 'main' and I'm sure I want to also have those changes.
Description of the feature
Users want to host their applications from a suburl, instead of a subdomain (e.g. https://example.com/dashdot)
Additional context
Other applications support it as well: https://wiki.servarr.com/sonarr/settings