Skip to content

Commit

Permalink
This CL introduces currency declaration support in adapters bid respo…
Browse files Browse the repository at this point in the history
…nses as described in prebid#280.

This change covers:
* Introducing a new struct `BidderResponse` carrying the list of bids `TypedBid` and a currency as string
* Change the existing adapters using the new API `MakeBids` so it start using the new `BidderResponse` struct

This change doesn't cover:
* Doesn't change the former API using `Call` method
* Any check done on Pre-bid server side to discard any bid received with an invalid currency
  (such as unknown, or a one that wasn't authorized in a first place via trhe bid request)
* Any mechanisms on tranlating currency rates

As a nice next step, we should implement the mechanism to filter bids having invalid currencies on not allowed ones.
It will allow to protect both parties from currencies mismatch / discrepancies.
  • Loading branch information
Benjamin Chastanier committed May 4, 2018
1 parent 1157580 commit 0ad0d1b
Show file tree
Hide file tree
Showing 29 changed files with 479 additions and 351 deletions.
27 changes: 18 additions & 9 deletions adapters/adapterstest/test_json.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,24 +101,28 @@ func runSpec(t *testing.T, filename string, spec *testSpec, bidder adapters.Bidd
diffErrorLists(t, fmt.Sprintf("%s: MakeRequests", filename), errs, spec.MakeRequestErrors)
diffHttpRequestLists(t, filename, actualReqs, spec.HttpCalls)

var bids = make([]*adapters.TypedBid, 0, len(spec.Bids))
bidResponses := make([]*adapters.BidderResponse, 0)

var bidsErrs = make([]error, 0, len(spec.MakeBidsErrors))
for i := 0; i < len(actualReqs); i++ {
theseBids, theseErrs := bidder.MakeBids(&spec.BidRequest, spec.HttpCalls[i].Request.ToRequestData(t), spec.HttpCalls[i].Response.ToResponseData(t))
bids = append(bids, theseBids...)
thisBidResponse, theseErrs := bidder.MakeBids(&spec.BidRequest, spec.HttpCalls[i].Request.ToRequestData(t), spec.HttpCalls[i].Response.ToResponseData(t))
bidsErrs = append(bidsErrs, theseErrs...)
bidResponses = append(bidResponses, thisBidResponse)
}

diffErrorLists(t, fmt.Sprintf("%s: MakeBids", filename), bidsErrs, spec.MakeBidsErrors)
diffBidLists(t, filename, bids, spec.Bids)

for i := 0; i < len(spec.BidResponses); i++ {
diffBidLists(t, filename, bidResponses[i].Bids, spec.BidResponses[i].Bids)
}
}

type testSpec struct {
BidRequest openrtb.BidRequest `json:"mockBidRequest"`
HttpCalls []httpCall `json:"httpCalls"`
Bids []expectedBid `json:"expectedBids"`
MakeRequestErrors []string `json:"expectedMakeRequestsErrors"`
MakeBidsErrors []string `json:"expectedMakeBidsErrors"`
BidRequest openrtb.BidRequest `json:"mockBidRequest"`
HttpCalls []httpCall `json:"httpCalls"`
BidResponses []expectedBidResponse `json:"expectedBidResponses"`
MakeRequestErrors []string `json:"expectedMakeRequestsErrors"`
MakeBidsErrors []string `json:"expectedMakeBidsErrors"`
}

func (spec *testSpec) expectsErrors() bool {
Expand Down Expand Up @@ -156,6 +160,11 @@ func (resp *httpResponse) ToResponseData(t *testing.T) *adapters.ResponseData {
}
}

type expectedBidResponse struct {
Bids []expectedBid `json:"bids"`
Currency string `json:"currency"`
}

type expectedBid struct {
Bid json.RawMessage `json:"bid"`
Type string `json:"type"`
Expand Down
14 changes: 7 additions & 7 deletions adapters/adform/adform.go
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ func openRtbToAdformRequest(request *openrtb.BidRequest) (*adformRequest, []erro
}, errors
}

func (a *AdformAdapter) MakeBids(internalRequest *openrtb.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) ([]*adapters.TypedBid, []error) {
func (a *AdformAdapter) MakeBids(internalRequest *openrtb.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
if response.StatusCode == http.StatusNoContent {
return nil, nil
}
Expand All @@ -366,13 +366,13 @@ func (a *AdformAdapter) MakeBids(internalRequest *openrtb.BidRequest, externalRe
return nil, []error{err}
}

bids := toOpenRtbBids(adformOutput, internalRequest)
bidResponse := toOpenRtbBidResponse(adformOutput, internalRequest)

return bids, nil
return bidResponse, nil
}

func toOpenRtbBids(adformBids []*adformBid, r *openrtb.BidRequest) []*adapters.TypedBid {
bids := make([]*adapters.TypedBid, 0, len(adformBids))
func toOpenRtbBidResponse(adformBids []*adformBid, r *openrtb.BidRequest) *adapters.BidderResponse {
bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(adformBids))

for i, bid := range adformBids {
if bid.Banner == "" || bid.ResponseType != "banner" {
Expand All @@ -388,8 +388,8 @@ func toOpenRtbBids(adformBids []*adformBid, r *openrtb.BidRequest) []*adapters.T
DealID: bid.DealId,
}

bids = append(bids, &adapters.TypedBid{Bid: &openRtbBid, BidType: openrtb_ext.BidTypeBanner})
bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{Bid: &openRtbBid, BidType: openrtb_ext.BidTypeBanner})
}

return bids
return bidResponse
}
28 changes: 14 additions & 14 deletions adapters/adform/adform_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -369,18 +369,18 @@ func TestOpenRTBStandardResponse(t *testing.T) {
httpResponse := &adapters.ResponseData{StatusCode: http.StatusOK, Body: responseBody}

bidder := new(AdformAdapter)
bids, errs := bidder.MakeBids(request, nil, httpResponse)
bidResponse, errs := bidder.MakeBids(request, nil, httpResponse)

if len(bids) != 2 {
t.Fatalf("Expected 2 bids. Got %d", len(bids))
if len(bidResponse.Bids) != 2 {
t.Fatalf("Expected 2 bids. Got %d", len(bidResponse.Bids))
}
if len(errs) != 0 {
t.Errorf("Expected 0 errors. Got %d", len(errs))
}

for _, typeBid := range bids {
for _, typeBid := range bidResponse.Bids {
if typeBid.BidType != openrtb_ext.BidTypeBanner {
t.Errorf("Expected a banner bid. Got: %s", bids[0].BidType)
t.Errorf("Expected a banner bid. Got: %s", bidResponse.Bids[0].BidType)
}
bid := typeBid.Bid
matched := false
Expand Down Expand Up @@ -411,22 +411,22 @@ func TestOpenRTBStandardResponse(t *testing.T) {
func TestOpenRTBSurpriseResponse(t *testing.T) {
bidder := new(AdformAdapter)

bids, errs := bidder.MakeBids(nil, nil,
bidResponse, errs := bidder.MakeBids(nil, nil,
&adapters.ResponseData{StatusCode: http.StatusNoContent, Body: []byte("")})
if bids != nil && errs != nil {
t.Fatalf("Expected no bids and no errors. Got %d bids and %d", len(bids), len(errs))
if bidResponse != nil && errs != nil {
t.Fatalf("Expected no bids and no errors. Got %d bids and %d", len(bidResponse.Bids), len(errs))
}

bids, errs = bidder.MakeBids(nil, nil,
bidResponse, errs = bidder.MakeBids(nil, nil,
&adapters.ResponseData{StatusCode: http.StatusServiceUnavailable, Body: []byte("")})
if bids != nil || len(errs) != 1 {
t.Fatalf("Expected one error and no bids. Got %d bids and %d", len(bids), len(errs))
if bidResponse != nil || len(errs) != 1 {
t.Fatalf("Expected one error and no bids. Got %d bids and %d", len(bidResponse.Bids), len(errs))
}

bids, errs = bidder.MakeBids(nil, nil,
bidResponse, errs = bidder.MakeBids(nil, nil,
&adapters.ResponseData{StatusCode: http.StatusOK, Body: []byte("{:'not-valid-json'}")})
if bids != nil || len(errs) != 1 {
t.Fatalf("Expected one error and no bids. Got %d bids and %d", len(bids), len(errs))
if bidResponse != nil || len(errs) != 1 {
t.Fatalf("Expected one error and no bids. Got %d bids and %d", len(bidResponse.Bids), len(errs))
}
}

Expand Down
9 changes: 4 additions & 5 deletions adapters/adtelligent/adtelligent.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func (a *AdtelligentAdapter) MakeRequests(request *openrtb.BidRequest) ([]*adapt

}

func (a *AdtelligentAdapter) MakeBids(bidReq *openrtb.BidRequest, unused *adapters.RequestData, httpRes *adapters.ResponseData) ([]*adapters.TypedBid, []error) {
func (a *AdtelligentAdapter) MakeBids(bidReq *openrtb.BidRequest, unused *adapters.RequestData, httpRes *adapters.ResponseData) (*adapters.BidderResponse, []error) {

if httpRes.StatusCode == http.StatusNoContent {
return nil, nil
Expand All @@ -98,7 +98,7 @@ func (a *AdtelligentAdapter) MakeBids(bidReq *openrtb.BidRequest, unused *adapte
}}
}

var bids []*adapters.TypedBid
bidResponse := adapters.NewBidderResponse()
var errors []error

var impOK bool
Expand All @@ -117,7 +117,6 @@ func (a *AdtelligentAdapter) MakeBids(bidReq *openrtb.BidRequest, unused *adapte
if imp.Video != nil {
mediaType = openrtb_ext.BidTypeVideo
break

}
}
}
Expand All @@ -129,14 +128,14 @@ func (a *AdtelligentAdapter) MakeBids(bidReq *openrtb.BidRequest, unused *adapte
continue
}

bids = append(bids, &adapters.TypedBid{
bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
Bid: &bid,
BidType: mediaType,
})
}
}

return bids, errors
return bidResponse, errors
}

func validateImpression(imp *openrtb.Imp) (int, error) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,21 @@
}
}
],
"expectedBids": [
"expectedBidResponses": [
{
"bid": {
"id": "test-bid-id",
"impid": "test-imp-id",
"price": 3.5,
"w": 900,
"h": 250
},
"type": "video"
"currency": "USD",
"bids": [
{
"bid": {
"id": "test-bid-id",
"impid": "test-imp-id",
"price": 3.5,
"w": 900,
"h": 250
},
"type": "video"
}
]
}
]
}
8 changes: 4 additions & 4 deletions adapters/appnexus/appnexus.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ func makeKeywordStr(keywords []*openrtb_ext.ExtImpAppnexusKeyVal) string {
return strings.Join(kvs, ",")
}

func (a *AppNexusAdapter) MakeBids(internalRequest *openrtb.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) ([]*adapters.TypedBid, []error) {
func (a *AppNexusAdapter) MakeBids(internalRequest *openrtb.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
if response.StatusCode == http.StatusNoContent {
return nil, nil
}
Expand All @@ -417,14 +417,14 @@ func (a *AppNexusAdapter) MakeBids(internalRequest *openrtb.BidRequest, external
return nil, []error{err}
}

bids := make([]*adapters.TypedBid, 0, 5)
bidResponse := adapters.NewBidderResponseWithBidsCapacity(5)

var errs []error
for _, sb := range bidResp.SeatBid {
for i := 0; i < len(sb.Bid); i++ {
bid := sb.Bid[i]
if bidType, err := getMediaTypeForBid(&bid); err == nil {
bids = append(bids, &adapters.TypedBid{
bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
Bid: &bid,
BidType: bidType,
})
Expand All @@ -433,7 +433,7 @@ func (a *AppNexusAdapter) MakeBids(internalRequest *openrtb.BidRequest, external
}
}
}
return bids, errs
return bidResponse, errs
}

// getMediaTypeForBid determines which type of bid.
Expand Down
55 changes: 30 additions & 25 deletions adapters/appnexus/appnexustest/exemplary/native-1.1.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,33 +103,38 @@
}
}
],
"expectedBids": [
"expectedBidResponses": [
{
"bid": {
"id": "928185755156387460",
"impid": "some-imp-id",
"price": 1,
"adm": "{\"assets\":[{\"id\": 2,\"img\":{\"url\":\"http://vcdn.adnxs.com/p/creative-image/5e/b6/de/c3/5eb6dec3-4854-4dcd-980a-347f36ab502e.jpg\",\"w\": 3000,\"h\": 2250,\"ext\":{\"appnexus\":{\"prevent_crop\":0}}}},{\"id\": 1,\"title\":{\"text\":\"This is an example Prebid Native creative\"}},{\"id\": 3,\"data\":{\"value\":\"Prebid.org\"}},{\"id\": 4,\"data\":{\"value\":\"This is a Prebid Native Creative. There are many like it, but this one is mine.\"}}],\"link\":{\"url\":\"http://nym1-ib.adnxs.com/click?AAAAAAAA8D8AAAAAAADwPwAAAAAAAAAAAAAAAAAA8D8AAAAAAADwPwhdYz3ZyNFNG3fXpZUyLXNZ0o5aAAAAACrElgC-AwAAvgMAAAIAAAC98iUEeP4QAAAAAABVU0QAVVNEAAEAAQARIAAAAAABAgQCAAAAAAEAhBaSXgAAAAA./pp=${AUCTION_PRICE}/cnd=%21OwwGAQiGmooHEL3llyEY-PxDIAQoADoRZGVmYXVsdCNOWU0yOjQwMjM./bn=75922/test=1/referrer=prebid.org/clickenc=http%3A%2F%2Fprebid.org%2Fdev-docs%2Fshow-native-ads.html\"},\"imptrackers\":[\"http://nym1-ib.adnxs.com/openrtb_win?e=wqT_3QLFBqBFAwAAAwDWAAUBCNmku9QFEIi6jeuTm_LoTRib7t2u2tLMlnMqNgkAAAECCPA_EQEHEAAA8D8ZCQkIAAAhCQkI8D8pEQkAMQkJqAAAMKqI2wQ4vgdAvgdIAlC95ZchWPj8Q2AAaJFAeJLRBIABAYoBA1VTRJIFBvBQmAEBoAEBqAEBsAEAuAECwAEEyAEC0AEJ2AEA4AEB8AEAigI7dWYoJ2EnLCAxMzc2ODYwLCAxNTE5MzA5NDAxKTt1ZigncicsIDY5NTk1ODM3Nh4A8IqSAvUBIXRETkdfUWlHbW9vSEVMM2xseUVZQUNENF9FTXdBRGdBUUFSSXZnZFFxb2piQkZnQVlMTURhQUJ3QUhnQWdBRUFpQUVBa0FFQm1BRUJvQUVCcUFFRHNBRUF1UUVwaTRpREFBRHdQOEVCS1l1SWd3QUE4RF9KQVhfelYzek1zXzBfMlFFQUFBAQMkRHdQLUFCQVBVQgEOLEFKZ0NBS0FDQUxVQwUQBEwwCQjwTE1BQ0FNZ0NBT0FDQU9nQ0FQZ0NBSUFEQVpBREFKZ0RBYWdEaHBxS0I3b0RFV1JsWm1GMWJIUWpUbGxOTWpvME1ESXqaAjkhT3d3R0FRNvgA8E4tUHhESUFRb0FEb1JaR1ZtWVhWc2RDTk9XVTB5T2pRd01qTS7YAugH4ALH0wHqAgpwcmViaWQub3Jn8gIRCgZBRFZfSUQSBzEzNzY4NjDyARQMQ1BHXwEUNDM1MDMwOTjyAhEKBUNQARPwmQgxNDg0NzIzOIADAYgDAZADAJgDFKADAaoDAMADkBzIAwDYAwDgAwDoAwD4AwOABACSBAkvb3BlbnJ0YjKYBACiBAwxNTIuMTkzLjYuNzSoBJrMI7IEDAgAEAAYACAAMAA4ALgEAMAEAMgEANIEEWRlZmF1bHQjTllNMjo0MDIz2gQCCADgBADwBL3llyGIBQGYBQCgBf____8FA1ABqgULc29tZS1yZXEtaWTABQDJBQAFARTwP9IFCQkFC2QAAADYBQHgBQHwBd4C-gUECAAQAJAGAZgGAA..&s=08b1535744639c904684afe46e3c6c0e4786089f&test=1&referrer=prebid.org&pp=${AUCTION_PRICE}\"],\"jstracker\":\"<script src=\\\"http://www.dummyurl.js\\\"></script>\"}",
"adid": "69595837",
"adomain": [
"appnexus.com"
],
"iurl": "http://nym1-ib.adnxs.com/cr?id=69595837",
"cid": "958",
"crid": "69595837",
"cat": [
"IAB3-1"
],
"ext": {
"appnexus": {
"brand_id": 350,
"auction_id": 5607483846416358664,
"bidder_id": 2,
"bid_ad_type": 3
}
"currency": "USD",
"bids": [
{
"bid": {
"id": "928185755156387460",
"impid": "some-imp-id",
"price": 1,
"adm": "{\"assets\":[{\"id\": 2,\"img\":{\"url\":\"http://vcdn.adnxs.com/p/creative-image/5e/b6/de/c3/5eb6dec3-4854-4dcd-980a-347f36ab502e.jpg\",\"w\": 3000,\"h\": 2250,\"ext\":{\"appnexus\":{\"prevent_crop\":0}}}},{\"id\": 1,\"title\":{\"text\":\"This is an example Prebid Native creative\"}},{\"id\": 3,\"data\":{\"value\":\"Prebid.org\"}},{\"id\": 4,\"data\":{\"value\":\"This is a Prebid Native Creative. There are many like it, but this one is mine.\"}}],\"link\":{\"url\":\"http://nym1-ib.adnxs.com/click?AAAAAAAA8D8AAAAAAADwPwAAAAAAAAAAAAAAAAAA8D8AAAAAAADwPwhdYz3ZyNFNG3fXpZUyLXNZ0o5aAAAAACrElgC-AwAAvgMAAAIAAAC98iUEeP4QAAAAAABVU0QAVVNEAAEAAQARIAAAAAABAgQCAAAAAAEAhBaSXgAAAAA./pp=${AUCTION_PRICE}/cnd=%21OwwGAQiGmooHEL3llyEY-PxDIAQoADoRZGVmYXVsdCNOWU0yOjQwMjM./bn=75922/test=1/referrer=prebid.org/clickenc=http%3A%2F%2Fprebid.org%2Fdev-docs%2Fshow-native-ads.html\"},\"imptrackers\":[\"http://nym1-ib.adnxs.com/openrtb_win?e=wqT_3QLFBqBFAwAAAwDWAAUBCNmku9QFEIi6jeuTm_LoTRib7t2u2tLMlnMqNgkAAAECCPA_EQEHEAAA8D8ZCQkIAAAhCQkI8D8pEQkAMQkJqAAAMKqI2wQ4vgdAvgdIAlC95ZchWPj8Q2AAaJFAeJLRBIABAYoBA1VTRJIFBvBQmAEBoAEBqAEBsAEAuAECwAEEyAEC0AEJ2AEA4AEB8AEAigI7dWYoJ2EnLCAxMzc2ODYwLCAxNTE5MzA5NDAxKTt1ZigncicsIDY5NTk1ODM3Nh4A8IqSAvUBIXRETkdfUWlHbW9vSEVMM2xseUVZQUNENF9FTXdBRGdBUUFSSXZnZFFxb2piQkZnQVlMTURhQUJ3QUhnQWdBRUFpQUVBa0FFQm1BRUJvQUVCcUFFRHNBRUF1UUVwaTRpREFBRHdQOEVCS1l1SWd3QUE4RF9KQVhfelYzek1zXzBfMlFFQUFBAQMkRHdQLUFCQVBVQgEOLEFKZ0NBS0FDQUxVQwUQBEwwCQjwTE1BQ0FNZ0NBT0FDQU9nQ0FQZ0NBSUFEQVpBREFKZ0RBYWdEaHBxS0I3b0RFV1JsWm1GMWJIUWpUbGxOTWpvME1ESXqaAjkhT3d3R0FRNvgA8E4tUHhESUFRb0FEb1JaR1ZtWVhWc2RDTk9XVTB5T2pRd01qTS7YAugH4ALH0wHqAgpwcmViaWQub3Jn8gIRCgZBRFZfSUQSBzEzNzY4NjDyARQMQ1BHXwEUNDM1MDMwOTjyAhEKBUNQARPwmQgxNDg0NzIzOIADAYgDAZADAJgDFKADAaoDAMADkBzIAwDYAwDgAwDoAwD4AwOABACSBAkvb3BlbnJ0YjKYBACiBAwxNTIuMTkzLjYuNzSoBJrMI7IEDAgAEAAYACAAMAA4ALgEAMAEAMgEANIEEWRlZmF1bHQjTllNMjo0MDIz2gQCCADgBADwBL3llyGIBQGYBQCgBf____8FA1ABqgULc29tZS1yZXEtaWTABQDJBQAFARTwP9IFCQkFC2QAAADYBQHgBQHwBd4C-gUECAAQAJAGAZgGAA..&s=08b1535744639c904684afe46e3c6c0e4786089f&test=1&referrer=prebid.org&pp=${AUCTION_PRICE}\"],\"jstracker\":\"<script src=\\\"http://www.dummyurl.js\\\"></script>\"}",
"adid": "69595837",
"adomain": [
"appnexus.com"
],
"iurl": "http://nym1-ib.adnxs.com/cr?id=69595837",
"cid": "958",
"crid": "69595837",
"cat": [
"IAB3-1"
],
"ext": {
"appnexus": {
"brand_id": 350,
"auction_id": 5607483846416358664,
"bidder_id": 2,
"bid_ad_type": 3
}
}
},
"type": "native"
}
},
"type": "native"
]
}
]
}
51 changes: 28 additions & 23 deletions adapters/appnexus/appnexustest/exemplary/simple-banner.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,31 +95,36 @@
}
],

"expectedBids": [
"expectedBidResponses": [
{
"bid": {
"id": "7706636740145184841",
"impid": "test-imp-id",
"price": 0.5,
"adm": "some-test-ad",
"adid": "29681110",
"adomain": ["appnexus.com"],
"iurl": "http://nym1-ib.adnxs.com/cr?id=29681110",
"cid": "958",
"crid": "29681110",
"w": 300,
"h": 250,
"ext": {
"appnexus": {
"brand_id": 1,
"auction_id": 8189378542222915032,
"bid_ad_type": 0,
"bidder_id": 2,
"ranking_price": 0.000000
}
"currency": "USD",
"bids": [
{
"bid": {
"id": "7706636740145184841",
"impid": "test-imp-id",
"price": 0.5,
"adm": "some-test-ad",
"adid": "29681110",
"adomain": ["appnexus.com"],
"iurl": "http://nym1-ib.adnxs.com/cr?id=29681110",
"cid": "958",
"crid": "29681110",
"w": 300,
"h": 250,
"ext": {
"appnexus": {
"brand_id": 1,
"auction_id": 8189378542222915032,
"bid_ad_type": 0,
"bidder_id": 2,
"ranking_price": 0.000000
}
}
},
"type": "banner"
}
},
"type": "banner"
]
}
]
}
Loading

0 comments on commit 0ad0d1b

Please sign in to comment.