diff --git a/adapters/vastbidder/bidder_macro.go b/adapters/vastbidder/bidder_macro.go index 1979a829e83..d12bb6d4183 100644 --- a/adapters/vastbidder/bidder_macro.go +++ b/adapters/vastbidder/bidder_macro.go @@ -287,12 +287,13 @@ func (tag *BidderMacro) MacroPaymentIDChain(key string) string { return "" } +// MacroSchain contains definition for Schain Parameter func (tag *BidderMacro) MacroSchain(key string) string { if tag.Request.Source == nil || tag.Request.Source.Ext == nil { return "" } - schain, _, _, err := jsonparser.Get(tag.Request.Source.Ext, "schain") + schain, _, _, err := jsonparser.Get(tag.Request.Source.Ext, MacroSchain) if err != nil { return "" @@ -305,51 +306,48 @@ func (tag *BidderMacro) MacroSchain(key string) string { return "" } - serializedSchain := schainObj.Ver + "," + fmt.Sprintf("%v", schainObj.Complete) + var serializedSchain strings.Builder - // count track the current index for schain node - count := 0 - l := len(schainObj.Nodes) + serializedSchain.WriteString(schainObj.Ver + "," + fmt.Sprintf("%v", schainObj.Complete)) for _, node := range schainObj.Nodes { - if count < l { - serializedSchain += "!" - } + + serializedSchain.WriteString("!") + if node.ASI != "" { - serializedSchain += url.PathEscape(node.ASI) + "," + serializedSchain.WriteString(url.PathEscape(node.ASI) + ",") } else { - serializedSchain += "," + serializedSchain.WriteString(",") } if node.SID != "" { - serializedSchain += url.PathEscape(node.SID) + "," + serializedSchain.WriteString(url.PathEscape(node.SID) + ",") } else { - serializedSchain += "," + serializedSchain.WriteString(",") } if node.HP != nil { - serializedSchain += url.PathEscape(fmt.Sprintf("%v", *node.HP)) + "," + // node.HP is integer pointer so 1st dereference it then convert it to string and push to serializedSchain + serializedSchain.WriteString(url.PathEscape(fmt.Sprintf("%v", *node.HP)) + ",") } else { - serializedSchain += "," + serializedSchain.WriteString(",") } if node.RID != "" { - serializedSchain += url.PathEscape(node.RID) + "," + serializedSchain.WriteString(url.PathEscape(node.RID) + ",") } else { - serializedSchain += "," + serializedSchain.WriteString(",") } if node.Name != "" { - serializedSchain += url.PathEscape(node.Name) + "," + serializedSchain.WriteString(url.PathEscape(node.Name) + ",") } else { - serializedSchain += "," + serializedSchain.WriteString(",") } if node.Domain != "" { - serializedSchain += url.PathEscape(node.Domain) - } else if node.Ext != nil { - serializedSchain += "," - serializedSchain += url.QueryEscape(string(node.Ext)) // PathEscape() does not encode the : , & and to check + serializedSchain.WriteString(url.PathEscape(node.Domain)) + } + if node.Ext != nil { + serializedSchain.WriteString("," + url.QueryEscape(string(node.Ext))) } - } - - return serializedSchain + return serializedSchain.String() } /********************* Regs *********************/ diff --git a/adapters/vastbidder/bidder_macro_test.go b/adapters/vastbidder/bidder_macro_test.go index 1d708a295b4..de90aa4a2b2 100644 --- a/adapters/vastbidder/bidder_macro_test.go +++ b/adapters/vastbidder/bidder_macro_test.go @@ -1620,7 +1620,7 @@ func TestBidderMacroKVM(t *testing.T) { } } -func TestBidderMacro_MacroSchain(t *testing.T) { +func TestMacroSchain(t *testing.T) { type fields struct { Request *openrtb2.BidRequest @@ -1692,7 +1692,7 @@ func TestBidderMacro_MacroSchain(t *testing.T) { }, { - name: "nodes_with_missing_optional_parameters", + name: "node_with_missing_all_optional_parameters", fields: fields{&openrtb2.BidRequest{Source: &openrtb2.Source{ Ext: []byte(`{ "schain":{ @@ -1711,6 +1711,27 @@ func TestBidderMacro_MacroSchain(t *testing.T) { args: args{key: "schain"}, want: "1.0,1!exchange1.com,1234&abcd,1,,,", }, + { + name: "nodes_with_missing_some_optional_parameters", + fields: fields{&openrtb2.BidRequest{Source: &openrtb2.Source{ + Ext: []byte(`{ + "schain":{ + "complete":1, + "nodes":[ + { + "asi":"exchange1.com", + "sid":"1234&abcd", + "hp":1, + "name":"publisher name" + } + ], + "ver":"1.0" + } + }`), + }}}, + args: args{key: "schain"}, + want: "1.0,1!exchange1.com,1234&abcd,1,,publisher%20name,", + }, { name: "nodes_with_extension_and_missing_optional_parameters", fields: fields{&openrtb2.BidRequest{Source: &openrtb2.Source{ @@ -1732,6 +1753,66 @@ func TestBidderMacro_MacroSchain(t *testing.T) { args: args{key: "schain"}, want: "1.0,1!exchange1.com,1234&abcd,1,,,,%7B%22k1%22%3A%22v1%22%7D", }, + { + name: "multi_nodes_with_extension", + fields: fields{&openrtb2.BidRequest{Source: &openrtb2.Source{ + Ext: []byte(`{ + "schain":{ + "complete":1, + "nodes":[ + { + "asi":"exchange1.com", + "sid":"1234&abcd", + "rid":"bid-request-1", + "name":"publisher name", + "domain":"publisher.com", + "hp":1, + "ext": "hello" + } , + { + "asi":"exchange2.com", + "sid":"abc,d", + "rid":"bid-request-2", + "name":"intermediary", + "domain":"intermediary.com", + "hp":1, + "ext":{"name":"test","num":1} + } + ], + "ver":"1.0" + } + }`), + }}}, + args: args{key: "schain"}, + want: "1.0,1!exchange1.com,1234&abcd,1,bid-request-1,publisher%20name,publisher.com,%22hello%22!exchange2.com,abc%2Cd,1,bid-request-2,intermediary,intermediary.com,%7B%22name%22%3A%22test%22%2C%22num%22%3A1%7D", + }, + { + name: "missing_schain_object", + fields: fields{&openrtb2.BidRequest{Source: &openrtb2.Source{ + Ext: []byte(`{ + "somechain":{ + "complete":1, + "nodes":[ + { + "asi":"exchange1.com", + "sid":"1234&abcd", + "hp":1, + "ext":{"k1":"v1"} + } + ], + "ver":"1.0" + } + }`), + }}}, + args: args{key: "schain"}, + want: "", + }, + { + name: "nil_schain_object", + fields: fields{&openrtb2.BidRequest{Source: nil}}, + args: args{key: "schain"}, + want: "", + }, } for _, tt := range tests {