commit 9ffce56b80990611dbb20ba6c4af4df4f9846140 from: Oliver Lowe date: Mon Jan 31 22:04:27 2022 UTC Properly encode spaces in filter expressions This is a bit tricky. url.QueryEscape() encodes spaces in queries as "+", but Icinga2 wants them as "%20". A test case is included because this was kinda tricky to debug. commit - 64e18a8d1ef9f178f91aed840a371f3785c4d188 commit + 9ffce56b80990611dbb20ba6c4af4df4f9846140 blob - 7c35d24aaef3e10d308c0e2cd9547e15b25d392c blob + 4b981c1ef6945cc4f45b64af54f0ec37211e1deb --- http.go +++ http.go @@ -5,6 +5,7 @@ import ( "io" "net/http" "net/url" + "strings" ) const versionPrefix = "/v1" @@ -29,15 +30,22 @@ func NewRequest(method, url, username, password string return req, nil } +// filterEncode url-encodes the filter expression expr in the required +// format to be included in a request. Notably, spaces need to be encoded +// as "%20", not "+" as returned by the url package. +func filterEncode(expr string) string { + v := url.Values{} + v.Set("filter", expr) + return strings.ReplaceAll(v.Encode(), "+", "%20") +} + func (c *Client) get(path, filter string) (*http.Response, error) { u, err := url.Parse("https://" + c.addr + versionPrefix + path) if err != nil { return nil, err } if filter != "" { - v := url.Values{} - v.Set("filter", filter) - u.RawQuery = v.Encode() + u.RawQuery = filterEncode(filter) } req, err := NewRequest(http.MethodGet, u.String(), c.username, c.password, nil) if err != nil { blob - /dev/null blob + 91468315a23fb23055b378cfef60bdd8c091ffa1 (mode 644) --- /dev/null +++ http_test.go @@ -0,0 +1,13 @@ +package icinga + +import "testing" + +func TestFilterEncode(t *testing.T) { + expr := `match("*.example.com"), host.name) && "test" in host.groups` + want := "filter=match%28%22%2A.example.com%22%29%2C%20host.name%29%20%26%26%20%22test%22%20in%20host.groups" + got := filterEncode(expr) + if want != got { + t.Fail() + } + t.Logf("want %s, got %s", want, got) +} blob - e6e5d8c1eac900a0fce5682be080cdc969454f7e blob + 46576a0932c31df245fbdeb69470db5308629138 --- icinga_test.go +++ icinga_test.go @@ -200,6 +200,6 @@ func TestNonExistentService(t *testing.T) { if err == nil { t.Fail() } - t.Logf("lookup %s: %v", name, err) + t.Log(err) t.Logf("%+v", service) }