Skip to content

Commit 5d0d19c

Browse files
committed
Validate & cache IW2 url instance at daemon start up
1 parent f49956e commit 5d0d19c

File tree

5 files changed

+27
-12
lines changed

5 files changed

+27
-12
lines changed

internal/channel/channel.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212
"github.com/icinga/icinga-notifications/internal/recipient"
1313
"go.uber.org/zap"
1414
"go.uber.org/zap/zapcore"
15-
"net/url"
1615
)
1716

1817
type Channel struct {
@@ -163,7 +162,7 @@ func (c *Channel) Restart(logger *zap.SugaredLogger) {
163162
}
164163

165164
// Notify prepares and sends the notification request, returns a non-error on fails, nil on success
166-
func (c *Channel) Notify(contact *recipient.Contact, i contracts.Incident, ev *event.Event, icingaweb2Url string) error {
165+
func (c *Channel) Notify(contact *recipient.Contact, i contracts.Incident, ev *event.Event) error {
167166
p := c.getPlugin()
168167
if p == nil {
169168
return errors.New("plugin could not be started")
@@ -174,8 +173,7 @@ func (c *Channel) Notify(contact *recipient.Contact, i contracts.Incident, ev *e
174173
contactStruct.Addresses = append(contactStruct.Addresses, &plugin.Address{Type: addr.Type, Address: addr.Address})
175174
}
176175

177-
baseUrl, _ := url.Parse(icingaweb2Url)
178-
incidentUrl := baseUrl.JoinPath("/notifications/incident")
176+
incidentUrl := c.daemonConfig.IcingaWeb2UrlParsed.JoinPath("/notifications/incident")
179177
incidentUrl.RawQuery = fmt.Sprintf("id=%d", i.ID())
180178
object := i.IncidentObject()
181179

internal/daemon/config.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ package daemon
22

33
import (
44
"errors"
5+
"fmt"
56
"github.com/creasty/defaults"
67
"github.com/icinga/icinga-go-library/config"
78
"github.com/icinga/icinga-go-library/database"
89
"github.com/icinga/icinga-go-library/logging"
910
"github.com/icinga/icinga-go-library/utils"
1011
"github.com/icinga/icinga-notifications/internal"
12+
"net/url"
1113
"os"
1214
"time"
1315
)
@@ -25,6 +27,12 @@ type ConfigFile struct {
2527
Icingaweb2URL string `yaml:"icingaweb2-url"`
2628
Database database.Config `yaml:"database"`
2729
Logging logging.Config `yaml:"logging"`
30+
31+
// IcingaWeb2UrlParsed holds the parsed Icinga Web 2 URL after validation of the config file.
32+
//
33+
// This field is not part of the YAML config and is only populated after successful validation.
34+
// The resulting URL always ends with a trailing slash, making it easier to resolve relative paths against it.
35+
IcingaWeb2UrlParsed *url.URL
2836
}
2937

3038
// SetDefaults implements the defaults.Setter interface.
@@ -44,6 +52,15 @@ func (c *ConfigFile) Validate() error {
4452
return err
4553
}
4654

55+
if c.Icingaweb2URL == "" {
56+
return errors.New("icingaweb2-url must be set")
57+
}
58+
59+
parsedUrl, err := url.Parse(c.Icingaweb2URL)
60+
if err != nil {
61+
return fmt.Errorf("invalid icingaweb2-url: %w", err)
62+
}
63+
c.IcingaWeb2UrlParsed = parsedUrl.JoinPath("/")
4764
return nil
4865
}
4966

internal/event/event.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,18 @@ type Event struct {
3636
}
3737

3838
// CompleteURL prefixes the URL with the given Icinga Web 2 base URL unless it already carries a URL or is empty.
39-
func (e *Event) CompleteURL(icingaWebBaseUrl string) {
39+
func (e *Event) CompleteURL(icingaWebBaseUrl *url.URL) {
4040
if e.URL == "" {
4141
return
4242
}
4343

44-
if !strings.HasSuffix(icingaWebBaseUrl, "/") {
45-
icingaWebBaseUrl += "/"
44+
u, err := url.Parse(strings.TrimLeft(e.URL, "/"))
45+
if err != nil {
46+
return // leave as is on parse error
4647
}
4748

48-
u, err := url.Parse(e.URL)
49-
if err != nil || u.Scheme == "" {
50-
e.URL = icingaWebBaseUrl + e.URL
49+
if !u.IsAbs() {
50+
e.URL = icingaWebBaseUrl.ResolveReference(u).String()
5151
}
5252
}
5353

internal/incident/incident.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,7 @@ func (i *Incident) notifyContact(contact *recipient.Contact, ev *event.Event, ch
640640
i.logger.Infow(fmt.Sprintf("Notify contact %q via %q of type %q", contact.FullName, ch.Name, ch.Type),
641641
zap.Int64("channel_id", chID), zap.String("event_type", ev.Type.String()))
642642

643-
err := ch.Notify(contact, i, ev, i.DaemonConfig.Icingaweb2URL)
643+
err := ch.Notify(contact, i, ev)
644644
if err != nil {
645645
i.logger.Errorw("Failed to send notification via channel plugin", zap.String("type", ch.Type), zap.Error(err))
646646
return err

internal/listener/listener.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ func (l *Listener) ProcessEvent(w http.ResponseWriter, r *http.Request) {
141141
return
142142
}
143143

144-
ev.CompleteURL(l.Resources.DaemonConfig.Icingaweb2URL)
144+
ev.CompleteURL(l.DaemonConfig.IcingaWeb2UrlParsed)
145145
ev.Time = time.Now()
146146
ev.SourceId = src.ID
147147
if ev.Type == baseEv.TypeUnknown {

0 commit comments

Comments
 (0)