Fix usage of WOODPECKER_ROOT_PATH (#2485)

I had experienced some issues running Woodpecker behind a reverse-proxy,
resulting from not defining the `WOODPECKER_ROOT_PATH` environment
variable in #2477.

As suggested by @qwerty287, specifying `WOODPECKER_ROOT_PATH=/foo`
*mostly* solved the issue of running the woodpecker server at an url
like `https://example.org/foo`.
However, the webhook urls and badge urls were generated excluding the
configured `WOODPECKER_ROOT_PATH`.

This PR (mostly) fixes issues related to non-empty
`WOODPECKER_ROOT_PATH`.

---------

Co-authored-by: qwerty287 <80460567+qwerty287@users.noreply.github.com>
This commit is contained in:
Tom Kneiphof 2023-09-22 16:43:31 +02:00 committed by GitHub
parent f6d551c8b7
commit baaf8b97e1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 21 additions and 16 deletions

View file

@ -38,12 +38,12 @@ var flags = append([]cli.Flag{
&cli.StringFlag{
EnvVars: []string{"WOODPECKER_HOST"},
Name: "server-host",
Usage: "server fully qualified url (<scheme>://<host>)",
Usage: "server fully qualified url (<scheme>://<host>[/<prefixpath>])",
},
&cli.StringFlag{
EnvVars: []string{"WOODPECKER_WEBHOOK_HOST"},
Name: "server-webhook-host",
Usage: "server fully qualified url for forge's Webhooks (<scheme>://<host>)",
Usage: "server fully qualified url for forge's Webhooks (<scheme>://<host>[/<prefixpath>])",
},
&cli.StringFlag{
EnvVars: []string{"WOODPECKER_ROOT_PATH", "WOODPECKER_ROOT_URL"},
@ -450,7 +450,7 @@ var flags = append([]cli.Flag{
&cli.StringFlag{
EnvVars: []string{"WOODPECKER_DEV_OAUTH_HOST"},
Name: "server-dev-oauth-host",
Usage: "server fully qualified url (<scheme>://<host>) used for oauth redirect (used for development)",
Usage: "server fully qualified url (<scheme>://<host>[/<prefixpath>]) used for oauth redirect (used for development)",
Value: "",
Hidden: true,
},

View file

@ -344,7 +344,13 @@ func setupEvilGlobals(c *cli.Context, v store.Store, f forge.Forge) {
server.Config.Server.StatusContext = c.String("status-context")
server.Config.Server.StatusContextFormat = c.String("status-context-format")
server.Config.Server.SessionExpires = c.Duration("session-expires")
rootPath := strings.TrimSuffix(c.String("root-path"), "/")
rootPath := c.String("root-path")
if !c.IsSet("root-path") {
// Extract RootPath from Host...
u, _ := url.Parse(server.Config.Server.Host)
rootPath = u.Path
}
rootPath = strings.TrimSuffix(rootPath, "/")
if rootPath != "" && !strings.HasPrefix(rootPath, "/") {
rootPath = "/" + rootPath
}

View file

@ -93,7 +93,6 @@ services:
environment:
- [...]
+ - WOODPECKER_HOST=${WOODPECKER_HOST}
+ - WOODPECKER_HOST=${WOODPECKER_HOST}
```
Woodpecker can also have its port's configured. It uses a separate port for gRPC and for HTTP. The agent performs gRPC calls and connects to the gRPC port.

View file

@ -215,14 +215,14 @@ Disable colored debug output.
### `WOODPECKER_HOST`
> Default: empty
Server fully qualified URL of the user-facing hostname.
Server fully qualified URL of the user-facing hostname and path prefix.
Example: `WOODPECKER_HOST=http://woodpecker.example.org`
Example: `WOODPECKER_HOST=http://woodpecker.example.org` or `WOODPECKER_HOST=http://example.org/woodpecker`
### `WOODPECKER_WEBHOOK_HOST`
> Default: value from `WOODPECKER_HOST` config env
Server fully qualified URL of the Webhook-facing hostname.
Server fully qualified URL of the Webhook-facing hostname and path prefix.
Example: `WOODPECKER_WEBHOOK_HOST=http://woodpecker-server.cicd.svc.cluster.local:8000`
@ -529,7 +529,7 @@ Specify a configuration service endpoint, see [Configuration Extension](./100-ex
Specify how many seconds before timeout when fetching the Woodpecker configuration from a Forge
### `WOODPECKER_ROOT_PATH`
> Default: ``
> Default: extracted from `WOODPECKER_HOST`
Server URL path prefix (used for statics loading when having a url path prefix), should start with `/`

View file

@ -389,7 +389,7 @@ func DeleteRepo(c *gin.Context) {
}
}
if err := server.Config.Services.Forge.Deactivate(c, user, repo, server.Config.Server.Host); err != nil {
if err := server.Config.Services.Forge.Deactivate(c, user, repo, server.Config.Server.WebhookHost); err != nil {
_ = c.AbortWithError(http.StatusInternalServerError, err)
return
}
@ -534,7 +534,7 @@ func MoveRepo(c *gin.Context) {
}
// reconstruct the link
host := server.Config.Server.Host
host := server.Config.Server.WebhookHost
link := fmt.Sprintf(
"%s/api/hook?access_token=%s",
host,

View file

@ -421,7 +421,7 @@ func (c *config) newOAuth2Config() *oauth2.Config {
AuthURL: fmt.Sprintf("%s/site/oauth2/authorize", c.url),
TokenURL: fmt.Sprintf("%s/site/oauth2/access_token", c.url),
},
RedirectURL: fmt.Sprintf("%s%s/authorize", server.Config.Server.OAuthHost, server.Config.Server.RootPath),
RedirectURL: fmt.Sprintf("%s/authorize", server.Config.Server.OAuthHost),
}
}

View file

@ -103,7 +103,7 @@ func (c *Gitea) oauth2Config(ctx context.Context) (*oauth2.Config, context.Conte
AuthURL: fmt.Sprintf(authorizeTokenURL, c.url),
TokenURL: fmt.Sprintf(accessTokenURL, c.url),
},
RedirectURL: fmt.Sprintf("%s%s/authorize", server.Config.Server.OAuthHost, server.Config.Server.RootPath),
RedirectURL: fmt.Sprintf("%s/authorize", server.Config.Server.OAuthHost),
},
context.WithValue(ctx, oauth2.HTTPClient, &http.Client{Transport: &http.Transport{

View file

@ -400,9 +400,9 @@ func (c *client) newConfig(req *http.Request) *oauth2.Config {
intendedURL := req.URL.Query()["url"]
if len(intendedURL) > 0 {
redirect = fmt.Sprintf("%s%s/authorize?url=%s", server.Config.Server.OAuthHost, server.Config.Server.RootPath, intendedURL[0])
redirect = fmt.Sprintf("%s/authorize?url=%s", server.Config.Server.OAuthHost, intendedURL[0])
} else {
redirect = fmt.Sprintf("%s%s/authorize", server.Config.Server.OAuthHost, server.Config.Server.RootPath)
redirect = fmt.Sprintf("%s/authorize", server.Config.Server.OAuthHost)
}
return &oauth2.Config{

View file

@ -93,7 +93,7 @@ func (g *GitLab) oauth2Config(ctx context.Context) (*oauth2.Config, context.Cont
TokenURL: fmt.Sprintf("%s/oauth/token", g.url),
},
Scopes: []string{defaultScope},
RedirectURL: fmt.Sprintf("%s%s/authorize", server.Config.Server.OAuthHost, server.Config.Server.RootPath),
RedirectURL: fmt.Sprintf("%s/authorize", server.Config.Server.OAuthHost),
},
context.WithValue(ctx, oauth2.HTTPClient, &http.Client{Transport: &http.Transport{