Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions endpoints/openrtb2/auction.go
Original file line number Diff line number Diff line change
Expand Up @@ -1778,7 +1778,7 @@ func (deps *endpointDeps) processStoredRequests(requestJson []byte, impInfo []Im
}

// Extract Passthrough from Merged Imp
passthrough, _, _, err := jsonparser.Get(resolvedImp, "ext", "prebid", "passthrough")
passthrough, _, _, err := getExtPrebidValue(resolvedImp, "passthrough")
if err != nil && err != jsonparser.KeyPathNotFoundError {
return nil, nil, []error{err}
}
Expand Down Expand Up @@ -1814,7 +1814,7 @@ func (deps *endpointDeps) processStoredRequests(requestJson []byte, impInfo []Im
func parseImpInfo(requestJson []byte) (impData []ImpExtPrebidData, errs []error) {
if impArray, dataType, _, err := jsonparser.Get(requestJson, "imp"); err == nil && dataType == jsonparser.Array {
_, _ = jsonparser.ArrayEach(impArray, func(imp []byte, _ jsonparser.ValueType, _ int, _ error) {
impExtData, _, _, _ := jsonparser.Get(imp, "ext", "prebid")
impExtData, _, _, _ := getExtPrebidValue(imp)
var impExtPrebid openrtb_ext.ExtImpPrebid
if impExtData != nil {
if err := jsonutil.Unmarshal(impExtData, &impExtPrebid); err != nil {
Expand All @@ -1828,6 +1828,20 @@ func parseImpInfo(requestJson []byte) (impData []ImpExtPrebidData, errs []error)
return
}

// getExtPrebidValue reads <subKeys> from the prebid block of the given
// JSON. Top-level alias resolution: when ext.openads exists it is used
// in full; otherwise ext.prebid is used. ext.prebid is never consulted
// when ext.openads exists, even for subkeys missing from openads.
// Outbound emission is unaffected.
func getExtPrebidValue(data []byte, subKeys ...string) ([]byte, jsonparser.ValueType, int, error) {
rootKey := openrtb_ext.PrebidExtKey
if _, dt, _, err := jsonparser.Get(data, "ext", openrtb_ext.OpenAdsExtKey); err == nil && dt != jsonparser.NotExist {
rootKey = openrtb_ext.OpenAdsExtKey
}
path := append([]string{"ext", rootKey}, subKeys...)
return jsonparser.Get(data, path...)
}

type ImpExtPrebidData struct {
Imp json.RawMessage
ImpExtPrebid openrtb_ext.ExtImpPrebid
Expand All @@ -1838,7 +1852,7 @@ type ImpExtPrebidData struct {
// (e.g. malformed json, id not a string, etc).
func getStoredRequestId(data []byte) (string, bool, error) {
// These keys must be kept in sync with openrtb_ext.ExtStoredRequest
storedRequestId, dataType, _, err := jsonparser.Get(data, "ext", openrtb_ext.PrebidExtKey, "storedrequest", "id")
storedRequestId, dataType, _, err := getExtPrebidValue(data, "storedrequest", "id")

if dataType == jsonparser.NotExist {
return "", false, nil
Expand Down
65 changes: 65 additions & 0 deletions endpoints/openrtb2/auction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1078,6 +1078,71 @@ func TestReferer(t *testing.T) {
}
}

func TestParseImpInfoOpenAdsAlias(t *testing.T) {
tests := []struct {
name string
input string
wantImp openrtb_ext.ExtImpPrebid
}{
{
name: "openads only at imp.ext",
input: `{"imp":[{"id":"imp1","ext":{"openads":{"storedrequest":{"id":"42"},"options":{"echovideoattrs":true}}}}]}`,
wantImp: openrtb_ext.ExtImpPrebid{StoredRequest: &openrtb_ext.ExtStoredRequest{ID: "42"}, Options: &openrtb_ext.Options{EchoVideoAttrs: true}},
},
{
name: "both keys, openads wins",
input: `{"imp":[{"id":"imp1","ext":{"prebid":{"storedrequest":{"id":"FROM_PREBID"}},"openads":{"storedrequest":{"id":"FROM_OPENADS"}}}}]}`,
wantImp: openrtb_ext.ExtImpPrebid{StoredRequest: &openrtb_ext.ExtStoredRequest{ID: "FROM_OPENADS"}},
},
}

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
impInfo, errs := parseImpInfo([]byte(tc.input))
assert.Empty(t, errs, "no errors expected")
if assert.Len(t, impInfo, 1) {
assert.Equal(t, tc.wantImp, impInfo[0].ImpExtPrebid)
}
})
}
}

func TestGetStoredRequestIdOpenAdsAlias(t *testing.T) {
tests := []struct {
name string
input string
wantID string
wantHas bool
}{
{
name: "openads alias",
input: `{"ext":{"openads":{"storedrequest":{"id":"sr-99"}}}}`,
wantID: "sr-99",
wantHas: true,
},
{
name: "openads wins over prebid",
input: `{"ext":{"prebid":{"storedrequest":{"id":"FROM_PREBID"}},"openads":{"storedrequest":{"id":"FROM_OPENADS"}}}}`,
wantID: "FROM_OPENADS",
wantHas: true,
},
{
name: "neither",
input: `{"ext":{"data":{}}}`,
wantID: "",
wantHas: false,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
id, has, err := getStoredRequestId([]byte(tc.input))
assert.NoError(t, err)
assert.Equal(t, tc.wantHas, has)
assert.Equal(t, tc.wantID, id)
})
}
}

func TestParseImpInfoSingleImpression(t *testing.T) {

expectedRes := []ImpExtPrebidData{
Expand Down
34 changes: 24 additions & 10 deletions exchange/exchange_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5828,17 +5828,26 @@ func parseRequestAliases(r openrtb2.BidRequest) (map[string]string, error) {
return nil, nil
}

ext := struct {
Prebid struct {
Aliases map[string]string `json:"aliases"`
} `json:"prebid"`
}{}

// Top-level alias resolution: if ext.openads is present it is used
// in full; ext.prebid is ignored entirely in that case.
var ext map[string]json.RawMessage
if err := jsonutil.Unmarshal(r.Ext, &ext); err != nil {
return nil, err
}

return ext.Prebid.Aliases, nil
src, ok := ext[openrtb_ext.OpenAdsExtKey]
if !ok {
src, ok = ext[openrtb_ext.PrebidExtKey]
}
if !ok {
return nil, nil
}
var pe struct {
Aliases map[string]string `json:"aliases"`
}
if err := jsonutil.Unmarshal(src, &pe); err != nil {
return nil, err
}
return pe.Aliases, nil
}

func getInfoFromImp(req *openrtb_ext.RequestWrapper) (json.RawMessage, string, error) {
Expand All @@ -5851,9 +5860,14 @@ func getInfoFromImp(req *openrtb_ext.RequestWrapper) (json.RawMessage, string, e
return nil, "", err
}

// Top-level alias resolution: openads wins outright when present.
prebidJSON := bidderExts[openrtb_ext.OpenAdsExtKey]
if prebidJSON == nil {
prebidJSON = bidderExts[openrtb_ext.PrebidExtKey]
}
var extPrebid openrtb_ext.ExtImpPrebid
if bidderExts[openrtb_ext.PrebidExtKey] != nil {
if err := jsonutil.UnmarshalValid(bidderExts[openrtb_ext.PrebidExtKey], &extPrebid); err != nil {
if prebidJSON != nil {
if err := jsonutil.UnmarshalValid(prebidJSON, &extPrebid); err != nil {
return nil, "", err
}
}
Expand Down
136 changes: 136 additions & 0 deletions exchange/exchangetest/aliases-openads-key.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
{
"incomingRequest": {
"ortbRequest": {
"id": "some-request-id",
"site": {
"page": "test.somepage.com"
},
"imp": [
{
"id": "my-imp-id",
"video": {
"mimes": [
"video/mp4"
]
},
"ext": {
"openads": {
"bidder": {
"thetradedesk": {
"publisherId": "pub1",
"supplySourceId": "src1"
},
"ttdalias": {
"publisherId": "pub2",
"supplySourceId": "src2"
}
}
}
}
}
],
"ext": {
"openads": {
"aliases": {
"ttdalias": "thetradedesk"
}
}
}
},
"usersyncs": {
"thetradedesk": "123"
}
},
"outgoingRequests": {
"thetradedesk": {
"expectRequest": {
"ortbRequest": {
"id": "some-request-id",
"site": {
"page": "test.somepage.com"
},
"user": {
"buyeruid": "123"
},
"imp": [
{
"id": "my-imp-id",
"video": {
"mimes": [
"video/mp4"
]
},
"ext": {
"bidder": {
"publisherId": "pub1",
"supplySourceId": "src1"
}
}
}
]
}
},
"mockResponse": {
"errors": [
"thetradedesk-error"
]
}
},
"ttdalias": {
"expectRequest": {
"ortbRequest": {
"id": "some-request-id",
"site": {
"page": "test.somepage.com"
},
"user": {
"buyeruid": "123"
},
"imp": [
{
"id": "my-imp-id",
"video": {
"mimes": [
"video/mp4"
]
},
"ext": {
"bidder": {
"publisherId": "pub2",
"supplySourceId": "src2"
}
}
}
],
"ext": {
"prebid": {
"aliases": {
"ttdalias": "thetradedesk"
}
}
}
}
},
"mockResponse": {
"errors": [
"ttdalias-error"
]
}
}
},
"response": {
"bids": {
"id": "some-request-id",
"ext": {
"errors": {
"thetradedesk": [
"thetradedesk-error"
],
"ttdalias": [
"ttdalias-error"
]
}
}
}
}
}
Loading
Loading