diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index bb8ecb733a66..4337e951fbf8 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -226,6 +226,7 @@ for a few releases. Please use other tools provided by Elastic to fetch data fro - Fix initialization of http client in Cloudfoundry input. {issue}28271[28271] {pull}28277[28277] - Correctly track bytes read when max_bytes is exceeded. {issue}28317[28317] {pull}28352[28352] - Fix aws-s3 input by checking if GetObject API call response content type exists. {pull}28457[28457] +- Set `url` as a pointer in the `httpjson` template context to ensure access to all methods. {pull}28695[28695] *Heartbeat* diff --git a/x-pack/filebeat/input/httpjson/internal/v2/request_test.go b/x-pack/filebeat/input/httpjson/internal/v2/request_test.go index 6e35d5cc45f5..898043aa8ddf 100644 --- a/x-pack/filebeat/input/httpjson/internal/v2/request_test.go +++ b/x-pack/filebeat/input/httpjson/internal/v2/request_test.go @@ -95,7 +95,7 @@ func TestCtxAfterDoRequest(t *testing.T) { assert.EqualValues(t, &response{ page: 1, - url: newURL(fmt.Sprintf("%s?%s", testServer.URL, "%24filter=alertCreationTime+ge+2002-10-02T14%3A50%3A00Z")), + url: *(newURL(fmt.Sprintf("%s?%s", testServer.URL, "%24filter=alertCreationTime+ge+2002-10-02T14%3A50%3A00Z"))), body: common.MapStr{"@timestamp": "2002-10-02T15:00:00Z", "foo": "bar"}, }, lastResp, @@ -127,7 +127,7 @@ func TestCtxAfterDoRequest(t *testing.T) { assert.EqualValues(t, &response{ page: 1, - url: newURL(fmt.Sprintf("%s?%s", testServer.URL, "%24filter=alertCreationTime+ge+2002-10-02T15%3A00%3A00Z")), + url: *(newURL(fmt.Sprintf("%s?%s", testServer.URL, "%24filter=alertCreationTime+ge+2002-10-02T15%3A00%3A00Z"))), body: common.MapStr{"@timestamp": "2002-10-02T15:00:01Z", "foo": "bar"}, }, lastResp, diff --git a/x-pack/filebeat/input/httpjson/internal/v2/response.go b/x-pack/filebeat/input/httpjson/internal/v2/response.go index 7513c8476b70..7fb7f904f409 100644 --- a/x-pack/filebeat/input/httpjson/internal/v2/response.go +++ b/x-pack/filebeat/input/httpjson/internal/v2/response.go @@ -175,10 +175,12 @@ func (resp *response) templateValues() common.MapStr { return common.MapStr{} } return common.MapStr{ - "header": resp.header.Clone(), - "page": resp.page, - "url.value": resp.url.String(), - "url.params": resp.url.Query(), - "body": resp.body, + "header": resp.header.Clone(), + "page": resp.page, + "url": common.MapStr{ + "value": resp.url.String(), + "params": resp.url.Query(), + }, + "body": resp.body, } } diff --git a/x-pack/filebeat/input/httpjson/internal/v2/response_test.go b/x-pack/filebeat/input/httpjson/internal/v2/response_test.go index f3dd507b3949..9660d6c2e73f 100644 --- a/x-pack/filebeat/input/httpjson/internal/v2/response_test.go +++ b/x-pack/filebeat/input/httpjson/internal/v2/response_test.go @@ -16,7 +16,7 @@ import ( func TestTemplateValues(t *testing.T) { resp := &response{ page: 1, - url: newURL("http://test?p1=v1"), + url: *(newURL("http://test?p1=v1")), header: http.Header{ "Authorization": []string{"Bearer token"}, }, @@ -28,8 +28,10 @@ func TestTemplateValues(t *testing.T) { vals := resp.templateValues() assert.Equal(t, resp.page, vals["page"]) - assert.Equal(t, resp.url.String(), vals["url.value"]) - assert.EqualValues(t, resp.url.Query(), vals["url.params"]) + v, _ := vals.GetValue("url.value") + assert.Equal(t, resp.url.String(), v) + v, _ = vals.GetValue("url.params") + assert.EqualValues(t, resp.url.Query(), v) assert.EqualValues(t, resp.header, vals["header"]) assert.EqualValues(t, resp.body, vals["body"]) diff --git a/x-pack/filebeat/input/httpjson/internal/v2/transform.go b/x-pack/filebeat/input/httpjson/internal/v2/transform.go index 577edc2ba857..2bb50dabce75 100644 --- a/x-pack/filebeat/input/httpjson/internal/v2/transform.go +++ b/x-pack/filebeat/input/httpjson/internal/v2/transform.go @@ -161,7 +161,7 @@ func (tr transformable) body() common.MapStr { } func (tr transformable) setURL(v url.URL) { - tr.Put("url", v) + tr.Put("url", &v) } func (tr transformable) url() url.URL { @@ -170,12 +170,12 @@ func (tr transformable) url() url.URL { return url.URL{} } - u, ok := val.(url.URL) + u, ok := val.(*url.URL) if !ok { return url.URL{} } - return u + return *u } type transform interface { diff --git a/x-pack/filebeat/input/httpjson/internal/v2/transform_set_test.go b/x-pack/filebeat/input/httpjson/internal/v2/transform_set_test.go index 6a3a2d8915cf..4b3904f5d2d0 100644 --- a/x-pack/filebeat/input/httpjson/internal/v2/transform_set_test.go +++ b/x-pack/filebeat/input/httpjson/internal/v2/transform_set_test.go @@ -239,7 +239,7 @@ func TestDifferentSetValueTypes(t *testing.T) { assert.EqualValues(t, exp, tr.body()) } -func newURL(u string) url.URL { +func newURL(u string) *url.URL { url, _ := url.Parse(u) - return *url + return url } diff --git a/x-pack/filebeat/input/httpjson/internal/v2/value_tpl_test.go b/x-pack/filebeat/input/httpjson/internal/v2/value_tpl_test.go index 06768eb478a8..41ae1feced8f 100644 --- a/x-pack/filebeat/input/httpjson/internal/v2/value_tpl_test.go +++ b/x-pack/filebeat/input/httpjson/internal/v2/value_tpl_test.go @@ -27,6 +27,18 @@ func TestValueTpl(t *testing.T) { setup func() teardown func() }{ + { + name: "can access Go types in context", + value: `[[.last_response.header.Get "foo"]] [[.last_response.url.params.Get "foo"]] [[.url.Host]] [[.url.Query.Get "bar"]]`, + paramCtx: &transformContext{ + firstEvent: &common.MapStr{}, + lastEvent: &common.MapStr{}, + lastResponse: newTestResponse(common.MapStr{"param": 25}, http.Header{"Foo": []string{"bar"}}, "http://localhost?foo=bar"), + }, + paramTr: transformable{"url": newURL("http://localhost?bar=bazz")}, + paramDefVal: "", + expectedVal: "bar bar localhost bazz", + }, { name: "can render values from ctx", value: "[[.last_response.body.param]]", @@ -424,7 +436,7 @@ func newTestResponse(body common.MapStr, header http.Header, url string) *respon resp.header = header } if url != "" { - resp.url = newURL(url) + resp.url = *(newURL(url)) } return resp }