Skip to content

Commit 9cab775

Browse files
authored
[Filebeat] [httpjson] Add support for single string containing multiple relation-types in getRFC5988Link (#32811)
* case with single string but multiple rel * misspell lint error * Add ascii doc
1 parent 6c1620a commit 9cab775

3 files changed

Lines changed: 83 additions & 4 deletions

File tree

CHANGELOG.next.asciidoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ https://github.com/elastic/beats/compare/v8.2.0\...main[Check the HEAD diff]
117117
- add documentation for decode_xml_wineventlog processor field mappings. {pull}32456[32456]
118118
- httpjson input: Add request tracing logger. {issue}32402[32402] {pull}32412[32412]
119119
- Add cloudflare R2 to provider list in AWS S3 input. {pull}32620[32620]
120+
- Add support for single string containing multiple relation-types in getRFC5988Link. {pull}32811[32811]
120121

121122
*Auditbeat*
122123

x-pack/filebeat/input/httpjson/value_tpl.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,8 @@ func parseTimestampNano(ns int64) time.Time {
214214

215215
var regexpLinkRel = regexp.MustCompile(`<(.*)>;.*\srel\="?([^;"]*)`)
216216

217-
func getRFC5988Link(rel string, links []string) string {
218-
for _, link := range links {
217+
func getMatchLink(rel string, linksSplit []string) string {
218+
for _, link := range linksSplit {
219219
if !regexpLinkRel.MatchString(link) {
220220
continue
221221
}
@@ -231,10 +231,17 @@ func getRFC5988Link(rel string, links []string) string {
231231

232232
return matches[1]
233233
}
234-
235234
return ""
236235
}
237236

237+
func getRFC5988Link(rel string, links []string) string {
238+
if len(links) == 1 && strings.Count(links[0], "rel=") > 1 {
239+
linksSplit := strings.Split(links[0], ",")
240+
return getMatchLink(rel, linksSplit)
241+
}
242+
return getMatchLink(rel, links)
243+
}
244+
238245
func toInt(v interface{}) int64 {
239246
vv := reflect.ValueOf(v)
240247
switch vv.Kind() {

x-pack/filebeat/input/httpjson/value_tpl_test.go

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,24 @@ func TestValueTpl(t *testing.T) {
189189
expectedVal: "2020-11-05 13:25:32 +0000 UTC",
190190
},
191191
{
192-
name: "func getRFC5988Link",
192+
name: "func getRFC5988Link single rel matches",
193+
value: `[[ getRFC5988Link "next" .last_response.header.Link ]]`,
194+
paramCtx: &transformContext{
195+
firstEvent: &mapstr.M{},
196+
lastEvent: &mapstr.M{},
197+
lastResponse: newTestResponse(
198+
nil,
199+
http.Header{"Link": []string{
200+
`<https://example.com/api/v1/users?after=00ubfjQEMYBLRUWIEDKK>; title="Page 3"; rel="next"`,
201+
}},
202+
"",
203+
),
204+
},
205+
paramTr: transformable{},
206+
expectedVal: "https://example.com/api/v1/users?after=00ubfjQEMYBLRUWIEDKK",
207+
},
208+
{
209+
name: "func getRFC5988Link multiple rel as separate strings matches",
193210
value: `[[ getRFC5988Link "previous" .last_response.header.Link ]]`,
194211
paramCtx: &transformContext{
195212
firstEvent: &mapstr.M{},
@@ -206,6 +223,60 @@ func TestValueTpl(t *testing.T) {
206223
paramTr: transformable{},
207224
expectedVal: "https://example.com/api/v1/users?before=00ubfjQEMYBLRUWIEDKK",
208225
},
226+
{
227+
name: "func getRFC5988Link multiple rel as separate strings in random order matches",
228+
value: `[[ getRFC5988Link "previous" .last_response.header.Link ]]`,
229+
paramCtx: &transformContext{
230+
firstEvent: &mapstr.M{},
231+
lastEvent: &mapstr.M{},
232+
lastResponse: newTestResponse(
233+
nil,
234+
http.Header{"Link": []string{
235+
`<https://example.com/api/v1/users?before=00ubfjQEMYBLRUWIEDKK>; title="Page 1"; rel="previous"`,
236+
`<https://example.com/api/v1/users?after=00ubfjQEMYBLRUWIEDKK>; title="Page 3"; rel="next"`,
237+
}},
238+
"",
239+
),
240+
},
241+
paramTr: transformable{},
242+
expectedVal: "https://example.com/api/v1/users?before=00ubfjQEMYBLRUWIEDKK",
243+
},
244+
{
245+
name: "func getRFC5988Link multiple rel as single string matches",
246+
value: `[[ getRFC5988Link "previous" .last_response.header.Link ]]`,
247+
paramCtx: &transformContext{
248+
firstEvent: &mapstr.M{},
249+
lastEvent: &mapstr.M{},
250+
lastResponse: newTestResponse(
251+
nil,
252+
http.Header{"Link": []string{
253+
`<https://example.com/api/v1/users?before=00ubfjQEMYBLRUWIEDKK>; title="Page 1"; rel="previous",
254+
<https://example.com/api/v1/users?after=00ubfjQEMYBLRUWIEDKK>; title="Page 3"; rel="next"`,
255+
}},
256+
"",
257+
),
258+
},
259+
paramTr: transformable{},
260+
expectedVal: "https://example.com/api/v1/users?before=00ubfjQEMYBLRUWIEDKK",
261+
},
262+
{
263+
name: "func getRFC5988Link multiple rel as single string in random order matches",
264+
value: `[[ getRFC5988Link "next" .last_response.header.Link ]]`,
265+
paramCtx: &transformContext{
266+
firstEvent: &mapstr.M{},
267+
lastEvent: &mapstr.M{},
268+
lastResponse: newTestResponse(
269+
nil,
270+
http.Header{"Link": []string{
271+
`<https://example.com/api/v1/users?before=00ubfjQEMYBLRUWIEDKK>; title="Page 1"; rel="previous",
272+
<https://example.com/api/v1/users?after=00ubfjQEMYBLRUWIEDKK>; title="Page 3"; rel="next"`,
273+
}},
274+
"",
275+
),
276+
},
277+
paramTr: transformable{},
278+
expectedVal: "https://example.com/api/v1/users?after=00ubfjQEMYBLRUWIEDKK",
279+
},
209280
{
210281
name: "func getRFC5988Link does not match",
211282
value: `[[ getRFC5988Link "previous" .last_response.header.Link ]]`,

0 commit comments

Comments
 (0)