From 5cf94e3df7a0a7901d5390491027086b4e902f03 Mon Sep 17 00:00:00 2001 From: sambaiz Date: Mon, 30 Mar 2020 14:24:44 +0900 Subject: [PATCH 1/9] Add AJA adapter --- adapters/aja/aja.go | 128 ++++++++++++++ adapters/aja/aja_test.go | 13 ++ .../exemplary/banner-multiple-imps.json | 159 ++++++++++++++++++ adapters/aja/ajatest/exemplary/video.json | 90 ++++++++++ adapters/aja/ajatest/params/race/banner.json | 3 + adapters/aja/ajatest/params/race/video.json | 3 + adapters/aja/usersync.go | 12 ++ adapters/aja/usersync_test.go | 31 ++++ analytics/config/testFiles/test-20200303 | 0 config/config.go | 2 + exchange/adapter_map.go | 2 + openrtb_ext/bidders.go | 2 + openrtb_ext/imp_aja.go | 5 + static/bidder-info/aja.yaml | 13 ++ static/bidder-params/aja.json | 13 ++ usersync/usersyncers/syncer.go | 2 + usersync/usersyncers/syncer_test.go | 1 + 17 files changed, 479 insertions(+) create mode 100644 adapters/aja/aja.go create mode 100644 adapters/aja/aja_test.go create mode 100644 adapters/aja/ajatest/exemplary/banner-multiple-imps.json create mode 100644 adapters/aja/ajatest/exemplary/video.json create mode 100644 adapters/aja/ajatest/params/race/banner.json create mode 100644 adapters/aja/ajatest/params/race/video.json create mode 100644 adapters/aja/usersync.go create mode 100644 adapters/aja/usersync_test.go delete mode 100644 analytics/config/testFiles/test-20200303 create mode 100644 openrtb_ext/imp_aja.go create mode 100644 static/bidder-info/aja.yaml create mode 100644 static/bidder-params/aja.json diff --git a/adapters/aja/aja.go b/adapters/aja/aja.go new file mode 100644 index 00000000000..504a07687b2 --- /dev/null +++ b/adapters/aja/aja.go @@ -0,0 +1,128 @@ +package aja + +import ( + "encoding/json" + "fmt" + "github.com/mxmCherry/openrtb" + "github.com/prebid/prebid-server/adapters" + "github.com/prebid/prebid-server/errortypes" + "github.com/prebid/prebid-server/openrtb_ext" + "net/http" +) + +type AJAAdapter struct { + endpoint string +} + +func (a *AJAAdapter) MakeRequests(bidReq *openrtb.BidRequest, extraInfo *adapters.ExtraRequestInfo) (adapterReqs []*adapters.RequestData, errs []error) { + // split imps by tagid + impsByTagID := map[string][]openrtb.Imp{} + for _, imp := range bidReq.Imp { + extAJA, err := parseExtAJA(imp) + if err != nil { + errs = append(errs, err) + continue + } + imp.TagID = extAJA.AdSpotID + imp.Ext = nil + impsByTagID[imp.TagID] = append(impsByTagID[imp.TagID], imp) + } + + originalImps := bidReq.Imp + for _, imps := range impsByTagID { + bidReq.Imp = imps + body, err := json.Marshal(bidReq) + if err != nil { + errs = append(errs, err) + continue + } + adapterReqs = append(adapterReqs, &adapters.RequestData{ + Method: "POST", + Uri: a.endpoint, + Body: body, + }) + } + bidReq.Imp = originalImps + + return +} + +func parseExtAJA(imp openrtb.Imp) (openrtb_ext.ExtImpAJA, error) { + var ( + extImp adapters.ExtImpBidder + extAJA openrtb_ext.ExtImpAJA + ) + + if err := json.Unmarshal(imp.Ext, &extImp); err != nil { + return extAJA, &errortypes.BadInput{ + Message: fmt.Sprintf("Failed to unmarshal ext impID: %s err: %s", imp.ID, err), + } + } + + if err := json.Unmarshal(extImp.Bidder, &extAJA); err != nil { + return extAJA, &errortypes.BadInput{ + Message: fmt.Sprintf("Failed to unmarshal ext.bidder impID: %s err: %s", imp.ID, err), + } + } + + return extAJA, nil +} + +func (a *AJAAdapter) MakeBids(bidReq *openrtb.BidRequest, adapterReq *adapters.RequestData, adapterResp *adapters.ResponseData) (*adapters.BidderResponse, []error) { + if adapterResp.StatusCode != http.StatusOK { + if adapterResp.StatusCode == http.StatusNoContent { + return nil, nil + } + if adapterResp.StatusCode == http.StatusBadRequest { + return nil, []error{&errortypes.BadInput{ + Message: fmt.Sprintf("Unexpected status code: %d", adapterResp.StatusCode), + }} + } + return nil, []error{&errortypes.BadServerResponse{ + Message: fmt.Sprintf("Unexpected status code: %d", adapterResp.StatusCode), + }} + } + + var bidResp openrtb.BidResponse + if err := json.Unmarshal(adapterResp.Body, &bidResp); err != nil { + return nil, []error{&errortypes.BadServerResponse{ + Message: fmt.Sprintf("Failed to unmarshal bid response: %s", err.Error()), + }} + } + + bidderResp := adapters.NewBidderResponseWithBidsCapacity(len(bidReq.Imp)) + var errors []error + + for _, seatbid := range bidResp.SeatBid { + for _, bid := range seatbid.Bid { + impID: + for _, imp := range bidReq.Imp { + if imp.ID == bid.ImpID { + var bidType openrtb_ext.BidType + if imp.Banner != nil { + bidType = openrtb_ext.BidTypeBanner + } else if imp.Video != nil { + bidType = openrtb_ext.BidTypeVideo + } else { + errors = append(errors, &errortypes.BadServerResponse{ + Message: fmt.Sprintf("Response received for unexpected type of bid bidID: %s", bid.ID), + }) + continue + } + bidderResp.Bids = append(bidderResp.Bids, &adapters.TypedBid{ + Bid: &bid, + BidType: bidType, + }) + break impID + } + } + } + } + return bidderResp, errors +} + +func NewAJABidder(endpoint string) adapters.Bidder { + return &AJAAdapter{ + endpoint: endpoint, + } +} diff --git a/adapters/aja/aja_test.go b/adapters/aja/aja_test.go new file mode 100644 index 00000000000..1cc8200d60b --- /dev/null +++ b/adapters/aja/aja_test.go @@ -0,0 +1,13 @@ +package aja + +import ( + "testing" + + "github.com/prebid/prebid-server/adapters/adapterstest" +) + +const testsBidderEndpoint = "https://localhost/bid/4" + +func TestJsonSamples(t *testing.T) { + adapterstest.RunJSONBidderTest(t, "ajatest", NewAJABidder(testsBidderEndpoint)) +} diff --git a/adapters/aja/ajatest/exemplary/banner-multiple-imps.json b/adapters/aja/ajatest/exemplary/banner-multiple-imps.json new file mode 100644 index 00000000000..8de9a31eadb --- /dev/null +++ b/adapters/aja/ajatest/exemplary/banner-multiple-imps.json @@ -0,0 +1,159 @@ +{ + "mockBidRequest": { + "id": "test-req-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "asi": "test-asi" + } + } + }, + { + "id": "test-imp-id2", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "asi": "test-asi2" + } + } + } + ], + "user": { + "buyeruid": "test-uid" + }, + "tmax": 500 + }, + + "httpcalls": [ + { + "expectedRequest": { + "uri": "https://localhost/bid/4", + "headers": {}, + "body": { + "id": "test-req-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "w": 300, + "h": 250 + }, + "tagid": "test-asi" + } + ], + "user": { + "buyeruid": "test-uid" + }, + "tmax": 500 + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-req-id", + "seatbid": [ + { + "bid": [ + { + "id": "test-bid-id", + "impid": "test-imp-id", + "price": 1, + "adm": "
test
", + "crid": "test-creative-id" + } + ] + } + ], + "bidid": "test-seatbid-id", + "cur": "USD" + } + } + }, + { + "expectedRequest": { + "uri": "https://localhost/bid/4", + "headers": {}, + "body": { + "id": "test-req-id", + "imp": [ + { + "id": "test-imp-id2", + "banner": { + "w": 300, + "h": 250 + }, + "tagid": "test-asi2" + } + ], + "user": { + "buyeruid": "test-uid" + }, + "tmax": 500 + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-req-id", + "seatbid": [ + { + "bid": [ + { + "id": "test-bid-id2", + "impid": "test-imp-id2", + "price": 1, + "adm": "
test2
", + "crid": "test-creative-id2" + } + ] + } + ], + "bidid": "test-seatbid-id", + "cur": "USD" + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "test-bid-id", + "impid": "test-imp-id", + "price": 1, + "adm": "
test
", + "crid": "test-creative-id" + }, + "type": "banner" + } + ] + }, + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "test-bid-id2", + "impid": "test-imp-id2", + "price": 1, + "adm": "
test2
", + "crid": "test-creative-id2" + }, + "type": "banner" + } + ] + } + ] +} diff --git a/adapters/aja/ajatest/exemplary/video.json b/adapters/aja/ajatest/exemplary/video.json new file mode 100644 index 00000000000..a7991570bba --- /dev/null +++ b/adapters/aja/ajatest/exemplary/video.json @@ -0,0 +1,90 @@ +{ + "mockBidRequest": { + "id": "test-req-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": ["video/mp4"], + "w": 640, + "h": 480 + }, + "ext": { + "bidder": { + "asi": "test-asi" + } + } + } + ], + "user": { + "buyeruid": "test-uid" + }, + "tmax": 500 + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://localhost/bid/4", + "headers": {}, + "body": { + "id": "test-req-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": ["video/mp4"], + "w": 640, + "h": 480 + }, + "tagid": "test-asi" + } + ], + "user": { + "buyeruid": "test-uid" + }, + "tmax": 500 + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-req-id", + "seatbid": [ + { + "bid": [ + { + "id": "test-bid-id", + "impid": "test-imp-id", + "price": 1, + "adm": "", + "crid": "test-creative-id" + } + ] + } + ], + "bidid": "test-seatbid-id", + "cur": "USD" + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "test-bid-id", + "impid": "test-imp-id", + "price": 1, + "adm": "", + "crid": "test-creative-id" + }, + "type": "video" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/aja/ajatest/params/race/banner.json b/adapters/aja/ajatest/params/race/banner.json new file mode 100644 index 00000000000..6d50c2d1880 --- /dev/null +++ b/adapters/aja/ajatest/params/race/banner.json @@ -0,0 +1,3 @@ +{ + "asi": "abc123" +} \ No newline at end of file diff --git a/adapters/aja/ajatest/params/race/video.json b/adapters/aja/ajatest/params/race/video.json new file mode 100644 index 00000000000..6d50c2d1880 --- /dev/null +++ b/adapters/aja/ajatest/params/race/video.json @@ -0,0 +1,3 @@ +{ + "asi": "abc123" +} \ No newline at end of file diff --git a/adapters/aja/usersync.go b/adapters/aja/usersync.go new file mode 100644 index 00000000000..c54405dbbd1 --- /dev/null +++ b/adapters/aja/usersync.go @@ -0,0 +1,12 @@ +package aja + +import ( + "text/template" + + "github.com/prebid/prebid-server/adapters" + "github.com/prebid/prebid-server/usersync" +) + +func NewAJASyncer(temp *template.Template) usersync.Usersyncer { + return adapters.NewSyncer("aja", 0, temp, adapters.SyncTypeRedirect) +} diff --git a/adapters/aja/usersync_test.go b/adapters/aja/usersync_test.go new file mode 100644 index 00000000000..5b2e6df7e1e --- /dev/null +++ b/adapters/aja/usersync_test.go @@ -0,0 +1,31 @@ +package aja + +import ( + "testing" + "text/template" + + "github.com/prebid/prebid-server/privacy" + "github.com/prebid/prebid-server/privacy/gdpr" + "github.com/stretchr/testify/assert" +) + +func TestAJASyncer(t *testing.T) { + syncURL := "https://ad.as.amanad.adtdp.com/v1/sync/ssp?ssp=4&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&redir=localhost/setuid?bidder=aja&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&uid=%s" + syncURLTemplate := template.Must( + template.New("sync-template").Parse(syncURL), + ) + + syncer := NewAJASyncer(syncURLTemplate) + syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{ + GDPR: gdpr.Policy{ + Signal: "1", + Consent: "BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA", + }, + }) + + assert.NoError(t, err) + assert.Equal(t, "https://ad.as.amanad.adtdp.com/v1/sync/ssp?ssp=4&gdpr=1&gdpr_consent=BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA&redir=localhost/setuid?bidder=aja&gdpr=1&gdpr_consent=BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA&uid=%s", syncInfo.URL) + assert.Equal(t, "redirect", syncInfo.Type) + assert.EqualValues(t, 0, syncer.GDPRVendorID()) + assert.Equal(t, false, syncInfo.SupportCORS) +} diff --git a/analytics/config/testFiles/test-20200303 b/analytics/config/testFiles/test-20200303 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/config/config.go b/config/config.go index d4edab2b53f..409052ff0af 100644 --- a/config/config.go +++ b/config/config.go @@ -500,6 +500,7 @@ func (cfg *Configuration) setDerivedDefaults() { setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAdtelligent, "https://sync.adtelligent.com/csync?t=p&ep=0&redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dadtelligent%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7Buid%7D") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAdmixer, "https://inv-nets.admixer.net/adxcm.aspx?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir=1&rurl="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dadmixer%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%24visitor_cookie%24%24") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAdvangelists, "https://nep.advangelists.com/xp/user-sync?acctid={aid}&&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dadvangelists%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID") + setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAJA, "https://ad.as.amanad.adtdp.com/v1/sync/ssp?ssp=4&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Daja%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%25s") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAppnexus, "https://ib.adnxs.com/getuid?"+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dadnxs%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderBeachfront, "https://sync.bfmio.com/sync_s2s?gdpr={{.GDPR}}&us_privacy={{.USPrivacy}}&url="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dbeachfront%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%5Bio_cid%5D") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderBrightroll, "https://pr-bh.ybp.yahoo.com/sync/appnexusprebidserver/?gdpr={{.GDPR}}&euconsent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&url="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dbrightroll%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID") @@ -689,6 +690,7 @@ func SetupViper(v *viper.Viper, filename string) { v.SetDefault("adapters.adpone.endpoint", "http://rtb.adpone.com/bid-request?src=prebid_server") v.SetDefault("adapters.adtelligent.endpoint", "http://hb.adtelligent.com/auction") v.SetDefault("adapters.advangelists.endpoint", "http://nep.advangelists.com/xp/get?pubid={{.PublisherID}}") + v.SetDefault("adapters.aja.endpoint", "https://ad.as.amanad.adtdp.com/v1/bid/4") v.SetDefault("adapters.applogy.endpoint", "http://rtb.applogy.com/v1/prebid") v.SetDefault("adapters.appnexus.endpoint", "http://ib.adnxs.com/openrtb2") // Docs: https://wiki.appnexus.com/display/supply/Incoming+Bid+Request+from+SSPs v.SetDefault("adapters.appnexus.platform_id", "5") diff --git a/exchange/adapter_map.go b/exchange/adapter_map.go index 05f44e24b66..74f7294b803 100644 --- a/exchange/adapter_map.go +++ b/exchange/adapter_map.go @@ -2,6 +2,7 @@ package exchange import ( "fmt" + "github.com/prebid/prebid-server/adapters/aja" "net/http" "strings" @@ -81,6 +82,7 @@ func newAdapterMap(client *http.Client, cfg *config.Configuration, infos adapter openrtb_ext.BidderAdpone: adpone.NewAdponeBidder(cfg.Adapters[string(openrtb_ext.BidderAdpone)].Endpoint), openrtb_ext.BidderAdtelligent: adtelligent.NewAdtelligentBidder(cfg.Adapters[string(openrtb_ext.BidderAdtelligent)].Endpoint), openrtb_ext.BidderAdvangelists: advangelists.NewAdvangelistsBidder(cfg.Adapters[string(openrtb_ext.BidderAdvangelists)].Endpoint), + openrtb_ext.BidderAJA: aja.NewAJABidder(cfg.Adapters[string(openrtb_ext.BidderAJA)].Endpoint), openrtb_ext.BidderApplogy: applogy.NewApplogyBidder(cfg.Adapters[string(openrtb_ext.BidderApplogy)].Endpoint), openrtb_ext.BidderAppnexus: appnexus.NewAppNexusBidder(client, cfg.Adapters[string(openrtb_ext.BidderAppnexus)].Endpoint, cfg.Adapters[string(openrtb_ext.BidderAppnexus)].PlatformID), // TODO #615: Update the config setup so that the Beachfront URLs can be configured, and use those in TestRaceIntegration in exchange_test.go diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go index 00c25f8a3f0..a7e934b88d2 100644 --- a/openrtb_ext/bidders.go +++ b/openrtb_ext/bidders.go @@ -28,6 +28,7 @@ const ( BidderAdmixer BidderName = "admixer" BidderAdtelligent BidderName = "adtelligent" BidderAdvangelists BidderName = "advangelists" + BidderAJA BidderName = "aja" BidderApplogy BidderName = "applogy" BidderAppnexus BidderName = "appnexus" BidderAdoppler BidderName = "adoppler" @@ -89,6 +90,7 @@ var BidderMap = map[string]BidderName{ "adpone": BidderAdpone, "adtelligent": BidderAdtelligent, "advangelists": BidderAdvangelists, + "aja": BidderAJA, "applogy": BidderApplogy, "appnexus": BidderAppnexus, "adoppler": BidderAdoppler, diff --git a/openrtb_ext/imp_aja.go b/openrtb_ext/imp_aja.go new file mode 100644 index 00000000000..db04fa3f3ac --- /dev/null +++ b/openrtb_ext/imp_aja.go @@ -0,0 +1,5 @@ +package openrtb_ext + +type ExtImpAJA struct { + AdSpotID string `json:"asi"` +} diff --git a/static/bidder-info/aja.yaml b/static/bidder-info/aja.yaml new file mode 100644 index 00000000000..53f43689172 --- /dev/null +++ b/static/bidder-info/aja.yaml @@ -0,0 +1,13 @@ +maintainer: + email: "dev@aja-kk.co.jp" +capabilities: + site: + mediaTypes: + - banner + - video + + app: + mediaTypes: + - banner + - video + diff --git a/static/bidder-params/aja.json b/static/bidder-params/aja.json new file mode 100644 index 00000000000..c15a4e04d12 --- /dev/null +++ b/static/bidder-params/aja.json @@ -0,0 +1,13 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "AJA Adapter Params", + "description": "A schema which validates params accepted by the AJA adapter", + "type": "object", + "properties": { + "asi": { + "type": "string", + "description": "Ad spot ID" + } + }, + "required": ["asi"] +} diff --git a/usersync/usersyncers/syncer.go b/usersync/usersyncers/syncer.go index c7ad70b7eff..fabc94192e2 100644 --- a/usersync/usersyncers/syncer.go +++ b/usersync/usersyncers/syncer.go @@ -1,6 +1,7 @@ package usersyncers import ( + "github.com/prebid/prebid-server/adapters/aja" "strings" "text/template" @@ -75,6 +76,7 @@ func NewSyncerMap(cfg *config.Configuration) map[openrtb_ext.BidderName]usersync insertIntoMap(cfg, syncers, openrtb_ext.BidderAdpone, adpone.NewadponeSyncer) insertIntoMap(cfg, syncers, openrtb_ext.BidderAdtelligent, adtelligent.NewAdtelligentSyncer) insertIntoMap(cfg, syncers, openrtb_ext.BidderAdvangelists, advangelists.NewAdvangelistsSyncer) + insertIntoMap(cfg, syncers, openrtb_ext.BidderAJA, aja.NewAJASyncer) insertIntoMap(cfg, syncers, openrtb_ext.BidderAppnexus, appnexus.NewAppnexusSyncer) insertIntoMap(cfg, syncers, openrtb_ext.BidderBeachfront, beachfront.NewBeachfrontSyncer) insertIntoMap(cfg, syncers, openrtb_ext.BidderBrightroll, brightroll.NewBrightrollSyncer) diff --git a/usersync/usersyncers/syncer_test.go b/usersync/usersyncers/syncer_test.go index 3de64ec1eb0..7bb2b9fe306 100644 --- a/usersync/usersyncers/syncer_test.go +++ b/usersync/usersyncers/syncer_test.go @@ -22,6 +22,7 @@ func TestNewSyncerMap(t *testing.T) { string(openrtb_ext.BidderAdpone): syncConfig, string(openrtb_ext.BidderAdtelligent): syncConfig, string(openrtb_ext.BidderAdvangelists): syncConfig, + string(openrtb_ext.BidderAJA): syncConfig, string(openrtb_ext.BidderAppnexus): syncConfig, string(openrtb_ext.BidderBeachfront): syncConfig, string(openrtb_ext.BidderBrightroll): syncConfig, From 5b064eb1e257920d8fcff6aafbf29b03fad2b95e Mon Sep 17 00:00:00 2001 From: sambaiz Date: Wed, 22 Apr 2020 18:00:29 +0900 Subject: [PATCH 2/9] ccpa support --- adapters/aja/usersync_test.go | 8 ++++++-- config/config.go | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/adapters/aja/usersync_test.go b/adapters/aja/usersync_test.go index 5b2e6df7e1e..dbb66cc9ae2 100644 --- a/adapters/aja/usersync_test.go +++ b/adapters/aja/usersync_test.go @@ -1,6 +1,7 @@ package aja import ( + "github.com/prebid/prebid-server/privacy/ccpa" "testing" "text/template" @@ -10,7 +11,7 @@ import ( ) func TestAJASyncer(t *testing.T) { - syncURL := "https://ad.as.amanad.adtdp.com/v1/sync/ssp?ssp=4&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&redir=localhost/setuid?bidder=aja&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&uid=%s" + syncURL := "https://ad.as.amanad.adtdp.com/v1/sync/ssp?ssp=4&gdpr={{.GDPR}}&us_privacy={{.USPrivacy}}&redir=localhost/setuid?bidder=aja&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&uid=%s" syncURLTemplate := template.Must( template.New("sync-template").Parse(syncURL), ) @@ -21,10 +22,13 @@ func TestAJASyncer(t *testing.T) { Signal: "1", Consent: "BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA", }, + CCPA: ccpa.Policy{ + Value: "C", + }, }) assert.NoError(t, err) - assert.Equal(t, "https://ad.as.amanad.adtdp.com/v1/sync/ssp?ssp=4&gdpr=1&gdpr_consent=BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA&redir=localhost/setuid?bidder=aja&gdpr=1&gdpr_consent=BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA&uid=%s", syncInfo.URL) + assert.Equal(t, "https://ad.as.amanad.adtdp.com/v1/sync/ssp?ssp=4&gdpr=1&us_privacy=C&redir=localhost/setuid?bidder=aja&gdpr=1&gdpr_consent=BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA&uid=%s", syncInfo.URL) assert.Equal(t, "redirect", syncInfo.Type) assert.EqualValues(t, 0, syncer.GDPRVendorID()) assert.Equal(t, false, syncInfo.SupportCORS) diff --git a/config/config.go b/config/config.go index 409052ff0af..ea1ca39d1d2 100644 --- a/config/config.go +++ b/config/config.go @@ -500,7 +500,7 @@ func (cfg *Configuration) setDerivedDefaults() { setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAdtelligent, "https://sync.adtelligent.com/csync?t=p&ep=0&redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dadtelligent%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7Buid%7D") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAdmixer, "https://inv-nets.admixer.net/adxcm.aspx?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir=1&rurl="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dadmixer%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%24visitor_cookie%24%24") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAdvangelists, "https://nep.advangelists.com/xp/user-sync?acctid={aid}&&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dadvangelists%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID") - setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAJA, "https://ad.as.amanad.adtdp.com/v1/sync/ssp?ssp=4&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Daja%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%25s") + setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAJA, "https://ad.as.amanad.adtdp.com/v1/sync/ssp?ssp=4&gdpr={{.GDPR}}&us_privacy={{.USPrivacy}}&redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Daja%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%25s") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAppnexus, "https://ib.adnxs.com/getuid?"+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dadnxs%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderBeachfront, "https://sync.bfmio.com/sync_s2s?gdpr={{.GDPR}}&us_privacy={{.USPrivacy}}&url="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dbeachfront%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%5Bio_cid%5D") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderBrightroll, "https://pr-bh.ybp.yahoo.com/sync/appnexusprebidserver/?gdpr={{.GDPR}}&euconsent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&url="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dbrightroll%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID") From 62bbdc6602573a0c69f0eaef99346e252a58fe29 Mon Sep 17 00:00:00 2001 From: sambaiz Date: Fri, 24 Apr 2020 12:48:56 +0900 Subject: [PATCH 3/9] make import alphabetical sorted --- exchange/adapter_map.go | 2 +- usersync/usersyncers/syncer.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/exchange/adapter_map.go b/exchange/adapter_map.go index 74f7294b803..650255a3417 100644 --- a/exchange/adapter_map.go +++ b/exchange/adapter_map.go @@ -2,7 +2,6 @@ package exchange import ( "fmt" - "github.com/prebid/prebid-server/adapters/aja" "net/http" "strings" @@ -16,6 +15,7 @@ import ( "github.com/prebid/prebid-server/adapters/adpone" "github.com/prebid/prebid-server/adapters/adtelligent" "github.com/prebid/prebid-server/adapters/advangelists" + "github.com/prebid/prebid-server/adapters/aja" "github.com/prebid/prebid-server/adapters/applogy" "github.com/prebid/prebid-server/adapters/appnexus" "github.com/prebid/prebid-server/adapters/audienceNetwork" diff --git a/usersync/usersyncers/syncer.go b/usersync/usersyncers/syncer.go index fabc94192e2..8137ade6041 100644 --- a/usersync/usersyncers/syncer.go +++ b/usersync/usersyncers/syncer.go @@ -1,7 +1,6 @@ package usersyncers import ( - "github.com/prebid/prebid-server/adapters/aja" "strings" "text/template" @@ -14,6 +13,7 @@ import ( "github.com/prebid/prebid-server/adapters/adpone" "github.com/prebid/prebid-server/adapters/adtelligent" "github.com/prebid/prebid-server/adapters/advangelists" + "github.com/prebid/prebid-server/adapters/aja" "github.com/prebid/prebid-server/adapters/appnexus" "github.com/prebid/prebid-server/adapters/audienceNetwork" "github.com/prebid/prebid-server/adapters/beachfront" From 421e681076bb1f2cb9f9704dd082cfc587efc4fa Mon Sep 17 00:00:00 2001 From: sambaiz Date: Fri, 24 Apr 2020 17:35:29 +0900 Subject: [PATCH 4/9] copy bidReq --- adapters/aja/aja.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/adapters/aja/aja.go b/adapters/aja/aja.go index 504a07687b2..f85bf2ad904 100644 --- a/adapters/aja/aja.go +++ b/adapters/aja/aja.go @@ -28,10 +28,10 @@ func (a *AJAAdapter) MakeRequests(bidReq *openrtb.BidRequest, extraInfo *adapter impsByTagID[imp.TagID] = append(impsByTagID[imp.TagID], imp) } - originalImps := bidReq.Imp + req := *bidReq for _, imps := range impsByTagID { - bidReq.Imp = imps - body, err := json.Marshal(bidReq) + req.Imp = imps + body, err := json.Marshal(req) if err != nil { errs = append(errs, err) continue @@ -42,7 +42,6 @@ func (a *AJAAdapter) MakeRequests(bidReq *openrtb.BidRequest, extraInfo *adapter Body: body, }) } - bidReq.Imp = originalImps return } From e0ae3affa5678360a6e1d78712d6c83d43bef8b5 Mon Sep 17 00:00:00 2001 From: sambaiz Date: Fri, 24 Apr 2020 19:25:51 +0900 Subject: [PATCH 5/9] add some supplemental --- adapters/aja/aja.go | 8 +++-- .../supplemental/invalid-ext-bidder.json | 36 +++++++++++++++++++ .../aja/ajatest/supplemental/invalid-ext.json | 34 ++++++++++++++++++ 3 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 adapters/aja/ajatest/supplemental/invalid-ext-bidder.json create mode 100644 adapters/aja/ajatest/supplemental/invalid-ext.json diff --git a/adapters/aja/aja.go b/adapters/aja/aja.go index f85bf2ad904..0e76781a5e6 100644 --- a/adapters/aja/aja.go +++ b/adapters/aja/aja.go @@ -16,6 +16,7 @@ type AJAAdapter struct { func (a *AJAAdapter) MakeRequests(bidReq *openrtb.BidRequest, extraInfo *adapters.ExtraRequestInfo) (adapterReqs []*adapters.RequestData, errs []error) { // split imps by tagid + tagIDs := []string{} impsByTagID := map[string][]openrtb.Imp{} for _, imp := range bidReq.Imp { extAJA, err := parseExtAJA(imp) @@ -25,12 +26,15 @@ func (a *AJAAdapter) MakeRequests(bidReq *openrtb.BidRequest, extraInfo *adapter } imp.TagID = extAJA.AdSpotID imp.Ext = nil + if _, ok := impsByTagID[imp.TagID]; !ok { + tagIDs = append(tagIDs, imp.TagID) + } impsByTagID[imp.TagID] = append(impsByTagID[imp.TagID], imp) } req := *bidReq - for _, imps := range impsByTagID { - req.Imp = imps + for _, tagID := range tagIDs { + req.Imp = impsByTagID[tagID] body, err := json.Marshal(req) if err != nil { errs = append(errs, err) diff --git a/adapters/aja/ajatest/supplemental/invalid-ext-bidder.json b/adapters/aja/ajatest/supplemental/invalid-ext-bidder.json new file mode 100644 index 00000000000..b12b431b0ed --- /dev/null +++ b/adapters/aja/ajatest/supplemental/invalid-ext-bidder.json @@ -0,0 +1,36 @@ +{ + "mockBidRequest": { + "id": "test-req-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": ["video/mp4"], + "w": 640, + "h": 480 + }, + "ext": { + "bidder": { + "asi": 111 + } + } + } + ], + "user": { + "buyeruid": "test-uid" + }, + "tmax": 500 + }, + + "httpCalls": [], + + "expectedBidResponses": [], + + "expectedMakeRequestsErrors": [ + { + "value": "Failed to unmarshal ext.bidder impID: test-imp-id err: json: cannot unmarshal number into Go struct field ExtImpAJA.asi of type string", + "comparison": "literal" + } + + ] +} \ No newline at end of file diff --git a/adapters/aja/ajatest/supplemental/invalid-ext.json b/adapters/aja/ajatest/supplemental/invalid-ext.json new file mode 100644 index 00000000000..61b79944762 --- /dev/null +++ b/adapters/aja/ajatest/supplemental/invalid-ext.json @@ -0,0 +1,34 @@ +{ + "mockBidRequest": { + "id": "test-req-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": ["video/mp4"], + "w": 640, + "h": 480 + }, + "ext": { + "bidder": 111 + } + } + ], + "user": { + "buyeruid": "test-uid" + }, + "tmax": 500 + }, + + "httpCalls": [], + + "expectedBidResponses": [], + + "expectedMakeRequestsErrors": [ + { + "value": "Failed to unmarshal ext.bidder impID: test-imp-id err: json: cannot unmarshal number into Go value of type openrtb_ext.ExtImpAJA", + "comparison": "literal" + } + + ] +} \ No newline at end of file From 365ae854f8a578912fc294443eecedb25ad1f602 Mon Sep 17 00:00:00 2001 From: sambaiz Date: Mon, 27 Apr 2020 12:24:58 +0900 Subject: [PATCH 6/9] remove unnecessary label --- adapters/aja/aja.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/adapters/aja/aja.go b/adapters/aja/aja.go index 0e76781a5e6..d2f451b1582 100644 --- a/adapters/aja/aja.go +++ b/adapters/aja/aja.go @@ -98,7 +98,6 @@ func (a *AJAAdapter) MakeBids(bidReq *openrtb.BidRequest, adapterReq *adapters.R for _, seatbid := range bidResp.SeatBid { for _, bid := range seatbid.Bid { - impID: for _, imp := range bidReq.Imp { if imp.ID == bid.ImpID { var bidType openrtb_ext.BidType @@ -116,7 +115,7 @@ func (a *AJAAdapter) MakeBids(bidReq *openrtb.BidRequest, adapterReq *adapters.R Bid: &bid, BidType: bidType, }) - break impID + break } } } From 0f8189056da7d9c8af9df370bc366425af06fe82 Mon Sep 17 00:00:00 2001 From: sambaiz Date: Mon, 27 Apr 2020 15:20:39 +0900 Subject: [PATCH 7/9] add supplementals --- adapters/aja/aja.go | 4 +- .../supplemental/invalid-bid-type.json | 71 +++++++++++++++++++ .../supplemental/status-bad-request.json | 64 +++++++++++++++++ .../status-internal-server-error.json | 64 +++++++++++++++++ .../supplemental/status-no-content.json | 57 +++++++++++++++ 5 files changed, 259 insertions(+), 1 deletion(-) create mode 100644 adapters/aja/ajatest/supplemental/invalid-bid-type.json create mode 100644 adapters/aja/ajatest/supplemental/status-bad-request.json create mode 100644 adapters/aja/ajatest/supplemental/status-internal-server-error.json create mode 100644 adapters/aja/ajatest/supplemental/status-no-content.json diff --git a/adapters/aja/aja.go b/adapters/aja/aja.go index d2f451b1582..7f85d02f10a 100644 --- a/adapters/aja/aja.go +++ b/adapters/aja/aja.go @@ -37,7 +37,9 @@ func (a *AJAAdapter) MakeRequests(bidReq *openrtb.BidRequest, extraInfo *adapter req.Imp = impsByTagID[tagID] body, err := json.Marshal(req) if err != nil { - errs = append(errs, err) + errs = append(errs, &errortypes.BadInput{ + Message: fmt.Sprintf("Failed to unmarshal bidrequest ID: %s err: %s", bidReq.ID, err), + }) continue } adapterReqs = append(adapterReqs, &adapters.RequestData{ diff --git a/adapters/aja/ajatest/supplemental/invalid-bid-type.json b/adapters/aja/ajatest/supplemental/invalid-bid-type.json new file mode 100644 index 00000000000..1bba635f731 --- /dev/null +++ b/adapters/aja/ajatest/supplemental/invalid-bid-type.json @@ -0,0 +1,71 @@ +{ + "mockBidRequest": { + "id": "test-req-id", + "imp": [ + { + "id": "test-imp-id", + "ext": { + "bidder": { + "asi": "test-asi" + } + } + } + ], + "user": { + "buyeruid": "test-uid" + }, + "tmax": 500 + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://localhost/bid/4", + "headers": {}, + "body": { + "id": "test-req-id", + "imp": [ + { + "id": "test-imp-id", + "tagid": "test-asi" + } + ], + "user": { + "buyeruid": "test-uid" + }, + "tmax": 500 + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-req-id", + "seatbid": [ + { + "bid": [ + { + "id": "test-bid-id", + "impid": "test-imp-id", + "price": 1, + "adm": "", + "crid": "test-creative-id" + } + ] + } + ], + "bidid": "test-seatbid-id", + "cur": "USD" + } + } + } + ], + + "expectedBidResponses": [], + + "expectedMakeBidsErrors": [ + { + "value": "Response received for unexpected type of bid bidID: test-bid-id", + "comparison": "literal" + } + ] +} \ No newline at end of file diff --git a/adapters/aja/ajatest/supplemental/status-bad-request.json b/adapters/aja/ajatest/supplemental/status-bad-request.json new file mode 100644 index 00000000000..a47db8bbca9 --- /dev/null +++ b/adapters/aja/ajatest/supplemental/status-bad-request.json @@ -0,0 +1,64 @@ +{ + "mockBidRequest": { + "id": "test-req-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": ["video/mp4"], + "w": 640, + "h": 480 + }, + "ext": { + "bidder": { + "asi": "test-asi" + } + } + } + ], + "user": { + "buyeruid": "test-uid" + }, + "tmax": 500 + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://localhost/bid/4", + "headers": {}, + "body": { + "id": "test-req-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": ["video/mp4"], + "w": 640, + "h": 480 + }, + "tagid": "test-asi" + } + ], + "user": { + "buyeruid": "test-uid" + }, + "tmax": 500 + } + }, + "mockResponse": { + "status": 400, + "body": {} + } + } + ], + + "expectedBidResponses": [], + + "expectedMakeBidsErrors": [ + { + "value": "Unexpected status code: 400", + "comparison": "literal" + } + ] +} \ No newline at end of file diff --git a/adapters/aja/ajatest/supplemental/status-internal-server-error.json b/adapters/aja/ajatest/supplemental/status-internal-server-error.json new file mode 100644 index 00000000000..5d36dc5dcdc --- /dev/null +++ b/adapters/aja/ajatest/supplemental/status-internal-server-error.json @@ -0,0 +1,64 @@ +{ + "mockBidRequest": { + "id": "test-req-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": ["video/mp4"], + "w": 640, + "h": 480 + }, + "ext": { + "bidder": { + "asi": "test-asi" + } + } + } + ], + "user": { + "buyeruid": "test-uid" + }, + "tmax": 500 + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://localhost/bid/4", + "headers": {}, + "body": { + "id": "test-req-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": ["video/mp4"], + "w": 640, + "h": 480 + }, + "tagid": "test-asi" + } + ], + "user": { + "buyeruid": "test-uid" + }, + "tmax": 500 + } + }, + "mockResponse": { + "status": 500, + "body": {} + } + } + ], + + "expectedBidResponses": [], + + "expectedMakeBidsErrors": [ + { + "value": "Unexpected status code: 500", + "comparison": "literal" + } + ] +} \ No newline at end of file diff --git a/adapters/aja/ajatest/supplemental/status-no-content.json b/adapters/aja/ajatest/supplemental/status-no-content.json new file mode 100644 index 00000000000..e12fd21a26a --- /dev/null +++ b/adapters/aja/ajatest/supplemental/status-no-content.json @@ -0,0 +1,57 @@ +{ + "mockBidRequest": { + "id": "test-req-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": ["video/mp4"], + "w": 640, + "h": 480 + }, + "ext": { + "bidder": { + "asi": "test-asi" + } + } + } + ], + "user": { + "buyeruid": "test-uid" + }, + "tmax": 500 + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://localhost/bid/4", + "headers": {}, + "body": { + "id": "test-req-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": ["video/mp4"], + "w": 640, + "h": 480 + }, + "tagid": "test-asi" + } + ], + "user": { + "buyeruid": "test-uid" + }, + "tmax": 500 + } + }, + "mockResponse": { + "status": 204, + "body": {} + } + } + ], + + "expectedBidResponses": [] +} \ No newline at end of file From d4b0e3f0ed13fe7b710d6ed6f7c99c1a7097ce1d Mon Sep 17 00:00:00 2001 From: sambaiz Date: Mon, 27 Apr 2020 15:37:05 +0900 Subject: [PATCH 8/9] fix supplemental --- adapters/aja/ajatest/supplemental/invalid-ext.json | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/adapters/aja/ajatest/supplemental/invalid-ext.json b/adapters/aja/ajatest/supplemental/invalid-ext.json index 61b79944762..478222d0ee9 100644 --- a/adapters/aja/ajatest/supplemental/invalid-ext.json +++ b/adapters/aja/ajatest/supplemental/invalid-ext.json @@ -9,9 +9,7 @@ "w": 640, "h": 480 }, - "ext": { - "bidder": 111 - } + "ext": 111 } ], "user": { @@ -26,7 +24,7 @@ "expectedMakeRequestsErrors": [ { - "value": "Failed to unmarshal ext.bidder impID: test-imp-id err: json: cannot unmarshal number into Go value of type openrtb_ext.ExtImpAJA", + "value": "Failed to unmarshal ext impID: test-imp-id err: json: cannot unmarshal number into Go value of type adapters.ExtImpBidder", "comparison": "literal" } From f9ef8468dd96636abad50b961e5ea7c320500c3d Mon Sep 17 00:00:00 2001 From: sambaiz Date: Mon, 27 Apr 2020 18:58:45 +0900 Subject: [PATCH 9/9] run validate --- adapters/aja/aja.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adapters/aja/aja.go b/adapters/aja/aja.go index 7f85d02f10a..a8db3f6ddbc 100644 --- a/adapters/aja/aja.go +++ b/adapters/aja/aja.go @@ -37,7 +37,7 @@ func (a *AJAAdapter) MakeRequests(bidReq *openrtb.BidRequest, extraInfo *adapter req.Imp = impsByTagID[tagID] body, err := json.Marshal(req) if err != nil { - errs = append(errs, &errortypes.BadInput{ + errs = append(errs, &errortypes.BadInput{ Message: fmt.Sprintf("Failed to unmarshal bidrequest ID: %s err: %s", bidReq.ID, err), }) continue