commit 9ffce56b80990611dbb20ba6c4af4df4f9846140
parent 64e18a8d1ef9f178f91aed840a371f3785c4d188
Author: Oliver Lowe <o@olowe.co>
Date: Wed, 26 Jan 2022 16:54:32 +1100
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.
Diffstat:
3 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/http.go b/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, body io.Reader) (*http.R
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 {
diff --git a/http_test.go b/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)
+}
diff --git a/icinga_test.go b/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)
}