Skip to content

Commit 85f8d12

Browse files
committed
eventstream: mimic PHP's rawurlencode function
As Icinga Web uses rawurldecode instead of rawurlencode, the space to plus substitution cannot be used.
1 parent d3a57ff commit 85f8d12

File tree

4 files changed

+43
-3
lines changed

4 files changed

+43
-3
lines changed

internal/eventstream/client.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ func (client *Client) buildCommonEvent(host, service string) (*event.Event, erro
156156
eventName = host + "!" + service
157157

158158
eventUrl = eventUrl.JoinPath("/icingadb/service")
159-
eventUrl.RawQuery = "name=" + url.PathEscape(service) + "&host.name=" + url.PathEscape(host)
159+
eventUrl.RawQuery = "name=" + rawurlencode(service) + "&host.name=" + rawurlencode(host)
160160

161161
eventTags = map[string]string{
162162
"host": host,
@@ -174,7 +174,7 @@ func (client *Client) buildCommonEvent(host, service string) (*event.Event, erro
174174
eventName = host
175175

176176
eventUrl = eventUrl.JoinPath("/icingadb/host")
177-
eventUrl.RawQuery = "name=" + url.PathEscape(host)
177+
eventUrl.RawQuery = "name=" + rawurlencode(host)
178178

179179
eventTags = map[string]string{
180180
"host": host,

internal/eventstream/client_api.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ func (client *Client) queryObjectsApi(urlPaths []string, method string, body io.
7474
// queryObjectsApiDirect performs a direct resp. "fast" API query against an object, optionally identified by its name.
7575
func (client *Client) queryObjectsApiDirect(objType, objName string) (io.ReadCloser, error) {
7676
return client.queryObjectsApi(
77-
[]string{"/v1/objects/", objType + "s/", url.PathEscape(objName)},
77+
[]string{"/v1/objects/", objType + "s/", rawurlencode(objName)},
7878
http.MethodGet,
7979
nil,
8080
map[string]string{"Accept": "application/json"})

internal/eventstream/util.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99
"github.com/icinga/icingadb/pkg/icingadb"
1010
"github.com/icinga/icingadb/pkg/logging"
1111
"go.uber.org/zap"
12+
"net/url"
13+
"strings"
1214
)
1315

1416
// makeProcessEvent creates a closure function to process received events.
@@ -69,3 +71,15 @@ func makeProcessEvent(
6971
}
7072
}
7173
}
74+
75+
// rawurlencode mimics PHP's rawurlencode to be used for parameter encoding.
76+
//
77+
// Icinga Web uses rawurldecode instead of urldecode, which, as its main difference, does not honor the plus char ('+')
78+
// as a valid substitution for space (' '). Unfortunately, Go's url.QueryEscape does this very substitution and
79+
// url.PathEscape does a bit too less and has a misleading name on top.
80+
//
81+
// - https://www.php.net/manual/en/function.rawurlencode.php
82+
// - https://github.com/php/php-src/blob/php-8.2.12/ext/standard/url.c#L538
83+
func rawurlencode(s string) string {
84+
return strings.ReplaceAll(url.QueryEscape(s), "+", "%20")
85+
}

internal/eventstream/util_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package eventstream
2+
3+
import (
4+
"github.com/stretchr/testify/assert"
5+
"testing"
6+
)
7+
8+
func TestRawurlencode(t *testing.T) {
9+
tests := []struct {
10+
name string
11+
in string
12+
want string
13+
}{
14+
{"empty", "", ""},
15+
{"printable", "abcABC0123", "abcABC0123"},
16+
{"space", "foo bar", "foo%20bar"},
17+
{"plus", "foo+bar", "foo%2Bbar"},
18+
{"slash", "foo/bar", "foo%2Fbar"},
19+
{"percent", "foo%bar", "foo%25bar"},
20+
}
21+
for _, tt := range tests {
22+
t.Run(tt.name, func(t *testing.T) {
23+
assert.Equal(t, tt.want, rawurlencode(tt.in))
24+
})
25+
}
26+
}

0 commit comments

Comments
 (0)