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

feat: Support configurable base path for server #714

Merged
merged 2 commits into from
Nov 18, 2024

Conversation

chrishoage
Copy link
Contributor

Closes: #576
Closes: #575

This PR Adds a BasePath config that allows the go server to respond to requests at a specific sub path.

To test supply the BaseBath config though the environment variable DAGU_BASE_PATH=/foo or through the admin.yaml file

  1. Load dagu at the root /
  2. Should be redirected to /foo
  3. dagu should work with out regressions
  4. Restart dagu with out base path
  5. dagu should work with out regressions as before

docs/source/config.rst Show resolved Hide resolved
Comment on lines 107 to 110
if basePath != "" && r.URL.Path == "/" {
http.Redirect(w, r, basePath, http.StatusSeeOther)
return
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the root of the server is hit and we have a base path configured redirect to that base path for convenience.

Copy link
Collaborator

@yohamta yohamta Nov 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tested this locally with an nginx reverse proxy (configuration below) but encountered an issue when accessing via the proxy path http://localhost/dagu/. It seems the path prefix check might be the cause. The following code, however, works as expected:

if strings.HasPrefix(r.URL.Path, "/api") {
    next.ServeHTTP(w, r)
} else {
    defaultHandler.ServeHTTP(w, r)
}

Would you mind taking a look when you have a chance?

Test setup

server {
    listen       80;
    server_name  localhost;
    location /dagu/ {
        proxy_pass http://localhost:8080/;
        proxy_set_header Host $host;
        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;
    }
}

~/.dagu/admin.cfg

basePath: /dagu/
port: 8080

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue is the trailing slash. I was only testing with /dagu and missed this case.

I have made the BasePath more robust

  • Normalize the value in config.go so that all parts of the app can be sure it has the same shape
  • changed prefixChecker to strip the prefix first, then do the strings.HasPrefix check in a HandlerFunc to not have to worry about the prefix.

I tested with

  • no basepath set at all
  • basepath set as an empty string
  • basePath set as /
  • basePath set as /dagu
  • basePath set as /dagu/
  • basePath set as /dagu/foo

I believe this should be good.

I have pushed up the fix as a !fixup commit to make it easier to review. This can be "squashed" when merging or I can squash it before this is ready to merge.

return
}

if strings.HasPrefix(r.URL.Path, path.Join(basePath, "/api")) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a better solution to path.Join here? It doesn't feel robust.

It really feels like /api should be a handler which is hung off of http.StripPrefix(basePath, next) such that any route registered under it would be handled by /api

I wasn't sure of the consequences of such a change however, so I just updated the string comparison.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #714 (comment) this has been improved to not rely on path.join for this prefix check

ui/webpack.prod.js Show resolved Hide resolved
Comment on lines 113 to 115
http.StripPrefix(basePath, next).ServeHTTP(w, r)
} else {
defaultHandler.ServeHTTP(w, r)
http.StripPrefix(basePath, defaultHandler).ServeHTTP(w, r)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

http.StripPrefix seemed like the cleanest way to allow all existing routes to work as before.

This is my first time writing Go so if there's a more idiomatic way of doing this let me know!

Copy link

codecov bot commented Nov 17, 2024

Codecov Report

Attention: Patch coverage is 0% with 2 lines in your changes missing coverage. Please review.

Project coverage is 61.77%. Comparing base (6ce3fdd) to head (453f0d2).

Files with missing lines Patch % Lines
internal/config/config.go 0.00% 2 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #714      +/-   ##
==========================================
- Coverage   61.80%   61.77%   -0.03%     
==========================================
  Files          53       53              
  Lines        5249     5251       +2     
==========================================
  Hits         3244     3244              
- Misses       1751     1753       +2     
  Partials      254      254              
Files with missing lines Coverage Δ
internal/config/config.go 0.00% <0.00%> (ø)

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 6ce3fdd...453f0d2. Read the comment docs.

Copy link
Collaborator

@yohamta yohamta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looking amazing, thank you so much for the great PR! I've left a small question, so please take a look when you have a moment :)

Comment on lines 107 to 110
if basePath != "" && r.URL.Path == "/" {
http.Redirect(w, r, basePath, http.StatusSeeOther)
return
}
Copy link
Collaborator

@yohamta yohamta Nov 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tested this locally with an nginx reverse proxy (configuration below) but encountered an issue when accessing via the proxy path http://localhost/dagu/. It seems the path prefix check might be the cause. The following code, however, works as expected:

if strings.HasPrefix(r.URL.Path, "/api") {
    next.ServeHTTP(w, r)
} else {
    defaultHandler.ServeHTTP(w, r)
}

Would you mind taking a look when you have a chance?

Test setup

server {
    listen       80;
    server_name  localhost;
    location /dagu/ {
        proxy_pass http://localhost:8080/;
        proxy_set_header Host $host;
        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;
    }
}

~/.dagu/admin.cfg

basePath: /dagu/
port: 8080

@chrishoage
Copy link
Contributor Author

@yohamta This should be good for another review, thank you!

@chrishoage chrishoage requested a review from yohamta November 17, 2024 18:25
Copy link
Collaborator

@yohamta yohamta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✨✨✨🚀🚀🚀 Looking great ✨✨✨🚀🚀🚀, thank you so much!

@yohamta yohamta merged commit 444c452 into dagu-org:main Nov 18, 2024
3 checks passed
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

Successfully merging this pull request may close these issues.

Add environment variable DAGU_BASE_URL Serving dagu behind reverse proxy on subpath
2 participants