diff --git a/adapters/33across/usersync_test.go b/adapters/33across/usersync_test.go index f4bb28150de..a5e301b1082 100644 --- a/adapters/33across/usersync_test.go +++ b/adapters/33across/usersync_test.go @@ -5,20 +5,30 @@ import ( "text/template" "github.com/prebid/prebid-server/privacy" + "github.com/prebid/prebid-server/privacy/ccpa" + "github.com/prebid/prebid-server/privacy/gdpr" "github.com/stretchr/testify/assert" ) func Test33AcrossSyncer(t *testing.T) { - syncURL := "https://ic.tynt.com/r/d?m=xch&rt=html&ri=123&ru=%2Fsetuid%3Fbidder%3D33across%26uid%3D33XUSERID33X&id=zzz000000000002zzz" + syncURL := "https://ic.tynt.com/r/d?m=xch&rt=html&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&ru=%2Fsetuid%3Fbidder%3D33across%26uid%3D33XUSERID33X&id=zzz000000000002zzz" syncURLTemplate := template.Must( template.New("sync-template").Parse(syncURL), ) syncer := New33AcrossSyncer(syncURLTemplate) - syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{}) + syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{ + GDPR: gdpr.Policy{ + Signal: "A", + Consent: "B", + }, + CCPA: ccpa.Policy{ + Value: "C", + }, + }) assert.NoError(t, err) - assert.Equal(t, "https://ic.tynt.com/r/d?m=xch&rt=html&ri=123&ru=%2Fsetuid%3Fbidder%3D33across%26uid%3D33XUSERID33X&id=zzz000000000002zzz", syncInfo.URL) + assert.Equal(t, "https://ic.tynt.com/r/d?m=xch&rt=html&gdpr=A&gdpr_consent=B&us_privacy=C&ru=%2Fsetuid%3Fbidder%3D33across%26uid%3D33XUSERID33X&id=zzz000000000002zzz", syncInfo.URL) assert.Equal(t, "iframe", syncInfo.Type) assert.EqualValues(t, 58, syncer.GDPRVendorID()) assert.False(t, syncInfo.SupportCORS) diff --git a/adapters/adform/adform_test.go b/adapters/adform/adform_test.go index e59bd951858..63646f5f7f5 100644 --- a/adapters/adform/adform_test.go +++ b/adapters/adform/adform_test.go @@ -21,6 +21,8 @@ import ( "github.com/prebid/prebid-server/adapters" "github.com/prebid/prebid-server/config" "github.com/prebid/prebid-server/openrtb_ext" + + "github.com/stretchr/testify/assert" ) func TestJsonSamples(t *testing.T) { @@ -597,3 +599,77 @@ func TestPriceTypeUrlParameterCreation(t *testing.T) { } } } + +// Asserts that toOpenRtbBidResponse() creates a *adapters.BidderResponse with +// the currency of the last valid []*adformBid element and the expected number of bids +func TestToOpenRtbBidResponse(t *testing.T) { + expectedBids := 3 + lastCurrency, anotherCurrency, emptyCurrency := "EUR", "USD", "" + + request := &openrtb.BidRequest{ + ID: "test-request-id", + Imp: []openrtb.Imp{ + { + ID: "banner-imp-no1", + Ext: json.RawMessage(`{"bidder1": { "mid": "32341" }}`), + Banner: &openrtb.Banner{}, + }, + { + ID: "banner-imp-no2", + Ext: json.RawMessage(`{"bidder1": { "mid": "32342" }}`), + Banner: &openrtb.Banner{}, + }, + { + ID: "banner-imp-no3", + Ext: json.RawMessage(`{"bidder1": { "mid": "32343" }}`), + Banner: &openrtb.Banner{}, + }, + { + ID: "banner-imp-no4", + Ext: json.RawMessage(`{"bidder1": { "mid": "32344" }}`), + Banner: &openrtb.Banner{}, + }, + }, + Device: &openrtb.Device{UA: "ua", IP: "ip"}, + User: &openrtb.User{BuyerUID: "buyerUID"}, + } + + testAdformBids := []*adformBid{ + { + ResponseType: "banner", + Banner: "banner-content1", + Price: 1.23, + Currency: anotherCurrency, + Width: 300, + Height: 200, + DealId: "dealId1", + CreativeId: "creativeId1", + }, + {}, + { + ResponseType: "banner", + Banner: "banner-content3", + Price: 1.24, + Currency: emptyCurrency, + Width: 300, + Height: 200, + DealId: "dealId3", + CreativeId: "creativeId3", + }, + { + ResponseType: "banner", + Banner: "banner-content4", + Price: 1.25, + Currency: lastCurrency, + Width: 300, + Height: 200, + DealId: "dealId4", + CreativeId: "creativeId4", + }, + } + + actualBidResponse := toOpenRtbBidResponse(testAdformBids, request) + + assert.Equalf(t, expectedBids, len(actualBidResponse.Bids), "bid count") + assert.Equalf(t, lastCurrency, actualBidResponse.Currency, "currency") +} diff --git a/adapters/adkernel/usersync_test.go b/adapters/adkernel/usersync_test.go index bd09c361a03..0d539d11ee0 100644 --- a/adapters/adkernel/usersync_test.go +++ b/adapters/adkernel/usersync_test.go @@ -5,12 +5,13 @@ import ( "text/template" "github.com/prebid/prebid-server/privacy" + "github.com/prebid/prebid-server/privacy/ccpa" "github.com/prebid/prebid-server/privacy/gdpr" "github.com/stretchr/testify/assert" ) func TestAdkernelAdnSyncer(t *testing.T) { - syncURL := "https://sync.adkernel.com/user-sync?t=image&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&r=https%3A%2F%2Flocalhost%3A8888%2Fsetuid%3Fbidder%3Dadkernel%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7BUID%7D" + syncURL := "https://sync.adkernel.com/user-sync?t=image&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r=https%3A%2F%2Flocalhost%3A8888%2Fsetuid%3Fbidder%3Dadkernel%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7BUID%7D" syncURLTemplate := template.Must( template.New("sync-template").Parse(syncURL), ) @@ -21,10 +22,13 @@ func TestAdkernelAdnSyncer(t *testing.T) { Signal: "1", Consent: "BONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw", }, + CCPA: ccpa.Policy{ + Value: "1NYN", + }, }) assert.NoError(t, err) - assert.Equal(t, "https://sync.adkernel.com/user-sync?t=image&gdpr=1&gdpr_consent=BONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw&r=https%3A%2F%2Flocalhost%3A8888%2Fsetuid%3Fbidder%3Dadkernel%26gdpr%3D1%26gdpr_consent%3DBONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw%26uid%3D%7BUID%7D", syncInfo.URL) + assert.Equal(t, "https://sync.adkernel.com/user-sync?t=image&gdpr=1&gdpr_consent=BONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw&us_privacy=1NYN&r=https%3A%2F%2Flocalhost%3A8888%2Fsetuid%3Fbidder%3Dadkernel%26gdpr%3D1%26gdpr_consent%3DBONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw%26uid%3D%7BUID%7D", syncInfo.URL) assert.Equal(t, "redirect", syncInfo.Type) assert.EqualValues(t, adkernelGDPRVendorID, syncer.GDPRVendorID()) assert.Equal(t, false, syncInfo.SupportCORS) diff --git a/adapters/adkernelAdn/usersync_test.go b/adapters/adkernelAdn/usersync_test.go index 007cacce29c..ecc759bdf70 100644 --- a/adapters/adkernelAdn/usersync_test.go +++ b/adapters/adkernelAdn/usersync_test.go @@ -5,12 +5,13 @@ import ( "text/template" "github.com/prebid/prebid-server/privacy" + "github.com/prebid/prebid-server/privacy/ccpa" "github.com/prebid/prebid-server/privacy/gdpr" "github.com/stretchr/testify/assert" ) func TestAdkernelAdnSyncer(t *testing.T) { - syncURL := "https://tag.adkernel.com/syncr?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&r=https%3A%2F%2Flocalhost%3A8888%2Fsetuid%3Fbidder%3DadkernelAdn%26uid%3D%7BUID%7D" + syncURL := "https://tag.adkernel.com/syncr?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r=https%3A%2F%2Flocalhost%3A8888%2Fsetuid%3Fbidder%3DadkernelAdn%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7BUID%7D" syncURLTemplate := template.Must( template.New("sync-template").Parse(syncURL), ) @@ -21,10 +22,13 @@ func TestAdkernelAdnSyncer(t *testing.T) { Signal: "1", Consent: "BONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw", }, + CCPA: ccpa.Policy{ + Value: "1NYN", + }, }) assert.NoError(t, err) - assert.Equal(t, "https://tag.adkernel.com/syncr?gdpr=1&gdpr_consent=BONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw&r=https%3A%2F%2Flocalhost%3A8888%2Fsetuid%3Fbidder%3DadkernelAdn%26uid%3D%7BUID%7D", syncInfo.URL) + assert.Equal(t, "https://tag.adkernel.com/syncr?gdpr=1&gdpr_consent=BONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw&us_privacy=1NYN&r=https%3A%2F%2Flocalhost%3A8888%2Fsetuid%3Fbidder%3DadkernelAdn%26gdpr%3D1%26gdpr_consent%3DBONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw%26uid%3D%7BUID%7D", syncInfo.URL) assert.Equal(t, "redirect", syncInfo.Type) assert.EqualValues(t, adkernelGDPRVendorID, syncer.GDPRVendorID()) assert.Equal(t, false, syncInfo.SupportCORS) diff --git a/adapters/adpone/adpone.go b/adapters/adpone/adpone.go index 345a4988580..b1822a0ac07 100644 --- a/adapters/adpone/adpone.go +++ b/adapters/adpone/adpone.go @@ -3,9 +3,10 @@ package adpone import ( "encoding/json" "fmt" - "github.com/prebid/prebid-server/openrtb_ext" "net/http" + "github.com/prebid/prebid-server/openrtb_ext" + "github.com/mxmCherry/openrtb" "github.com/prebid/prebid-server/adapters" "github.com/prebid/prebid-server/errortypes" diff --git a/adapters/adtelligent/adtelligenttest/supplemental/audio.json b/adapters/adtelligent/adtelligenttest/supplemental/audio.json index aa9a40bcc99..d8904251e11 100644 --- a/adapters/adtelligent/adtelligenttest/supplemental/audio.json +++ b/adapters/adtelligent/adtelligenttest/supplemental/audio.json @@ -9,7 +9,7 @@ }, "ext": { "bidder": { - "placementId": 10433394 + "placementId": 1 } } } diff --git a/adapters/adtelligent/adtelligenttest/supplemental/native.json b/adapters/adtelligent/adtelligenttest/supplemental/native.json index 90ddff2f679..00fb3984bc7 100644 --- a/adapters/adtelligent/adtelligenttest/supplemental/native.json +++ b/adapters/adtelligent/adtelligenttest/supplemental/native.json @@ -9,7 +9,7 @@ }, "ext": { "bidder": { - "placementId": 10433394 + "placementId": 1 } } } diff --git a/adapters/applogy/applogy.go b/adapters/applogy/applogy.go new file mode 100644 index 00000000000..a1215e24940 --- /dev/null +++ b/adapters/applogy/applogy.go @@ -0,0 +1,160 @@ +package applogy + +import ( + "encoding/json" + "errors" + "net/http" + "strconv" + + "github.com/mxmCherry/openrtb" + "github.com/prebid/prebid-server/adapters" + "github.com/prebid/prebid-server/errortypes" + "github.com/prebid/prebid-server/openrtb_ext" +) + +type ApplogyAdapter struct { + endpoint string +} + +func (a *ApplogyAdapter) MakeRequests(request *openrtb.BidRequest, _ *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { + headers := http.Header{} + headers.Add("Content-Type", "application/json;charset=utf-8") + headers.Add("Accept", "application/json") + impressions := request.Imp + result := make([]*adapters.RequestData, 0, len(impressions)) + errs := make([]error, 0, len(impressions)) + + for i, impression := range impressions { + if impression.Banner == nil && impression.Video == nil && impression.Native == nil { + errs = append(errs, &errortypes.BadInput{ + Message: "Applogy only supports banner, video or native ads", + }) + continue + } + if impression.Banner != nil { + banner := impression.Banner + if banner.W == nil || banner.H == nil || *banner.W == 0 || *banner.H == 0 { + if len(banner.Format) == 0 { + errs = append(errs, &errortypes.BadInput{ + Message: "banner size information missing", + }) + continue + } + format := banner.Format[0] + banner.W = &format.W + banner.H = &format.H + } + } + if len(impression.Ext) == 0 { + errs = append(errs, errors.New("impression extensions required")) + continue + } + var bidderExt adapters.ExtImpBidder + err := json.Unmarshal(impression.Ext, &bidderExt) + if err != nil { + errs = append(errs, err) + continue + } + if len(bidderExt.Bidder) == 0 { + errs = append(errs, errors.New("bidder required")) + continue + } + var impressionExt openrtb_ext.ExtImpApplogy + err = json.Unmarshal(bidderExt.Bidder, &impressionExt) + if err != nil { + errs = append(errs, err) + continue + } + if impressionExt.Token == "" { + errs = append(errs, errors.New("Applogy token required")) + continue + } + request.Imp = impressions[i : i+1] + body, err := json.Marshal(request) + if err != nil { + errs = append(errs, err) + continue + } + result = append(result, &adapters.RequestData{ + Method: "POST", + Uri: a.endpoint + "/" + impressionExt.Token, + Body: body, + Headers: headers, + }) + } + + request.Imp = impressions + + if len(result) == 0 { + return nil, errs + } + return result, errs +} + +func (a *ApplogyAdapter) MakeBids(request *openrtb.BidRequest, _ *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) { + var errs []error + + switch responseData.StatusCode { + case http.StatusNoContent: + return nil, nil + case http.StatusBadRequest: + return nil, []error{&errortypes.BadInput{ + Message: "unexpected status code: " + strconv.Itoa(responseData.StatusCode), + }} + case http.StatusOK: + break + default: + return nil, []error{&errortypes.BadServerResponse{ + Message: "unexpected status code: " + strconv.Itoa(responseData.StatusCode), + }} + } + + var bidResponse openrtb.BidResponse + err := json.Unmarshal(responseData.Body, &bidResponse) + if err != nil { + return nil, []error{&errortypes.BadServerResponse{ + Message: err.Error(), + }} + } + + response := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp)) + + for _, seatBid := range bidResponse.SeatBid { + for _, bid := range seatBid.Bid { + bid := bid // pin https://github.com/kyoh86/scopelint#whats-this + var bidType openrtb_ext.BidType + for _, impression := range request.Imp { + if impression.ID != bid.ImpID { + continue + } + switch { + case impression.Banner != nil: + bidType = openrtb_ext.BidTypeBanner + case impression.Video != nil: + bidType = openrtb_ext.BidTypeVideo + case impression.Native != nil: + bidType = openrtb_ext.BidTypeNative + } + break + } + if bidType == "" { + errs = append(errs, &errortypes.BadServerResponse{ + Message: "ignoring bid id=" + bid.ID + ", request doesn't contain any valid impression with id=" + bid.ImpID, + }) + continue + } + response.Bids = append(response.Bids, &adapters.TypedBid{ + Bid: &bid, + BidType: bidType, + }) + } + } + + return response, errs +} + +func NewApplogyBidder(endpoint string) *ApplogyAdapter { + return &ApplogyAdapter{ + endpoint: endpoint, + } +} diff --git a/adapters/applogy/applogy_test.go b/adapters/applogy/applogy_test.go new file mode 100644 index 00000000000..8883db5786a --- /dev/null +++ b/adapters/applogy/applogy_test.go @@ -0,0 +1,11 @@ +package applogy + +import ( + "testing" + + "github.com/prebid/prebid-server/adapters/adapterstest" +) + +func TestJsonSamples(t *testing.T) { + adapterstest.RunJSONBidderTest(t, "applogytest", NewApplogyBidder("http://example.com/prebid")) +} diff --git a/adapters/applogy/applogytest/exemplary/simple-banner.json b/adapters/applogy/applogytest/exemplary/simple-banner.json new file mode 100644 index 00000000000..a3926dea623 --- /dev/null +++ b/adapters/applogy/applogytest/exemplary/simple-banner.json @@ -0,0 +1,170 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [{ + "id": "test-impression-id-1", + "banner": { + "format": [{ + "h": 250, + "w": 300 + }] + }, + "ext": { + "bidder": { + "token": "test-token-1" + } + } + }, { + "id": "test-impression-id-2", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "token": "test-token-1" + } + } + }, { + "id": "test-impression-id-3", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "token": "test-token-2" + } + } + }] + }, + "httpCalls": [{ + "expectedRequest": { + "uri": "http://example.com/prebid/test-token-1", + "body": { + "id": "test-request-id", + "imp": [{ + "id": "test-impression-id-1", + "banner": { + "format": [{ + "h": 250, + "w": 300 + }], + "h": 250, + "w": 300 + }, + "ext": { + "bidder": { + "token": "test-token-1" + } + } + }] + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-response-id", + "seatbid": [{ + "bid": [{ + "id": "test-bid-id-1", + "impid": "test-impression-id-1", + "price": 1 + }] + }] + } + } + }, { + "expectedRequest": { + "uri": "http://example.com/prebid/test-token-1", + "body": { + "id": "test-request-id", + "imp": [{ + "id": "test-impression-id-2", + "banner": { + "h": 250, + "w": 300 + }, + "ext": { + "bidder": { + "token": "test-token-1" + } + } + }] + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-response-id-2", + "seatbid": [{ + "bid": [{ + "id": "test-bid-id-2", + "impid": "test-impression-id-2", + "price": 2 + }] + }] + } + } + }, { + "expectedRequest": { + "uri": "http://example.com/prebid/test-token-2", + "body": { + "id": "test-request-id", + "imp": [{ + "id": "test-impression-id-3", + "banner": { + "h": 250, + "w": 300 + }, + "ext": { + "bidder": { + "token": "test-token-2" + } + } + }] + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-response-id-3", + "seatbid": [{ + "bid": [{ + "id": "test-bid-id-3", + "impid": "test-impression-id-3", + "price": 3 + }] + }] + } + } + }], + "expectedBidResponses": [{ + "bids": [{ + "bid": { + "id": "test-bid-id-1", + "impid": "test-impression-id-1", + "price": 1 + }, + "type": "banner" + }] + }, { + "bids": [{ + "bid": { + "id": "test-bid-id-2", + "impid": "test-impression-id-2", + "price": 2 + }, + "type": "banner" + }] + }, { + "bids": [{ + "bid": { + "id": "test-bid-id-3", + "impid": "test-impression-id-3", + "price": 3 + }, + "type": "banner" + }] + }] +} diff --git a/adapters/applogy/applogytest/exemplary/simple-native.json b/adapters/applogy/applogytest/exemplary/simple-native.json new file mode 100644 index 00000000000..84565ec5575 --- /dev/null +++ b/adapters/applogy/applogytest/exemplary/simple-native.json @@ -0,0 +1,164 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [{ + "id": "test-impression-id-1", + "native": { + "request": "{\"ver\":\"1.1\",\"context\":1,\"contextsubtype\":11,\"plcmttype\":4,\"plcmtcnt\":1,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":500}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":1,\"hmin\":1}},{\"id\":3,\"required\":0,\"data\":{\"type\":1,\"len\":200}},{\"id\":4,\"required\":0,\"data\":{\"type\":2,\"len\":15000}},{\"id\":5,\"required\":0,\"data\":{\"type\":6,\"len\":40}},{\"id\":6,\"required\":0,\"data\":{\"type\":500}}]}", + "ver": "1.1" + }, + "ext": { + "bidder": { + "token": "test-token-1" + } + } + }, { + "id": "test-impression-id-2", + "native": { + "request": "{\"ver\":\"1.1\",\"context\":1,\"contextsubtype\":11,\"plcmttype\":4,\"plcmtcnt\":1,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":500}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":1,\"hmin\":1}},{\"id\":3,\"required\":0,\"data\":{\"type\":1,\"len\":200}},{\"id\":4,\"required\":0,\"data\":{\"type\":2,\"len\":15000}},{\"id\":5,\"required\":0,\"data\":{\"type\":6,\"len\":40}},{\"id\":6,\"required\":0,\"data\":{\"type\":500}}]}", + "ver": "1.1" + }, + "ext": { + "bidder": { + "token": "test-token-1" + } + } + }, { + "id": "test-impression-id-3", + "native": { + "request": "{\"ver\":\"1.1\",\"context\":1,\"contextsubtype\":11,\"plcmttype\":4,\"plcmtcnt\":1,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":500}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":1,\"hmin\":1}},{\"id\":3,\"required\":0,\"data\":{\"type\":1,\"len\":200}},{\"id\":4,\"required\":0,\"data\":{\"type\":2,\"len\":15000}},{\"id\":5,\"required\":0,\"data\":{\"type\":6,\"len\":40}},{\"id\":6,\"required\":0,\"data\":{\"type\":500}}]}", + "ver": "1.1" + }, + "ext": { + "bidder": { + "token": "test-token-2" + } + } + }] + }, + "httpCalls": [{ + "expectedRequest": { + "uri": "http://example.com/prebid/test-token-1", + "body": { + "id": "test-request-id", + "imp": [{ + "id": "test-impression-id-1", + "native": { + "request": "{\"ver\":\"1.1\",\"context\":1,\"contextsubtype\":11,\"plcmttype\":4,\"plcmtcnt\":1,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":500}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":1,\"hmin\":1}},{\"id\":3,\"required\":0,\"data\":{\"type\":1,\"len\":200}},{\"id\":4,\"required\":0,\"data\":{\"type\":2,\"len\":15000}},{\"id\":5,\"required\":0,\"data\":{\"type\":6,\"len\":40}},{\"id\":6,\"required\":0,\"data\":{\"type\":500}}]}", + "ver": "1.1" + }, + "ext": { + "bidder": { + "token": "test-token-1" + } + } + }] + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-response-id", + "seatbid": [{ + "bid": [{ + "id": "test-bid-id-1", + "impid": "test-impression-id-1", + "price": 1 + }] + }] + } + } + }, { + "expectedRequest": { + "uri": "http://example.com/prebid/test-token-1", + "body": { + "id": "test-request-id", + "imp": [{ + "id": "test-impression-id-2", + "native": { + "request": "{\"ver\":\"1.1\",\"context\":1,\"contextsubtype\":11,\"plcmttype\":4,\"plcmtcnt\":1,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":500}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":1,\"hmin\":1}},{\"id\":3,\"required\":0,\"data\":{\"type\":1,\"len\":200}},{\"id\":4,\"required\":0,\"data\":{\"type\":2,\"len\":15000}},{\"id\":5,\"required\":0,\"data\":{\"type\":6,\"len\":40}},{\"id\":6,\"required\":0,\"data\":{\"type\":500}}]}", + "ver": "1.1" + }, + "ext": { + "bidder": { + "token": "test-token-1" + } + } + }] + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-response-id-2", + "seatbid": [{ + "bid": [{ + "id": "test-bid-id-2", + "impid": "test-impression-id-2", + "price": 2 + }] + }] + } + } + }, { + "expectedRequest": { + "uri": "http://example.com/prebid/test-token-2", + "body": { + "id": "test-request-id", + "imp": [{ + "id": "test-impression-id-3", + "native": { + "request": "{\"ver\":\"1.1\",\"context\":1,\"contextsubtype\":11,\"plcmttype\":4,\"plcmtcnt\":1,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":500}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":1,\"hmin\":1}},{\"id\":3,\"required\":0,\"data\":{\"type\":1,\"len\":200}},{\"id\":4,\"required\":0,\"data\":{\"type\":2,\"len\":15000}},{\"id\":5,\"required\":0,\"data\":{\"type\":6,\"len\":40}},{\"id\":6,\"required\":0,\"data\":{\"type\":500}}]}", + "ver": "1.1" + }, + "ext": { + "bidder": { + "token": "test-token-2" + } + } + }] + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-response-id-3", + "seatbid": [{ + "bid": [{ + "id": "test-bid-id-3", + "impid": "test-impression-id-3", + "price": 3 + }] + }] + } + } + }], + "expectedBidResponses": [{ + "bids": [{ + "bid": { + "id": "test-bid-id-1", + "impid": "test-impression-id-1", + "price": 1 + }, + "type": "native" + }] + }, { + "bids": [{ + "bid": { + "id": "test-bid-id-2", + "impid": "test-impression-id-2", + "price": 2 + }, + "type": "native" + }] + }, { + "bids": [{ + "bid": { + "id": "test-bid-id-3", + "impid": "test-impression-id-3", + "price": 3 + }, + "type": "native" + }] + }] +} diff --git a/adapters/applogy/applogytest/exemplary/simple-video.json b/adapters/applogy/applogytest/exemplary/simple-video.json new file mode 100644 index 00000000000..30237cccd10 --- /dev/null +++ b/adapters/applogy/applogytest/exemplary/simple-video.json @@ -0,0 +1,182 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [{ + "id": "test-impression-id-1", + "video": { + "w": 900, + "h": 250, + "mimes": [ + "video/mp4" + ] + }, + "ext": { + "bidder": { + "token": "test-token-1" + } + } + }, { + "id": "test-impression-id-2", + "video": { + "w": 900, + "h": 250, + "mimes": [ + "video/mp4" + ] + }, + "ext": { + "bidder": { + "token": "test-token-1" + } + } + }, { + "id": "test-impression-id-3", + "video": { + "w": 900, + "h": 250, + "mimes": [ + "video/mp4" + ] + }, + "ext": { + "bidder": { + "token": "test-token-2" + } + } + }] + }, + "httpCalls": [{ + "expectedRequest": { + "uri": "http://example.com/prebid/test-token-1", + "body": { + "id": "test-request-id", + "imp": [{ + "id": "test-impression-id-1", + "video": { + "w": 900, + "h": 250, + "mimes": [ + "video/mp4" + ] + }, + "ext": { + "bidder": { + "token": "test-token-1" + } + } + }] + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-response-id", + "seatbid": [{ + "bid": [{ + "id": "test-bid-id-1", + "impid": "test-impression-id-1", + "price": 1 + }] + }] + } + } + }, { + "expectedRequest": { + "uri": "http://example.com/prebid/test-token-1", + "body": { + "id": "test-request-id", + "imp": [{ + "id": "test-impression-id-2", + "video": { + "w": 900, + "h": 250, + "mimes": [ + "video/mp4" + ] + }, + "ext": { + "bidder": { + "token": "test-token-1" + } + } + }] + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-response-id-2", + "seatbid": [{ + "bid": [{ + "id": "test-bid-id-2", + "impid": "test-impression-id-2", + "price": 2 + }] + }] + } + } + }, { + "expectedRequest": { + "uri": "http://example.com/prebid/test-token-2", + "body": { + "id": "test-request-id", + "imp": [{ + "id": "test-impression-id-3", + "video": { + "w": 900, + "h": 250, + "mimes": [ + "video/mp4" + ] + }, + "ext": { + "bidder": { + "token": "test-token-2" + } + } + }] + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-response-id-3", + "seatbid": [{ + "bid": [{ + "id": "test-bid-id-3", + "impid": "test-impression-id-3", + "price": 3 + }] + }] + } + } + }], + "expectedBidResponses": [{ + "bids": [{ + "bid": { + "id": "test-bid-id-1", + "impid": "test-impression-id-1", + "price": 1 + }, + "type": "video" + }] + }, { + "bids": [{ + "bid": { + "id": "test-bid-id-2", + "impid": "test-impression-id-2", + "price": 2 + }, + "type": "video" + }] + }, { + "bids": [{ + "bid": { + "id": "test-bid-id-3", + "impid": "test-impression-id-3", + "price": 3 + }, + "type": "video" + }] + }] +} diff --git a/adapters/applogy/applogytest/supplemental/all-failed.json b/adapters/applogy/applogytest/supplemental/all-failed.json new file mode 100644 index 00000000000..7f0244afcfb --- /dev/null +++ b/adapters/applogy/applogytest/supplemental/all-failed.json @@ -0,0 +1,16 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [{ + "id": "test-impression-id-1", + "banner": { + "w": 300, + "h": 250 + } + }] + }, + "expectedMakeRequestsErrors": [{ + "value": "impression extensions required", + "comparison": "literal" + }] +} diff --git a/adapters/applogy/applogytest/supplemental/invalid-params.json b/adapters/applogy/applogytest/supplemental/invalid-params.json new file mode 100644 index 00000000000..6b5d5e3224d --- /dev/null +++ b/adapters/applogy/applogytest/supplemental/invalid-params.json @@ -0,0 +1,133 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [{ + "id": "test-impression-id-1", + "banner": {} + }, { + "id": "test-impression-id-2", + "banner": { + "w": 300, + "h": 250 + } + }, { + "id": "test-impression-id-3", + "banner": { + "w": 300, + "h": 250 + }, + "ext": {} + }, { + "id": "test-impression-id-4" + }, { + "id": "test-impression-id-5", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "token": "test-token-5" + } + } + }, { + "id": "test-impression-id-0", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "bidder": "invalid bidder" + } + }, { + "id": "test-impression-id-0", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "bidder": {} + } + }, { + "id": "test-impression-id-0", + "banner": { + "w": 300, + "h": 250 + }, + "ext": "invalid ext" + }] + }, + "httpCalls": [{ + "expectedRequest": { + "uri": "http://example.com/prebid/test-token-5", + "body": { + "id": "test-request-id", + "imp": [{ + "id": "test-impression-id-5", + "banner": { + "h": 250, + "w": 300 + }, + "ext": { + "bidder": { + "token": "test-token-5" + } + } + }] + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-response-id", + "seatbid": [{ + "bid": [{ + "id": "test-bid-id-5", + "impid": "test-impression-id-5", + "price": 5 + }, { + "id": "test-bid-id-6", + "impid": "test-impression-id-6", + "price": 6 + }] + }] + } + } + }], + "expectedBidResponses": [{ + "bids": [{ + "bid": { + "id": "test-bid-id-5", + "impid": "test-impression-id-5", + "price": 5 + }, + "type": "banner" + }] + }], + "expectedMakeRequestsErrors": [{ + "value": "banner size information missing", + "comparison": "literal" + }, { + "value": "impression extensions required", + "comparison": "literal" + }, { + "value": "bidder required", + "comparison": "literal" + }, { + "value": "Applogy only supports banner, video or native ads", + "comparison": "literal" + }, { + "value": "json: cannot unmarshal string into Go value of type openrtb_ext.ExtImpApplogy", + "comparison": "literal" + }, { + "value": "Applogy token required", + "comparison": "literal" + }, { + "value": "json: cannot unmarshal string into Go value of type adapters.ExtImpBidder", + "comparison": "literal" + }], + "expectedMakeBidsErrors": [{ + "value": "ignoring bid id=test-bid-id-6, request doesn't contain any valid impression with id=test-impression-id-6", + "comparison": "literal" + }] +} diff --git a/adapters/applogy/applogytest/supplemental/status-204.json b/adapters/applogy/applogytest/supplemental/status-204.json new file mode 100644 index 00000000000..c3516b184b5 --- /dev/null +++ b/adapters/applogy/applogytest/supplemental/status-204.json @@ -0,0 +1,41 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [{ + "id": "test-impression-id-1", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "token": "test-token-1" + } + } + }] + }, + "httpCalls": [{ + "expectedRequest": { + "uri": "http://example.com/prebid/test-token-1", + "body": { + "id": "test-request-id", + "imp": [{ + "id": "test-impression-id-1", + "banner": { + "h": 250, + "w": 300 + }, + "ext": { + "bidder": { + "token": "test-token-1" + } + } + }] + } + }, + "mockResponse": { + "status": 204, + "body": {} + } + }] +} diff --git a/adapters/applogy/applogytest/supplemental/status-400.json b/adapters/applogy/applogytest/supplemental/status-400.json new file mode 100644 index 00000000000..95e271bae8e --- /dev/null +++ b/adapters/applogy/applogytest/supplemental/status-400.json @@ -0,0 +1,45 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [{ + "id": "test-impression-id-1", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "token": "test-token-1" + } + } + }] + }, + "httpCalls": [{ + "expectedRequest": { + "uri": "http://example.com/prebid/test-token-1", + "body": { + "id": "test-request-id", + "imp": [{ + "id": "test-impression-id-1", + "banner": { + "h": 250, + "w": 300 + }, + "ext": { + "bidder": { + "token": "test-token-1" + } + } + }] + } + }, + "mockResponse": { + "status": 400, + "body": {} + } + }], + "expectedMakeBidsErrors": [{ + "value": "unexpected status code: 400", + "comparison": "literal" + }] +} diff --git a/adapters/applogy/applogytest/supplemental/status-502.json b/adapters/applogy/applogytest/supplemental/status-502.json new file mode 100644 index 00000000000..c0b1641653a --- /dev/null +++ b/adapters/applogy/applogytest/supplemental/status-502.json @@ -0,0 +1,45 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [{ + "id": "test-impression-id-1", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "token": "test-token-1" + } + } + }] + }, + "httpCalls": [{ + "expectedRequest": { + "uri": "http://example.com/prebid/test-token-1", + "body": { + "id": "test-request-id", + "imp": [{ + "id": "test-impression-id-1", + "banner": { + "h": 250, + "w": 300 + }, + "ext": { + "bidder": { + "token": "test-token-1" + } + } + }] + } + }, + "mockResponse": { + "status": 502, + "body": {} + } + }], + "expectedMakeBidsErrors": [{ + "value": "unexpected status code: 502", + "comparison": "literal" + }] +} diff --git a/adapters/appnexus/appnexusplatformtest/exemplary/simple-auction.json b/adapters/appnexus/appnexusplatformtest/exemplary/simple-auction.json index 8e4f52951b8..03c3f4c5880 100644 --- a/adapters/appnexus/appnexusplatformtest/exemplary/simple-auction.json +++ b/adapters/appnexus/appnexusplatformtest/exemplary/simple-auction.json @@ -14,7 +14,7 @@ }, "ext": { "bidder": { - "placement_id": 10433394 + "placement_id": 1 } } } @@ -46,7 +46,7 @@ }, "ext": { "appnexus": { - "placement_id": 10433394 + "placement_id": 1 } } } diff --git a/adapters/appnexus/appnexusplatformtest/video/simple-video.json b/adapters/appnexus/appnexusplatformtest/video/simple-video.json index 3c28b48a083..85960427d81 100644 --- a/adapters/appnexus/appnexusplatformtest/video/simple-video.json +++ b/adapters/appnexus/appnexusplatformtest/video/simple-video.json @@ -14,7 +14,7 @@ }, "ext": { "bidder": { - "placement_id": 10433394 + "placement_id": 1 } } } @@ -46,7 +46,7 @@ }, "ext": { "appnexus": { - "placement_id": 10433394 + "placement_id": 1 } } } diff --git a/adapters/appnexus/appnexustest/amp/simple-banner.json b/adapters/appnexus/appnexustest/amp/simple-banner.json index b5ea656c822..646359b4267 100644 --- a/adapters/appnexus/appnexustest/amp/simple-banner.json +++ b/adapters/appnexus/appnexustest/amp/simple-banner.json @@ -18,7 +18,7 @@ }, "ext": { "bidder": { - "placement_id": 10433394 + "placement_id": 1 } } } @@ -58,7 +58,7 @@ }, "ext": { "appnexus": { - "placement_id": 10433394 + "placement_id": 1 } } } diff --git a/adapters/appnexus/appnexustest/amp/simple-video.json b/adapters/appnexus/appnexustest/amp/simple-video.json index f44ed06605c..a6f96be34b8 100644 --- a/adapters/appnexus/appnexustest/amp/simple-video.json +++ b/adapters/appnexus/appnexustest/amp/simple-video.json @@ -14,7 +14,7 @@ }, "ext": { "bidder": { - "placement_id": 10433394 + "placement_id": 1 } } } @@ -48,7 +48,7 @@ }, "ext": { "appnexus": { - "placement_id": 10433394 + "placement_id": 1 } } } diff --git a/adapters/appnexus/appnexustest/exemplary/simple-banner.json b/adapters/appnexus/appnexustest/exemplary/simple-banner.json index 976f35b208a..e5bd311648f 100644 --- a/adapters/appnexus/appnexustest/exemplary/simple-banner.json +++ b/adapters/appnexus/appnexustest/exemplary/simple-banner.json @@ -18,7 +18,7 @@ }, "ext": { "bidder": { - "placement_id": 10433394 + "placement_id": 1 } } } @@ -56,7 +56,7 @@ }, "ext": { "appnexus": { - "placement_id": 10433394 + "placement_id": 1 } } } diff --git a/adapters/appnexus/appnexustest/exemplary/simple-video.json b/adapters/appnexus/appnexustest/exemplary/simple-video.json index 5afef01fa64..15755c7de37 100644 --- a/adapters/appnexus/appnexustest/exemplary/simple-video.json +++ b/adapters/appnexus/appnexustest/exemplary/simple-video.json @@ -14,7 +14,7 @@ }, "ext": { "bidder": { - "placement_id": 10433394 + "placement_id": 1 } } } @@ -46,7 +46,7 @@ }, "ext": { "appnexus": { - "placement_id": 10433394 + "placement_id": 1 } } } diff --git a/adapters/appnexus/appnexustest/exemplary/video-invalid-category.json b/adapters/appnexus/appnexustest/exemplary/video-invalid-category.json index 283f13cf111..d3686af00a9 100644 --- a/adapters/appnexus/appnexustest/exemplary/video-invalid-category.json +++ b/adapters/appnexus/appnexustest/exemplary/video-invalid-category.json @@ -14,7 +14,7 @@ }, "ext": { "bidder": { - "placement_id": 10433394 + "placement_id": 1 } } } @@ -46,7 +46,7 @@ }, "ext": { "appnexus": { - "placement_id": 10433394 + "placement_id": 1 } } } diff --git a/adapters/appnexus/appnexustest/params/race/banner.json b/adapters/appnexus/appnexustest/params/race/banner.json index 2e2b39e9429..a37e0036357 100644 --- a/adapters/appnexus/appnexustest/params/race/banner.json +++ b/adapters/appnexus/appnexustest/params/race/banner.json @@ -1,5 +1,5 @@ { - "placement_id": 10433394, + "placement_id": 1, "reserve": 20, "position": "below", "traffic_source_code": "trafficSource", diff --git a/adapters/appnexus/appnexustest/params/race/video.json b/adapters/appnexus/appnexustest/params/race/video.json index 2e2b39e9429..a37e0036357 100644 --- a/adapters/appnexus/appnexustest/params/race/video.json +++ b/adapters/appnexus/appnexustest/params/race/video.json @@ -1,5 +1,5 @@ { - "placement_id": 10433394, + "placement_id": 1, "reserve": 20, "position": "below", "traffic_source_code": "trafficSource", diff --git a/adapters/appnexus/appnexustest/supplemental/displaymanager-test.json b/adapters/appnexus/appnexustest/supplemental/displaymanager-test.json index a1602ff9a74..d5c981c6945 100644 --- a/adapters/appnexus/appnexustest/supplemental/displaymanager-test.json +++ b/adapters/appnexus/appnexustest/supplemental/displaymanager-test.json @@ -26,7 +26,7 @@ }, "ext": { "bidder": { - "placement_id": 10433394 + "placement_id": 1 } } } @@ -73,7 +73,7 @@ "displaymanagerver": "prebid-mobile-1.0.0", "ext": { "appnexus": { - "placement_id": 10433394 + "placement_id": 1 } } } diff --git a/adapters/appnexus/appnexustest/supplemental/explicit-dimensions.json b/adapters/appnexus/appnexustest/supplemental/explicit-dimensions.json index 11b5d887187..06e7724a23b 100644 --- a/adapters/appnexus/appnexustest/supplemental/explicit-dimensions.json +++ b/adapters/appnexus/appnexustest/supplemental/explicit-dimensions.json @@ -16,7 +16,7 @@ }, "ext": { "bidder": { - "placementId": 10433394 + "placementId": 1 } } } @@ -49,7 +49,7 @@ }, "ext": { "appnexus": { - "placement_id": 10433394 + "placement_id": 1 } } } diff --git a/adapters/appnexus/appnexustest/supplemental/multi-bid.json b/adapters/appnexus/appnexustest/supplemental/multi-bid.json index 1e3089b1e71..7234551ea3f 100644 --- a/adapters/appnexus/appnexustest/supplemental/multi-bid.json +++ b/adapters/appnexus/appnexustest/supplemental/multi-bid.json @@ -18,7 +18,7 @@ }, "ext": { "bidder": { - "placement_id": 10433394 + "placement_id": 1 } } } @@ -56,7 +56,7 @@ }, "ext": { "appnexus": { - "placement_id": 10433394 + "placement_id": 1 } } } diff --git a/adapters/audienceNetwork/audienceNetworktest/supplemental/banner-format-only.json b/adapters/audienceNetwork/audienceNetworktest/supplemental/banner-format-only.json new file mode 100644 index 00000000000..52b7655593a --- /dev/null +++ b/adapters/audienceNetwork/audienceNetworktest/supplemental/banner-format-only.json @@ -0,0 +1,140 @@ +{ + "mockBidRequest": { + "id": "test-req-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 640, + "h": 480 + }, + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "publisherid": "123", + "placementid": "456" + } + } + } + ], + "site": { + "domain": "prebid.org", + "page": "prebid.org" + }, + "device": { + "ip": "152.193.6.74" + }, + "user": { + "id": "db089de9-a62e-4861-a881-0ff15e052516", + "buyeruid": "v4_bidder_token" + }, + "tmax": 500 + }, + "httpcalls": [ + { + "expectedRequest": { + "uri": "https://an.facebook.com/placementbid.ortb", + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json;charset=utf-8" + ], + "X-Fb-Pool-Routing-Token": [ + "v4_bidder_token" + ] + }, + "body": { + "id": "test-req-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "w": -1, + "h": 250 + }, + "tagid": "123_456" + } + ], + "ext": { + "appnexus": { + "hb_source": 5 + }, + "prebid": {} + }, + "site": { + "domain": "prebid.org", + "page": "prebid.org", + "publisher": { + "id": "123" + } + }, + "device": { + "ip": "152.193.6.74" + }, + "user": { + "id": "db089de9-a62e-4861-a881-0ff15e052516", + "buyeruid": "v4_bidder_token" + }, + "tmax": 500, + "ext": { + "authentication_id": "b2f9edfd707106adb6b692520081ad7e2a345444af1a895310228297a1b6247e", + "platformid": "test-platform-id" + } + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-req-id", + "seatbid": [ + { + "bid": [ + { + "id": "987", + "impid": "test-imp-id", + "price": 1.000000, + "adm": "{\"type\":\"ID\",\"bid_id\":\"987\",\"placement_id\":\"123_456\",\"resolved_placement_id\":\"123_456\",\"sdk_version\":\"5.5.0\",\"device_id\":\"abc\",\"template\":1,\"payload\":null,\"bid_time_token\":\"v4_bidder_token=\"}", + "nurl": "https://www.facebook.com/audiencenetwork/nurl/?partner=test-platform-id&app=def&placement=456&auction=123&impression=123&request=123478&bid=987&ortb_loss_code=0&clearing_price=${AUCTION_PRICE}&app_version=iOS-1.0", + "lurl": "https://www.facebook.com/audiencenetwork/nurl/?partner=test-platform-id&app=def&placement=456&auction=123&impression=123&request=123478&bid=987&ortb_loss_code=${AUCTION_LOSS}&clearing_price=${AUCTION_PRICE}&app_version=iOS-1.0", + "burl": "https://www.facebook.com/audiencenetwork/burl/?partner=test-platform-id&app=def&placement=456&auction=123&impression=123&request=123478&bid=987&clearing_price=${AUCTION_PRICE}" + } + ] + } + ], + "bidid": "654", + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "987", + "impid": "test-imp-id", + "price": 1, + "adm": "{\"type\":\"ID\",\"bid_id\":\"987\",\"placement_id\":\"123_456\",\"resolved_placement_id\":\"123_456\",\"sdk_version\":\"5.5.0\",\"device_id\":\"abc\",\"template\":1,\"payload\":null,\"bid_time_token\":\"v4_bidder_token=\"}", + "adid": "987", + "crid": "987", + "nurl": "https://www.facebook.com/audiencenetwork/nurl/?partner=test-platform-id&app=def&placement=456&auction=123&impression=123&request=123478&bid=987&ortb_loss_code=0&clearing_price=${AUCTION_PRICE}&app_version=iOS-1.0", + "lurl": "https://www.facebook.com/audiencenetwork/nurl/?partner=test-platform-id&app=def&placement=456&auction=123&impression=123&request=123478&bid=987&ortb_loss_code=${AUCTION_LOSS}&clearing_price=${AUCTION_PRICE}&app_version=iOS-1.0", + "burl": "https://www.facebook.com/audiencenetwork/burl/?partner=test-platform-id&app=def&placement=456&auction=123&impression=123&request=123478&bid=987&clearing_price=${AUCTION_PRICE}" + }, + "type": "banner" + } + ] + } + ] +} diff --git a/adapters/audienceNetwork/facebook.go b/adapters/audienceNetwork/facebook.go index 1500f314f88..3ece7bb99e4 100644 --- a/adapters/audienceNetwork/facebook.go +++ b/adapters/audienceNetwork/facebook.go @@ -184,8 +184,17 @@ func (this *FacebookAdapter) modifyImp(out *openrtb.Imp) error { } if out.Banner.H == nil { - return &errortypes.BadInput{ - Message: fmt.Sprintf("imp #%s: banner height required", out.ID), + for _, f := range out.Banner.Format { + if _, ok := supportedBannerHeights[f.H]; ok { + h := f.H + out.Banner.H = &h + break + } + } + if out.Banner.H == nil { + return &errortypes.BadInput{ + Message: fmt.Sprintf("imp #%s: banner height required", out.ID), + } } } @@ -438,3 +447,20 @@ func NewFacebookBidder(client *http.Client, platformID string, appSecret string) appSecret: appSecret, } } + +func (fa *FacebookAdapter) MakeTimeoutNotification(req *adapters.RequestData) (*adapters.RequestData, []error) { + // Note, facebook creates one request per imp, so all these requests will only have one imp in them + auction_id, err := jsonparser.GetString(req.Body, "imp", "[0]", "id") + if err != nil { + return &adapters.RequestData{}, []error{err} + } + + uri := fmt.Sprintf("https://www.facebook.com/audiencenetwork/nurl/?partner=%s&app=%s&auction=%s&ortb_loss_code=2", fa.platformID, fa.platformID, auction_id) + timeoutReq := adapters.RequestData{ + Method: "GET", + Uri: uri, + Body: nil, + Headers: http.Header{}, + } + return &timeoutReq, nil +} diff --git a/adapters/audienceNetwork/facebook_test.go b/adapters/audienceNetwork/facebook_test.go index 2ce0ef3ba64..1edaabd45d7 100644 --- a/adapters/audienceNetwork/facebook_test.go +++ b/adapters/audienceNetwork/facebook_test.go @@ -4,7 +4,9 @@ import ( "testing" "time" + "github.com/prebid/prebid-server/adapters" "github.com/prebid/prebid-server/adapters/adapterstest" + "github.com/stretchr/testify/assert" ) type tagInfo struct { @@ -40,3 +42,38 @@ type FacebookExt struct { func TestJsonSamples(t *testing.T) { adapterstest.RunJSONBidderTest(t, "audienceNetworktest", NewFacebookBidder(nil, "test-platform-id", "test-app-secret")) } + +func TestMakeTimeoutNotice(t *testing.T) { + req := adapters.RequestData{ + Body: []byte(`{"imp":[{"id":"1234"}]}}`), + } + fba := NewFacebookBidder(nil, "test-platform-id", "test-app-secret") + + tb, ok := fba.(adapters.TimeoutBidder) + if !ok { + t.Error("Facebook adapter is not a TimeoutAdapter") + } + + toReq, err := tb.MakeTimeoutNotification(&req) + assert.Nil(t, err, "Facebook MakeTimeoutNotification() return an error %v", err) + expectedUri := "https://www.facebook.com/audiencenetwork/nurl/?partner=test-platform-id&app=test-platform-id&auction=1234&ortb_loss_code=2" + assert.Equal(t, expectedUri, toReq.Uri, "Facebook timeout notification not returning the expected URI.") + +} + +func TestMakeTimeoutNoticeBadRequest(t *testing.T) { + req := adapters.RequestData{ + Body: []byte(`{"imp":[{{"id":"1234"}}`), + } + fba := NewFacebookBidder(nil, "test-platform-id", "test-app-secret") + + tb, ok := fba.(adapters.TimeoutBidder) + if !ok { + t.Error("Facebook adapter is not a TimeoutAdapter") + } + + toReq, err := tb.MakeTimeoutNotification(&req) + assert.Empty(t, toReq.Uri, "Facebook MakeTimeoutNotification() did not return nil", err) + assert.NotNil(t, err, "Facebook MakeTimeoutNotification() did not return an error") + +} diff --git a/adapters/beachfront/usersync_test.go b/adapters/beachfront/usersync_test.go index 0b71e0f92f8..f0c4b3817d1 100644 --- a/adapters/beachfront/usersync_test.go +++ b/adapters/beachfront/usersync_test.go @@ -5,20 +5,30 @@ import ( "text/template" "github.com/prebid/prebid-server/privacy" + "github.com/prebid/prebid-server/privacy/ccpa" + "github.com/prebid/prebid-server/privacy/gdpr" "github.com/stretchr/testify/assert" ) func TestBeachfrontSyncer(t *testing.T) { - syncURL := "localhost" + syncURL := "https://sync.bfmio.com/sync_s2s?gdpr={{.GDPR}}&us_privacy={{.USPrivacy}}&url=https%3A%2F%2Flocalhost%3A8888%2Fsetuid%3Fbidder%3Dbeachfront%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%5Bio_cid%5D" syncURLTemplate := template.Must( template.New("sync-template").Parse(syncURL), ) syncer := NewBeachfrontSyncer(syncURLTemplate) - syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{}) + syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{ + GDPR: gdpr.Policy{ + Signal: "A", + Consent: "B", + }, + CCPA: ccpa.Policy{ + Value: "C", + }, + }) assert.NoError(t, err) - assert.Equal(t, "localhost", syncInfo.URL) + assert.Equal(t, "https://sync.bfmio.com/sync_s2s?gdpr=A&us_privacy=C&url=https%3A%2F%2Flocalhost%3A8888%2Fsetuid%3Fbidder%3Dbeachfront%26gdpr%3DA%26gdpr_consent%3DB%26uid%3D%5Bio_cid%5D", syncInfo.URL) assert.Equal(t, "iframe", syncInfo.Type) assert.EqualValues(t, 0, syncer.GDPRVendorID()) assert.Equal(t, false, syncInfo.SupportCORS) diff --git a/adapters/bidder.go b/adapters/bidder.go index 9d3ffb75414..baec4135b6a 100644 --- a/adapters/bidder.go +++ b/adapters/bidder.go @@ -39,6 +39,19 @@ type Bidder interface { MakeBids(internalRequest *openrtb.BidRequest, externalRequest *RequestData, response *ResponseData) (*BidderResponse, []error) } +// TimeoutBidder is used to identify bidders that support timeout notifications. +type TimeoutBidder interface { + Bidder + + // MakeTimeoutNotice functions much the same as MakeRequests, except it is fed the bidder request that timed out, + // and expects that only one notification "request" will be generated. A use case for multiple timeout notifications + // has not been anticipated. + // + // Do note that if MakeRequests returns multiple requests, and more than one of these times out, MakeTimeoutNotice will be called + // once for each timed out request. + MakeTimeoutNotification(req *RequestData) (*RequestData, []error) +} + type MisconfiguredBidder struct { Name string Error error diff --git a/adapters/brightroll/usersync_test.go b/adapters/brightroll/usersync_test.go index 08104c048ac..a5d47e35e56 100644 --- a/adapters/brightroll/usersync_test.go +++ b/adapters/brightroll/usersync_test.go @@ -9,7 +9,7 @@ import ( ) func TestBrightrollSyncer(t *testing.T) { - syncURL := "http://test-bh.ybp.yahoo.com/sync/appnexuspbs?gdpr={{.GDPR}}&euconsent={{.GDPRConsent}}&url=localhost%2Fsetuid%3Fbidder%3Dbrightroll%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7BUID%7D" + syncURL := "http://test-bh.ybp.yahoo.com/sync/appnexuspbs?gdpr={{.GDPR}}&euconsent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&url=localhost%2Fsetuid%3Fbidder%3Dbrightroll%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7BUID%7D" syncURLTemplate := template.Must( template.New("sync-template").Parse(syncURL), ) @@ -18,7 +18,7 @@ func TestBrightrollSyncer(t *testing.T) { syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{}) assert.NoError(t, err) - assert.Equal(t, "http://test-bh.ybp.yahoo.com/sync/appnexuspbs?gdpr=&euconsent=&url=localhost%2Fsetuid%3Fbidder%3Dbrightroll%26gdpr%3D%26gdpr_consent%3D%26uid%3D%24%7BUID%7D", syncInfo.URL) + assert.Equal(t, "http://test-bh.ybp.yahoo.com/sync/appnexuspbs?gdpr=&euconsent=&us_privacy=&url=localhost%2Fsetuid%3Fbidder%3Dbrightroll%26gdpr%3D%26gdpr_consent%3D%26uid%3D%24%7BUID%7D", syncInfo.URL) assert.Equal(t, "redirect", syncInfo.Type) assert.EqualValues(t, 25, syncer.GDPRVendorID()) assert.Equal(t, false, syncInfo.SupportCORS) diff --git a/adapters/consumable/usersync_test.go b/adapters/consumable/usersync_test.go index 7def6be0a48..eb97edf2cae 100644 --- a/adapters/consumable/usersync_test.go +++ b/adapters/consumable/usersync_test.go @@ -5,12 +5,13 @@ import ( "text/template" "github.com/prebid/prebid-server/privacy" + "github.com/prebid/prebid-server/privacy/ccpa" "github.com/prebid/prebid-server/privacy/gdpr" "github.com/stretchr/testify/assert" ) func TestConsumableSyncer(t *testing.T) { - syncURL := "//e.serverbid.com/udb/9969/match?redir=http%3A%2F%2Flocalhost%3A8000%2Fsetuid%3Fbidder%3Dconsumable%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D" + syncURL := "//e.serverbid.com/udb/9969/match?gdpr={{.GDPR}}&euconsent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir=http%3A%2F%2Flocalhost%3A8000%2Fsetuid%3Fbidder%3Dconsumable%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D" syncURLTemplate := template.Must( template.New("sync-template").Parse(syncURL), ) @@ -18,12 +19,16 @@ func TestConsumableSyncer(t *testing.T) { syncer := NewConsumableSyncer(syncURLTemplate) u, err := syncer.GetUsersyncInfo(privacy.Policies{ GDPR: gdpr.Policy{ - Signal: "0", + Signal: "A", + Consent: "B", + }, + CCPA: ccpa.Policy{ + Value: "C", }, }) assert.NoError(t, err) - assert.Equal(t, "//e.serverbid.com/udb/9969/match?redir=http%3A%2F%2Flocalhost%3A8000%2Fsetuid%3Fbidder%3Dconsumable%26gdpr%3D0%26gdpr_consent%3D%26uid%3D", u.URL) + assert.Equal(t, "//e.serverbid.com/udb/9969/match?gdpr=A&euconsent=B&us_privacy=C&redir=http%3A%2F%2Flocalhost%3A8000%2Fsetuid%3Fbidder%3Dconsumable%26gdpr%3DA%26gdpr_consent%3DB%26uid%3D", u.URL) assert.Equal(t, "redirect", u.Type) assert.Equal(t, uint16(65535), syncer.GDPRVendorID()) assert.Equal(t, false, u.SupportCORS) diff --git a/adapters/cpmstar/cpmstar.go b/adapters/cpmstar/cpmstar.go new file mode 100644 index 00000000000..ef6abe70cb7 --- /dev/null +++ b/adapters/cpmstar/cpmstar.go @@ -0,0 +1,161 @@ +package cpmstar + +import ( + "encoding/json" + "fmt" + "net/http" + + "github.com/mxmCherry/openrtb" + "github.com/prebid/prebid-server/adapters" + "github.com/prebid/prebid-server/errortypes" + "github.com/prebid/prebid-server/openrtb_ext" +) + +type Adapter struct { + endpoint string +} + +func (a *Adapter) MakeRequests(request *openrtb.BidRequest, unused *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { + var errs []error + var adapterRequests []*adapters.RequestData + + if err := preprocess(request); err != nil { + errs = append(errs, err) + return nil, errs + } + + adapterReq, err := a.makeRequest(request) + if err != nil { + errs = append(errs, err) + return nil, errs + } + + adapterRequests = append(adapterRequests, adapterReq) + + return adapterRequests, errs +} + +func (a *Adapter) makeRequest(request *openrtb.BidRequest) (*adapters.RequestData, error) { + var err error + + jsonBody, err := json.Marshal(request) + if err != nil { + return nil, err + } + + headers := http.Header{} + headers.Add("Content-Type", "application/json;charset=utf-8") + + return &adapters.RequestData{ + Method: "POST", + Uri: a.endpoint, + Body: jsonBody, + Headers: headers, + }, nil +} + +func preprocess(request *openrtb.BidRequest) error { + if len(request.Imp) == 0 { + return &errortypes.BadInput{ + Message: "No Imps in Bid Request", + } + } + for i := 0; i < len(request.Imp); i++ { + var imp = &request.Imp[i] + var bidderExt adapters.ExtImpBidder + + if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil { + return &errortypes.BadInput{ + Message: err.Error(), + } + } + + if err := validateImp(imp); err != nil { + return err + } + + var extImp openrtb_ext.ExtImpCpmstar + if err := json.Unmarshal(bidderExt.Bidder, &extImp); err != nil { + return &errortypes.BadInput{ + Message: err.Error(), + } + } + + imp.Ext = bidderExt.Bidder + } + + return nil +} + +func validateImp(imp *openrtb.Imp) error { + if imp.Banner == nil && imp.Video == nil { + return &errortypes.BadInput{ + Message: "Only Banner and Video bid-types are supported at this time", + } + } + return nil +} + +// MakeBids based on cpmstar server response +func (a *Adapter) MakeBids(bidRequest *openrtb.BidRequest, unused *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) { + if responseData.StatusCode == http.StatusNoContent { + return nil, nil + } + + if responseData.StatusCode != http.StatusOK { + return nil, []error{&errortypes.BadServerResponse{ + Message: fmt.Sprintf("Unexpected HTTP status code: %d. Run with request.debug = 1 for more info", responseData.StatusCode), + }} + } + + var bidResponse openrtb.BidResponse + + if err := json.Unmarshal(responseData.Body, &bidResponse); err != nil { + return nil, []error{&errortypes.BadServerResponse{ + Message: err.Error(), + }} + } + + if len(bidResponse.SeatBid) == 0 { + return nil, nil + } + + rv := adapters.NewBidderResponseWithBidsCapacity(len(bidResponse.SeatBid[0].Bid)) + var errors []error + + for _, seatbid := range bidResponse.SeatBid { + for _, bid := range seatbid.Bid { + foundMatchingBid := false + bidType := openrtb_ext.BidTypeBanner + for _, imp := range bidRequest.Imp { + if imp.ID == bid.ImpID { + foundMatchingBid = true + if imp.Banner != nil { + bidType = openrtb_ext.BidTypeBanner + } else if imp.Video != nil { + bidType = openrtb_ext.BidTypeVideo + } + break + } + } + + if foundMatchingBid { + rv.Bids = append(rv.Bids, &adapters.TypedBid{ + Bid: &bid, + BidType: bidType, + }) + } else { + errors = append(errors, &errortypes.BadServerResponse{ + Message: fmt.Sprintf("bid id='%s' could not find valid impid='%s'", bid.ID, bid.ImpID), + }) + } + } + } + return rv, errors +} + +func NewCpmstarBidder(endpoint string) *Adapter { + return &Adapter{ + endpoint: endpoint, + } +} diff --git a/adapters/cpmstar/cpmstar_test.go b/adapters/cpmstar/cpmstar_test.go new file mode 100644 index 00000000000..0a7f43f5ee7 --- /dev/null +++ b/adapters/cpmstar/cpmstar_test.go @@ -0,0 +1,11 @@ +package cpmstar + +import ( + "testing" + + "github.com/prebid/prebid-server/adapters/adapterstest" +) + +func TestJsonSamples(t *testing.T) { + adapterstest.RunJSONBidderTest(t, "cpmstartest", NewCpmstarBidder("//host")) +} diff --git a/adapters/cpmstar/cpmstartest/exemplary/banner-and-video.json b/adapters/cpmstar/cpmstartest/exemplary/banner-and-video.json new file mode 100644 index 00000000000..d4dcb4b8677 --- /dev/null +++ b/adapters/cpmstar/cpmstartest/exemplary/banner-and-video.json @@ -0,0 +1,154 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-banner-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "placementId": 154, + "subpoolId": 123 + } + } + }, + { + "id": "test-video-imp-id", + "video": { + "mimes": [ + "video/mp4" + ], + "protocols": [ + 2, + 5 + ], + "w": 640, + "h": 480 + }, + "ext": { + "bidder": { + "placementId": 154, + "subpoolId": 654 + } + } + } + ], + "site": { + "id": "fake-site-id" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "//host", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-banner-imp-id", + "banner": { + "format": [ + { + "h": 250, + "w": 300 + } + ] + }, + "ext": { + "placementId": 154, + "subpoolId": 123 + } + }, + { + "id": "test-video-imp-id", + "video": { + "h": 480, + "mimes": [ + "video/mp4" + ], + "protocols": [ + 2, + 5 + ], + "w": 640 + }, + "ext": { + "placementId": 154, + "subpoolId": 654 + } + } + ], + "site": { + "id": "fake-site-id" + } + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "cpmstar", + "bid": [ + { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-video-imp-id", + "price": 0.5, + "adm": "some-test-ad", + "crid": "crid_10", + "h": 250, + "w": 300 + } + ] + } + ], + "cur": "USD" + } + } + } + ], + "expectedBids": [ + { + "bid": { + "id": "7706636740145184841", + "impid": "test-imp-id", + "price": 0.5, + "adm": "some-test-ad", + "adid": "29681110", + "adomain": [ + "sample.com" + ], + "cid": "958", + "crid": "29681110", + "w": 1024, + "h": 576 + }, + "type": "banner" + }, + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-video-id", + "price": 0.5, + "adm": "some-test-ad", + "adid": "29484110", + "adomain": [ + "sample.com" + ], + "cid": "958", + "crid": "29484110", + "w": 1024, + "h": 576 + }, + "type": "video" + } + ] +} \ No newline at end of file diff --git a/adapters/cpmstar/cpmstartest/exemplary/banner.json b/adapters/cpmstar/cpmstartest/exemplary/banner.json new file mode 100644 index 00000000000..0bbe3060a63 --- /dev/null +++ b/adapters/cpmstar/cpmstartest/exemplary/banner.json @@ -0,0 +1,100 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-banner-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "placementId": 154, + "subpoolId": 123 + } + } + } + ], + "site": { + "id": "fake-site-id" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "//host", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-banner-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "placementId": 154, + "subpoolId": 123 + } + } + ], + "site": { + "id": "fake-site-id" + } + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "cpmstar", + "bid": [ + { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-banner-imp-id", + "price": 0.500000, + "adm": "some-test-ad", + "crid": "crid_10", + "h": 250, + "w": 300 + } + ] + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-banner-imp-id", + "price": 0.5, + "adm": "some-test-ad", + "crid": "crid_10", + "w": 300, + "h": 250 + }, + "type": "banner" + } + ] + } + ] +} + \ No newline at end of file diff --git a/adapters/cpmstar/cpmstartest/exemplary/video.json b/adapters/cpmstar/cpmstartest/exemplary/video.json new file mode 100644 index 00000000000..a0213cbdac1 --- /dev/null +++ b/adapters/cpmstar/cpmstartest/exemplary/video.json @@ -0,0 +1,55 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-video-imp-id", + "video": { + "w": 900, + "h": 250, + "mimes": [ + "video/x-flv", + "video/mp4" + ] + }, + "ext": { + "bidder": { + "placementId": 154, + "subpoolId": 123 + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "//host", + "body": { + "id": "test-request-id", + "imp": [ + { + "id":"test-video-imp-id", + "video": { + "w": 900, + "h": 250, + "mimes": [ + "video/x-flv", + "video/mp4" + ] + }, + "ext": { + "placementId": 154, + "subpoolId": 123 + } + } + ] + } + }, + "mockResponse": { + "status": 204 + } + } + ] +} diff --git a/adapters/cpmstar/cpmstartest/supplemental/audio.json b/adapters/cpmstar/cpmstartest/supplemental/audio.json new file mode 100644 index 00000000000..18ff171c7f5 --- /dev/null +++ b/adapters/cpmstar/cpmstartest/supplemental/audio.json @@ -0,0 +1,25 @@ +{ + "mockBidRequest": { + "id": "unsupported-audio-request", + "imp": [ + { + "id": "unsupported-audio-imp", + "audio": { + "mimes": ["video/mp4"] + }, + "ext": { + "bidder": { + "placementId": 154 + } + } + } + ] + }, + + "expectedMakeRequestsErrors": [ + { + "value": "Only Banner and Video bid-types are supported at this time", + "comparison": "literal" + } + ] +} diff --git a/adapters/cpmstar/cpmstartest/supplemental/explicit-dimensions.json b/adapters/cpmstar/cpmstartest/supplemental/explicit-dimensions.json new file mode 100644 index 00000000000..b8aad87514d --- /dev/null +++ b/adapters/cpmstar/cpmstartest/supplemental/explicit-dimensions.json @@ -0,0 +1,58 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ], + "w": 100, + "h": 400 + }, + "ext": { + "bidder": { + "placementId": 154, + "subpoolId": 123 + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "//host", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ], + "w": 100, + "h": 400 + }, + "ext": { + "placementId": 154, + "subpoolId": 123 + } + } + ] + } + }, + "mockResponse": { + "status": 204 + } + } + ] +} \ No newline at end of file diff --git a/adapters/cpmstar/cpmstartest/supplemental/invalid-response-no-bids.json b/adapters/cpmstar/cpmstartest/supplemental/invalid-response-no-bids.json new file mode 100644 index 00000000000..a3cb9114caa --- /dev/null +++ b/adapters/cpmstar/cpmstartest/supplemental/invalid-response-no-bids.json @@ -0,0 +1,50 @@ +{ + "mockBidRequest": { + "id": "some_test_auction", + "imp": [ + { + "id": "some_test_ad", + "banner": { + "w": 90, + "h": 728 + }, + "ext": { + "bidder": { + "placementId": 154 + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "//host", + "body": { + "id": "some_test_auction", + "imp": [ + { + "id": "some_test_ad", + "banner": { + "h": 728, + "w": 90 + }, + "ext": { + "placementId": 154 + } + } + ] + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "some_test_auction", + "seatbid": [ + ], + "cur": "USD" + } + } + } + ] +} \ No newline at end of file diff --git a/adapters/cpmstar/cpmstartest/supplemental/invalid-response-unmarshall-error.json b/adapters/cpmstar/cpmstartest/supplemental/invalid-response-unmarshall-error.json new file mode 100644 index 00000000000..e20acefe2c3 --- /dev/null +++ b/adapters/cpmstar/cpmstartest/supplemental/invalid-response-unmarshall-error.json @@ -0,0 +1,66 @@ +{ + "mockBidRequest": { + "id": "some_test_auction", + "imp": [ + { + "id": "some_test_ad", + "banner": { + "w": 90, + "h": 728 + }, + "ext": { + "bidder": { + "placementId": 154 + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "//host", + "body": { + "id": "some_test_auction", + "imp": [ + { + "id": "some_test_ad", + "banner": { + "h": 728, + "w": 90 + }, + "ext": { + "placementId": 154 + } + } + ] + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "some_test_auction", + "seatbid": [ + { + "bid": [ + { + "id": "uuid", + "impid": "some_test_ad", + "w": "728", + "h": 90 + } + ] + } + ], + "cur": "USD" + } + } + } + ], + "expectedMakeBidsErrors": [ + { + "value": "json: cannot unmarshal string into Go struct field Bid(\\.seatbid\\.bid)?\\.w of type uint64", + "comparison": "regex" + } + ] +} \ No newline at end of file diff --git a/adapters/cpmstar/cpmstartest/supplemental/native.json b/adapters/cpmstar/cpmstartest/supplemental/native.json new file mode 100644 index 00000000000..a02db78db0f --- /dev/null +++ b/adapters/cpmstar/cpmstartest/supplemental/native.json @@ -0,0 +1,25 @@ +{ + "mockBidRequest": { + "id": "unsupported-native-request", + "imp": [ + { + "id": "unsupported-native-imp", + "native": { + "ver": "1.1" + }, + "ext": { + "bidder": { + "placementId": 154 + } + } + } + ] + }, + + "expectedMakeRequestsErrors": [ + { + "value": "Only Banner and Video bid-types are supported at this time", + "comparison": "literal" + } + ] +} diff --git a/adapters/cpmstar/cpmstartest/supplemental/no-imps-in-request.json b/adapters/cpmstar/cpmstartest/supplemental/no-imps-in-request.json new file mode 100644 index 00000000000..274a34227cf --- /dev/null +++ b/adapters/cpmstar/cpmstartest/supplemental/no-imps-in-request.json @@ -0,0 +1,18 @@ +{ + "mockBidRequest": { + "id": "some_test_auction", + "imp": [ + ], + "site": { + "domain": "www.publisher.com", + "page": "http://www.publisher.com/awesome/site?with=some¶meters=here" + } + }, + + "expectedMakeRequestsErrors": [ + { + "value": "No Imps in Bid Request", + "comparison": "literal" + } + ] +} \ No newline at end of file diff --git a/adapters/cpmstar/cpmstartest/supplemental/server-error-code.json b/adapters/cpmstar/cpmstartest/supplemental/server-error-code.json new file mode 100644 index 00000000000..21e697d13f1 --- /dev/null +++ b/adapters/cpmstar/cpmstartest/supplemental/server-error-code.json @@ -0,0 +1,53 @@ +{ + "mockBidRequest": { + "id": "some_test_auction", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "w": 600, + "h": 300 + }, + "ext": { + "bidder": { + "placementId": 154 + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "//host", + "body": { + "id": "some_test_auction", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "w": 600, + "h": 300 + }, + "ext": { + "placementId": 154 + } + } + ] + } + }, + "mockResponse": { + "status": 500, + "body": {} + } + } + ], + + "expectedMakeBidsErrors": [ + { + "value": "Unexpected HTTP status code: 500. Run with request.debug = 1 for more info", + "comparison": "literal" + } + ] + } diff --git a/adapters/cpmstar/cpmstartest/supplemental/server-no-content.json b/adapters/cpmstar/cpmstartest/supplemental/server-no-content.json new file mode 100644 index 00000000000..e56db95f8e8 --- /dev/null +++ b/adapters/cpmstar/cpmstartest/supplemental/server-no-content.json @@ -0,0 +1,45 @@ +{ + "mockBidRequest": { + "id": "some_test_auction", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "placementId": 154 + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "//host", + "body": { + "id": "some_test_auction", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "placementId": 154 + } + } + ] + } + }, + "mockResponse": { + "status": 204 + } + } + ] + } diff --git a/adapters/cpmstar/cpmstartest/supplemental/wrong-impression-ext.json b/adapters/cpmstar/cpmstartest/supplemental/wrong-impression-ext.json new file mode 100644 index 00000000000..1e8de0acc66 --- /dev/null +++ b/adapters/cpmstar/cpmstartest/supplemental/wrong-impression-ext.json @@ -0,0 +1,26 @@ +{ + "mockBidRequest": { + "id": "rqid", + "imp": [ + { + "id": "impid", + "video": { + "w": 100, + "h": 200 + }, + "ext": { + "bidder": { + "placementId": "BOGUS" + } + } + } + ] + }, + + "expectedMakeRequestsErrors": [ + { + "value": "json: cannot unmarshal string into Go struct field ExtImpCpmstar.placementId of type int", + "comparison": "literal" + } + ] +} diff --git a/adapters/cpmstar/cpmstartest/supplemental/wrong-impression-mapping.json b/adapters/cpmstar/cpmstartest/supplemental/wrong-impression-mapping.json new file mode 100644 index 00000000000..6ab02db0ca7 --- /dev/null +++ b/adapters/cpmstar/cpmstartest/supplemental/wrong-impression-mapping.json @@ -0,0 +1,77 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "w": 900, + "h": 250, + "mimes": [ + "video/x-flv", + "video/mp4" + ] + }, + "ext": { + "bidder": { + "poolid": 154, + "subpoolid": 123 + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "//host", + "body": { + "id": "test-request-id", + "imp": [ + { + "id":"test-imp-id", + "video": { + "w": 900, + "h": 250, + "mimes": [ + "video/x-flv", + "video/mp4" + ] + }, + "ext": { + "poolid": 154, + "subpoolid": 123 + } + } + ] + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "test-bid-id", + "impid": "BOGUS-IMPID", + "price": 3.5, + "w": 900, + "h": 250 + } + ] + } + ] + } + } + } + ], + "expectedMakeBidsErrors": [ + { + "value": "bid id='test-bid-id' could not find valid impid='BOGUS-IMPID'", + "comparison": "regex" + } +] +} \ No newline at end of file diff --git a/adapters/cpmstar/params_test.go b/adapters/cpmstar/params_test.go new file mode 100644 index 00000000000..cee471a8322 --- /dev/null +++ b/adapters/cpmstar/params_test.go @@ -0,0 +1,54 @@ +package cpmstar + +import ( + "encoding/json" + "testing" + + "github.com/prebid/prebid-server/openrtb_ext" +) + +// This file actually intends to test static/bidder-params/cpmstar.json +// These also validate the format of the external API: request.imp[i].ext.cpmstar +// TestValidParams makes sure that the Cpmstar schema accepts all imp.ext fields which we intend to support. + +func TestValidParams(t *testing.T) { + validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") + if err != nil { + t.Fatalf("Failed to fetch the json-schemas. %v", err) + } + + for _, validParam := range validParams { + if err := validator.Validate(openrtb_ext.BidderCpmstar, json.RawMessage(validParam)); err != nil { + t.Errorf("Schema rejected Cpmstar params: %s", validParam) + } + } +} + +// TestInvalidParams makes sure that the Cpmstar schema rejects all the imp.ext fields we don't support. +func TestInvalidParams(t *testing.T) { + validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") + if err != nil { + t.Fatalf("Failed to fetch the json-schemas. %v", err) + } + + for _, invalidParam := range invalidParams { + if err := validator.Validate(openrtb_ext.BidderCpmstar, json.RawMessage(invalidParam)); err == nil { + t.Errorf("Schema allowed unexpected params: %s", invalidParam) + } + } +} + +var validParams = []string{ + `{"placementId": 154}`, + `{"placementId": 154, "subpoolId": 123}`, +} + +var invalidParams = []string{ + `{}`, + `null`, + `true`, + `154`, + `{"placementId": "154"}`, // placementId should be numeric + `{"placementId": 154, "subpoolId": "123"}`, // placementId and subpoolId should both be numeric + `{"invalid_param": 123}`, +} diff --git a/adapters/cpmstar/usersync.go b/adapters/cpmstar/usersync.go new file mode 100644 index 00000000000..9c864e24ce3 --- /dev/null +++ b/adapters/cpmstar/usersync.go @@ -0,0 +1,13 @@ +package cpmstar + +import ( + "text/template" + + "github.com/prebid/prebid-server/adapters" + "github.com/prebid/prebid-server/usersync" +) + +//NewCpmstarSyncer : +func NewCpmstarSyncer(temp *template.Template) usersync.Usersyncer { + return adapters.NewSyncer("cpmstar", 0, temp, adapters.SyncTypeRedirect) +} diff --git a/adapters/cpmstar/usersync_test.go b/adapters/cpmstar/usersync_test.go new file mode 100644 index 00000000000..dae55e6302e --- /dev/null +++ b/adapters/cpmstar/usersync_test.go @@ -0,0 +1,25 @@ +package cpmstar + +import ( + "testing" + "text/template" + + "github.com/prebid/prebid-server/privacy" + "github.com/stretchr/testify/assert" +) + +func TestCpmstarSyncer(t *testing.T) { + syncURL := "https://server.cpmstar.com/usersync.aspx?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirectUri=http%3A%2F%2Flocalhost:8000%2Fsetuid%3Fbidder%3Dcpmstar%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26us_privacy%3D{{.USPrivacy}}%26uid%3D%24UID" + syncURLTemplate := template.Must( + template.New("sync-template").Parse(syncURL), + ) + + syncer := NewCpmstarSyncer(syncURLTemplate) + syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{}) + + assert.NoError(t, err) + assert.Equal(t, "https://server.cpmstar.com/usersync.aspx?gdpr=&gdpr_consent=&us_privacy=&redirectUri=http%3A%2F%2Flocalhost:8000%2Fsetuid%3Fbidder%3Dcpmstar%26gdpr%3D%26gdpr_consent%3D%26us_privacy%3D%26uid%3D%24UID", syncInfo.URL) + assert.Equal(t, "redirect", syncInfo.Type) + assert.EqualValues(t, 0, syncer.GDPRVendorID()) + assert.False(t, syncInfo.SupportCORS) +} diff --git a/adapters/datablocks/usersync_test.go b/adapters/datablocks/usersync_test.go index 9dcaf8295fa..f8500ab9b03 100644 --- a/adapters/datablocks/usersync_test.go +++ b/adapters/datablocks/usersync_test.go @@ -5,12 +5,13 @@ import ( "text/template" "github.com/prebid/prebid-server/privacy" + "github.com/prebid/prebid-server/privacy/ccpa" "github.com/prebid/prebid-server/privacy/gdpr" "github.com/stretchr/testify/assert" ) func TestDatablocksSyncer(t *testing.T) { - syncURL := "https://sync.v5prebid.datablocks.net/s2ssync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&r=https%3A%2F%2Flocalhost%3A8888%2Fsetuid%3Fbidder%3Ddatablocks%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7Buid%7D" + syncURL := "https://sync.v5prebid.datablocks.net/s2ssync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r=https%3A%2F%2Flocalhost%3A8888%2Fsetuid%3Fbidder%3Ddatablocks%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7Buid%7D" syncURLTemplate := template.Must( template.New("sync-template").Parse(syncURL), ) @@ -21,10 +22,13 @@ func TestDatablocksSyncer(t *testing.T) { Signal: "1", Consent: "BONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw", }, + CCPA: ccpa.Policy{ + Value: "1NYN", + }, }) assert.NoError(t, err) - assert.Equal(t, "https://sync.v5prebid.datablocks.net/s2ssync?gdpr=1&gdpr_consent=BONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw&r=https%3A%2F%2Flocalhost%3A8888%2Fsetuid%3Fbidder%3Ddatablocks%26gdpr%3D1%26gdpr_consent%3DBONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw%26uid%3D%24%7Buid%7D", syncInfo.URL) + assert.Equal(t, "https://sync.v5prebid.datablocks.net/s2ssync?gdpr=1&gdpr_consent=BONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw&us_privacy=1NYN&r=https%3A%2F%2Flocalhost%3A8888%2Fsetuid%3Fbidder%3Ddatablocks%26gdpr%3D1%26gdpr_consent%3DBONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw%26uid%3D%24%7Buid%7D", syncInfo.URL) assert.Equal(t, "redirect", syncInfo.Type) assert.EqualValues(t, datablocksGDPRVendorID, syncer.GDPRVendorID()) assert.Equal(t, false, syncInfo.SupportCORS) diff --git a/adapters/emx_digital/usersync_test.go b/adapters/emx_digital/usersync_test.go index d8f874c8545..0e76936cea4 100644 --- a/adapters/emx_digital/usersync_test.go +++ b/adapters/emx_digital/usersync_test.go @@ -5,12 +5,13 @@ import ( "text/template" "github.com/prebid/prebid-server/privacy" + "github.com/prebid/prebid-server/privacy/ccpa" "github.com/prebid/prebid-server/privacy/gdpr" "github.com/stretchr/testify/assert" ) func TestEMXDigitalSyncer(t *testing.T) { - syncURL := "https://cs.emxdgt.com/um?ssp=pbs&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&redirect=localhost%2Fsetuid%3Fbidder%3Demx_digital%26uid%3D%24UID" + syncURL := "https://cs.emxdgt.com/um?ssp=pbs&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect=localhost%2Fsetuid%3Fbidder%3Demx_digital%26uid%3D%24UID" syncURLTemplate := template.Must( template.New("sync-template").Parse(syncURL), ) @@ -21,10 +22,13 @@ func TestEMXDigitalSyncer(t *testing.T) { Signal: "1", Consent: "BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA", }, + CCPA: ccpa.Policy{ + Value: "1NYN", + }, }) assert.NoError(t, err) - assert.Equal(t, "https://cs.emxdgt.com/um?ssp=pbs&gdpr=1&gdpr_consent=BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA&redirect=localhost%2Fsetuid%3Fbidder%3Demx_digital%26uid%3D%24UID", syncInfo.URL) + assert.Equal(t, "https://cs.emxdgt.com/um?ssp=pbs&gdpr=1&gdpr_consent=BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA&us_privacy=1NYN&redirect=localhost%2Fsetuid%3Fbidder%3Demx_digital%26uid%3D%24UID", syncInfo.URL) assert.Equal(t, "iframe", syncInfo.Type) assert.EqualValues(t, 183, syncer.GDPRVendorID()) assert.Equal(t, false, syncInfo.SupportCORS) diff --git a/adapters/engagebdr/usersync_test.go b/adapters/engagebdr/usersync_test.go index fbcde923f09..45e1e41e196 100644 --- a/adapters/engagebdr/usersync_test.go +++ b/adapters/engagebdr/usersync_test.go @@ -5,12 +5,13 @@ import ( "text/template" "github.com/prebid/prebid-server/privacy" + "github.com/prebid/prebid-server/privacy/ccpa" "github.com/prebid/prebid-server/privacy/gdpr" "github.com/stretchr/testify/assert" ) func TestEngageBDRSyncer(t *testing.T) { - syncURL := "https://match.bnmla.com/usersync/prbds2s?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&r=localhost%2Fsetuid%3Fbidder%3Dgumgum%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D" + syncURL := "https://match.bnmla.com/usersync/s2s?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r=localhost%2Fsetuid%3Fbidder%3Dengagebdr%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D" syncURLTemplate := template.Must( template.New("sync-template").Parse(syncURL), ) @@ -21,10 +22,13 @@ func TestEngageBDRSyncer(t *testing.T) { Signal: "1", Consent: "BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA", }, + CCPA: ccpa.Policy{ + Value: "1NYN", + }, }) assert.NoError(t, err) - assert.Equal(t, "https://match.bnmla.com/usersync/prbds2s?gdpr=1&gdpr_consent=BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA&r=localhost%2Fsetuid%3Fbidder%3Dgumgum%26gdpr%3D1%26gdpr_consent%3DBOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA%26uid%3D", syncInfo.URL) + assert.Equal(t, "https://match.bnmla.com/usersync/s2s?gdpr=1&gdpr_consent=BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA&us_privacy=1NYN&r=localhost%2Fsetuid%3Fbidder%3Dengagebdr%26gdpr%3D1%26gdpr_consent%3DBOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA%26uid%3D", syncInfo.URL) assert.Equal(t, "iframe", syncInfo.Type) assert.EqualValues(t, 62, syncer.GDPRVendorID()) assert.Equal(t, false, syncInfo.SupportCORS) diff --git a/adapters/eplanning/eplanning_test.go b/adapters/eplanning/eplanning_test.go index d1219ce4eef..d2c331d456d 100644 --- a/adapters/eplanning/eplanning_test.go +++ b/adapters/eplanning/eplanning_test.go @@ -8,7 +8,7 @@ import ( ) func TestJsonSamples(t *testing.T) { - eplanningAdapter := NewEPlanningBidder(new(http.Client), "http://ads.us.e-planning.net/hb/1") + eplanningAdapter := NewEPlanningBidder(new(http.Client), "https://ads.us.e-planning.net/hb/1") eplanningAdapter.testing = true adapterstest.RunJSONBidderTest(t, "eplanningtest", eplanningAdapter) } diff --git a/adapters/eplanning/eplanningtest/exemplary/simple-banner-2.json b/adapters/eplanning/eplanningtest/exemplary/simple-banner-2.json index 596b061576f..f4c8fe0c273 100644 --- a/adapters/eplanning/eplanningtest/exemplary/simple-banner-2.json +++ b/adapters/eplanning/eplanningtest/exemplary/simple-banner-2.json @@ -28,7 +28,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://ads.us.e-planning.net/hb/1/12345/1/FILE/ROS?r=pbs&ncb=1&ur=FILE&e=300x250:300x250", + "uri": "https://ads.us.e-planning.net/hb/1/12345/1/FILE/ROS?r=pbs&ncb=1&ur=FILE&e=300x250:300x250", "body": {} }, "mockResponse": { diff --git a/adapters/eplanning/eplanningtest/exemplary/simple-banner.json b/adapters/eplanning/eplanningtest/exemplary/simple-banner.json index 21cbbdae7df..61b7878a8bf 100644 --- a/adapters/eplanning/eplanningtest/exemplary/simple-banner.json +++ b/adapters/eplanning/eplanningtest/exemplary/simple-banner.json @@ -31,7 +31,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://ads.us.e-planning.net/hb/1/12345/1/FILE/ROS?r=pbs&ncb=1&ur=FILE&e=testadun_itco_de:600x300&uid=2154987&ip=123.123.123.123", + "uri": "https://ads.us.e-planning.net/hb/1/12345/1/FILE/ROS?r=pbs&ncb=1&ur=FILE&e=testadun_itco_de:600x300&uid=2154987&ip=123.123.123.123", "body": {} }, "mockResponse": { diff --git a/adapters/eplanning/eplanningtest/exemplary/two-banners.json b/adapters/eplanning/eplanningtest/exemplary/two-banners.json index 15639524207..fccc1a30e7e 100644 --- a/adapters/eplanning/eplanningtest/exemplary/two-banners.json +++ b/adapters/eplanning/eplanningtest/exemplary/two-banners.json @@ -39,7 +39,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://ads.us.e-planning.net/hb/1/12345/1/FILE/ROS?r=pbs&ncb=1&ur=FILE&e=testadunitcode:600x300+300x250:300x250&ip=123.123.123.123", + "uri": "https://ads.us.e-planning.net/hb/1/12345/1/FILE/ROS?r=pbs&ncb=1&ur=FILE&e=testadunitcode:600x300+300x250:300x250&ip=123.123.123.123", "body": {} }, "mockResponse": { @@ -120,4 +120,4 @@ } ] } - \ No newline at end of file + diff --git a/adapters/eplanning/eplanningtest/supplemental/banner-no-size-sends-1x1.json b/adapters/eplanning/eplanningtest/supplemental/banner-no-size-sends-1x1.json index 729115e55de..afa7b9532df 100644 --- a/adapters/eplanning/eplanningtest/supplemental/banner-no-size-sends-1x1.json +++ b/adapters/eplanning/eplanningtest/supplemental/banner-no-size-sends-1x1.json @@ -19,7 +19,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://ads.us.e-planning.net/hb/1/12345/1/FILE/ROS?r=pbs&ncb=1&ur=FILE&e=testadunitcodenosize:1x1", + "uri": "https://ads.us.e-planning.net/hb/1/12345/1/FILE/ROS?r=pbs&ncb=1&ur=FILE&e=testadunitcodenosize:1x1", "body": {} }, "mockResponse": { @@ -67,4 +67,4 @@ } ] } - \ No newline at end of file + diff --git a/adapters/eplanning/eplanningtest/supplemental/invalid-response-no-bids.json b/adapters/eplanning/eplanningtest/supplemental/invalid-response-no-bids.json index 57db7023360..3bf45a16364 100644 --- a/adapters/eplanning/eplanningtest/supplemental/invalid-response-no-bids.json +++ b/adapters/eplanning/eplanningtest/supplemental/invalid-response-no-bids.json @@ -21,7 +21,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://ads.us.e-planning.net/hb/1/12345/1/FILE/ROS?r=pbs&ncb=1&ur=FILE&e=testadunitcode:600x300", + "uri": "https://ads.us.e-planning.net/hb/1/12345/1/FILE/ROS?r=pbs&ncb=1&ur=FILE&e=testadunitcode:600x300", "body": {} }, "mockResponse": { @@ -45,4 +45,4 @@ } ] } - \ No newline at end of file + diff --git a/adapters/eplanning/eplanningtest/supplemental/invalid-response-unmarshall-error.json b/adapters/eplanning/eplanningtest/supplemental/invalid-response-unmarshall-error.json index fc85a6b45c0..e8d88f17a5e 100644 --- a/adapters/eplanning/eplanningtest/supplemental/invalid-response-unmarshall-error.json +++ b/adapters/eplanning/eplanningtest/supplemental/invalid-response-unmarshall-error.json @@ -21,7 +21,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://ads.us.e-planning.net/hb/1/12345/1/FILE/ROS?r=pbs&ncb=1&ur=FILE&e=testadunitcode:600x300", + "uri": "https://ads.us.e-planning.net/hb/1/12345/1/FILE/ROS?r=pbs&ncb=1&ur=FILE&e=testadunitcode:600x300", "body": {} }, "mockResponse": { @@ -52,4 +52,4 @@ } ] } - \ No newline at end of file + diff --git a/adapters/eplanning/eplanningtest/supplemental/server-bad-request.json b/adapters/eplanning/eplanningtest/supplemental/server-bad-request.json index 052c0561095..421f47efe3b 100644 --- a/adapters/eplanning/eplanningtest/supplemental/server-bad-request.json +++ b/adapters/eplanning/eplanningtest/supplemental/server-bad-request.json @@ -21,7 +21,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://ads.us.e-planning.net/hb/1/12345/1/FILE/ROS?r=pbs&ncb=1&ur=FILE&e=testadunitcode:600x300", + "uri": "https://ads.us.e-planning.net/hb/1/12345/1/FILE/ROS?r=pbs&ncb=1&ur=FILE&e=testadunitcode:600x300", "body": {} }, "mockResponse": { @@ -55,4 +55,4 @@ } ] } - \ No newline at end of file + diff --git a/adapters/eplanning/eplanningtest/supplemental/server-error-code.json b/adapters/eplanning/eplanningtest/supplemental/server-error-code.json index 699968ce398..ceec970ba45 100644 --- a/adapters/eplanning/eplanningtest/supplemental/server-error-code.json +++ b/adapters/eplanning/eplanningtest/supplemental/server-error-code.json @@ -21,7 +21,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://ads.us.e-planning.net/hb/1/12345/1/FILE/ROS?r=pbs&ncb=1&ur=FILE&e=testadunitcode:600x300", + "uri": "https://ads.us.e-planning.net/hb/1/12345/1/FILE/ROS?r=pbs&ncb=1&ur=FILE&e=testadunitcode:600x300", "body": {} }, "mockResponse": { @@ -55,4 +55,4 @@ } ] } - \ No newline at end of file + diff --git a/adapters/eplanning/eplanningtest/supplemental/server-no-content.json b/adapters/eplanning/eplanningtest/supplemental/server-no-content.json index 9058699af3e..a2e444a9901 100644 --- a/adapters/eplanning/eplanningtest/supplemental/server-no-content.json +++ b/adapters/eplanning/eplanningtest/supplemental/server-no-content.json @@ -21,7 +21,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://ads.us.e-planning.net/hb/1/12345/1/FILE/ROS?r=pbs&ncb=1&ur=FILE&e=testadunitcode:600x300", + "uri": "https://ads.us.e-planning.net/hb/1/12345/1/FILE/ROS?r=pbs&ncb=1&ur=FILE&e=testadunitcode:600x300", "body": {} }, "mockResponse": { @@ -30,4 +30,4 @@ } ] } - \ No newline at end of file + diff --git a/adapters/eplanning/eplanningtest/supplemental/site-domain-and-url-correctly-parsed.json b/adapters/eplanning/eplanningtest/supplemental/site-domain-and-url-correctly-parsed.json index 4ce8ef2f692..d889f48189c 100644 --- a/adapters/eplanning/eplanningtest/supplemental/site-domain-and-url-correctly-parsed.json +++ b/adapters/eplanning/eplanningtest/supplemental/site-domain-and-url-correctly-parsed.json @@ -25,7 +25,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://ads.us.e-planning.net/hb/1/12345/1/www.publisher.com/ROS?r=pbs&ncb=1&ur=http%3A%2F%2Fwww.publisher.com%2Fawesome%2Fsite%3Fwith%3Dsome%26parameters%3Dhere&e=testadunitcode:600x300", + "uri": "https://ads.us.e-planning.net/hb/1/12345/1/www.publisher.com/ROS?r=pbs&ncb=1&ur=http%3A%2F%2Fwww.publisher.com%2Fawesome%2Fsite%3Fwith%3Dsome%26parameters%3Dhere&e=testadunitcode:600x300", "body": {} }, "mockResponse": { @@ -73,4 +73,4 @@ } ] } - \ No newline at end of file + diff --git a/adapters/gumgum/usersync_test.go b/adapters/gumgum/usersync_test.go index 22c42695d38..3606f6ae04c 100644 --- a/adapters/gumgum/usersync_test.go +++ b/adapters/gumgum/usersync_test.go @@ -5,12 +5,13 @@ import ( "text/template" "github.com/prebid/prebid-server/privacy" + "github.com/prebid/prebid-server/privacy/ccpa" "github.com/prebid/prebid-server/privacy/gdpr" "github.com/stretchr/testify/assert" ) func TestGumGumSyncer(t *testing.T) { - syncURL := "https://rtb.gumgum.com/usync/prbds2s?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&r=localhost%2Fsetuid%3Fbidder%3Dgumgum%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D" + syncURL := "https://rtb.gumgum.com/usync/prbds2s?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r=localhost%2Fsetuid%3Fbidder%3Dgumgum%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D" syncURLTemplate := template.Must( template.New("sync-template").Parse(syncURL), ) @@ -21,10 +22,13 @@ func TestGumGumSyncer(t *testing.T) { Signal: "1", Consent: "BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA", }, + CCPA: ccpa.Policy{ + Value: "1NYN", + }, }) assert.NoError(t, err) - assert.Equal(t, "https://rtb.gumgum.com/usync/prbds2s?gdpr=1&gdpr_consent=BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA&r=localhost%2Fsetuid%3Fbidder%3Dgumgum%26gdpr%3D1%26gdpr_consent%3DBOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA%26uid%3D", syncInfo.URL) + assert.Equal(t, "https://rtb.gumgum.com/usync/prbds2s?gdpr=1&gdpr_consent=BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA&us_privacy=1NYN&r=localhost%2Fsetuid%3Fbidder%3Dgumgum%26gdpr%3D1%26gdpr_consent%3DBOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA%26uid%3D", syncInfo.URL) assert.Equal(t, "iframe", syncInfo.Type) assert.EqualValues(t, 61, syncer.GDPRVendorID()) assert.Equal(t, false, syncInfo.SupportCORS) diff --git a/adapters/improvedigital/usersync_test.go b/adapters/improvedigital/usersync_test.go index 861e4875a80..c928ebf123d 100644 --- a/adapters/improvedigital/usersync_test.go +++ b/adapters/improvedigital/usersync_test.go @@ -5,12 +5,13 @@ import ( "text/template" "github.com/prebid/prebid-server/privacy" + "github.com/prebid/prebid-server/privacy/ccpa" "github.com/prebid/prebid-server/privacy/gdpr" "github.com/stretchr/testify/assert" ) func TestImprovedigitalSyncer(t *testing.T) { - syncURL := "//not_localhost/synclocalhost%2Fsetuid%3Fbidder%3Dimprovedigital%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7BPUB_USER_ID%7D" + syncURL := "https://ad.360yield.com/server_match?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r=%2Fsetuid%3Fbidder%3Dimprovedigital%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7BPUB_USER_ID%7D" syncURLTemplate := template.Must( template.New("sync-template").Parse(syncURL), ) @@ -18,12 +19,16 @@ func TestImprovedigitalSyncer(t *testing.T) { syncer := NewImprovedigitalSyncer(syncURLTemplate) syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{ GDPR: gdpr.Policy{ - Signal: "0", + Signal: "A", + Consent: "B", + }, + CCPA: ccpa.Policy{ + Value: "C", }, }) assert.NoError(t, err) - assert.Equal(t, "//not_localhost/synclocalhost%2Fsetuid%3Fbidder%3Dimprovedigital%26gdpr%3D0%26gdpr_consent%3D%26uid%3D%7BPUB_USER_ID%7D", syncInfo.URL) + assert.Equal(t, "https://ad.360yield.com/server_match?gdpr=A&gdpr_consent=B&us_privacy=C&r=%2Fsetuid%3Fbidder%3Dimprovedigital%26gdpr%3DA%26gdpr_consent%3DB%26uid%3D%7BPUB_USER_ID%7D", syncInfo.URL) assert.Equal(t, "redirect", syncInfo.Type) assert.EqualValues(t, 253, syncer.GDPRVendorID()) assert.Equal(t, false, syncInfo.SupportCORS) diff --git a/adapters/lockerdome/usersync_test.go b/adapters/lockerdome/usersync_test.go index b0307c0f215..b5dea2261b6 100644 --- a/adapters/lockerdome/usersync_test.go +++ b/adapters/lockerdome/usersync_test.go @@ -9,7 +9,7 @@ import ( ) func TestLockerDomeSyncer(t *testing.T) { - syncURL := "https://lockerdome.com/usync/prebidserver?pid=&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&redirect=https%3A%2F%2Flocalhost%2Fsetuid%3Fbidder%3Dlockerdome%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7B%7Buid%7D%7D" + syncURL := "https://lockerdome.com/usync/prebidserver?pid=&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect=https%3A%2F%2Flocalhost%2Fsetuid%3Fbidder%3Dlockerdome%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7B%7Buid%7D%7D" syncURLTemplate := template.Must( template.New("sync-template").Parse(syncURL), ) @@ -18,7 +18,7 @@ func TestLockerDomeSyncer(t *testing.T) { syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{}) assert.NoError(t, err) - assert.Equal(t, "https://lockerdome.com/usync/prebidserver?pid=&gdpr=&gdpr_consent=&redirect=https%3A%2F%2Flocalhost%2Fsetuid%3Fbidder%3Dlockerdome%26gdpr%3D%26gdpr_consent%3D%26uid%3D%7B%7Buid%7D%7D", syncInfo.URL) + assert.Equal(t, "https://lockerdome.com/usync/prebidserver?pid=&gdpr=&gdpr_consent=&us_privacy=&redirect=https%3A%2F%2Flocalhost%2Fsetuid%3Fbidder%3Dlockerdome%26gdpr%3D%26gdpr_consent%3D%26uid%3D%7B%7Buid%7D%7D", syncInfo.URL) assert.Equal(t, "redirect", syncInfo.Type) assert.EqualValues(t, 0, syncer.GDPRVendorID()) assert.Equal(t, false, syncInfo.SupportCORS) diff --git a/adapters/marsmedia/usersync_test.go b/adapters/marsmedia/usersync_test.go index 0e50e2bcec9..67276a35fb6 100644 --- a/adapters/marsmedia/usersync_test.go +++ b/adapters/marsmedia/usersync_test.go @@ -5,16 +5,32 @@ import ( "text/template" "github.com/prebid/prebid-server/privacy" + "github.com/prebid/prebid-server/privacy/ccpa" + "github.com/prebid/prebid-server/privacy/gdpr" "github.com/stretchr/testify/assert" ) func TestMarsmediaSyncer(t *testing.T) { - temp := template.Must(template.New("sync-template").Parse("http://dmp.rtbsrv.com/dmp/profiles/cm?p_id=179&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&redirect=localhost:8000%2Fsetuid%3Fbidder%3Dmarsmedia%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7BUUID%7D")) - syncer := NewMarsmediaSyncer(temp) - syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{}) + syncURL := "https://dmp.rtbsrv.com/dmp/profiles/cm?p_id=179&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect=localhost:8000%2Fsetuid%3Fbidder%3Dmarsmedia%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7BUUID%7D" + syncURLTemplate := template.Must( + template.New("sync-template").Parse(syncURL), + ) + + syncer := NewMarsmediaSyncer(syncURLTemplate) + syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{ + GDPR: gdpr.Policy{ + Signal: "A", + Consent: "B", + }, + CCPA: ccpa.Policy{ + Value: "C", + }, + }) + assert.NoError(t, err) - assert.Equal(t, "http://dmp.rtbsrv.com/dmp/profiles/cm?p_id=179&gdpr=&gdpr_consent=&redirect=localhost:8000%2Fsetuid%3Fbidder%3Dmarsmedia%26gdpr%3D%26gdpr_consent%3D%26uid%3D%24%7BUUID%7D", syncInfo.URL) + assert.Equal(t, "https://dmp.rtbsrv.com/dmp/profiles/cm?p_id=179&gdpr=A&gdpr_consent=B&us_privacy=C&redirect=localhost:8000%2Fsetuid%3Fbidder%3Dmarsmedia%26gdpr%3DA%26gdpr_consent%3DB%26uid%3D%24%7BUUID%7D", syncInfo.URL) assert.Equal(t, "redirect", syncInfo.Type) assert.EqualValues(t, 0, syncer.GDPRVendorID()) assert.Equal(t, false, syncInfo.SupportCORS) + } diff --git a/adapters/pubmatic/pubmatic_test.go b/adapters/pubmatic/pubmatic_test.go index 4eb66d25430..be086f5adf1 100644 --- a/adapters/pubmatic/pubmatic_test.go +++ b/adapters/pubmatic/pubmatic_test.go @@ -23,7 +23,7 @@ import ( ) func TestJsonSamples(t *testing.T) { - adapterstest.RunJSONBidderTest(t, "pubmatictest", NewPubmaticBidder(nil, "http://hbopenbid.pubmatic.com/translator?source=prebid-server")) + adapterstest.RunJSONBidderTest(t, "pubmatictest", NewPubmaticBidder(nil, "https://hbopenbid.pubmatic.com/translator?source=prebid-server")) } // ---------------------------------------------------------------------------- diff --git a/adapters/pubmatic/pubmatictest/exemplary/simple-banner.json b/adapters/pubmatic/pubmatictest/exemplary/simple-banner.json index e669bce8826..1eb8a212bff 100644 --- a/adapters/pubmatic/pubmatictest/exemplary/simple-banner.json +++ b/adapters/pubmatic/pubmatictest/exemplary/simple-banner.json @@ -43,7 +43,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://hbopenbid.pubmatic.com/translator?source=prebid-server", + "uri": "https://hbopenbid.pubmatic.com/translator?source=prebid-server", "body": { "id": "test-request-id", "imp": [ diff --git a/adapters/pubmatic/pubmatictest/exemplary/video.json b/adapters/pubmatic/pubmatictest/exemplary/video.json index f9cfc2976ea..25ed366ee05 100644 --- a/adapters/pubmatic/pubmatictest/exemplary/video.json +++ b/adapters/pubmatic/pubmatictest/exemplary/video.json @@ -49,7 +49,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://hbopenbid.pubmatic.com/translator?source=prebid-server", + "uri": "https://hbopenbid.pubmatic.com/translator?source=prebid-server", "body": { "id": "test-video-request", "imp": [ diff --git a/adapters/pubmatic/pubmatictest/supplemental/app.json b/adapters/pubmatic/pubmatictest/supplemental/app.json index a2b737f0aa2..636433ca1f5 100644 --- a/adapters/pubmatic/pubmatictest/supplemental/app.json +++ b/adapters/pubmatic/pubmatictest/supplemental/app.json @@ -43,7 +43,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://hbopenbid.pubmatic.com/translator?source=prebid-server", + "uri": "https://hbopenbid.pubmatic.com/translator?source=prebid-server", "body": { "id": "app-request", "imp": [ diff --git a/adapters/pubmatic/pubmatictest/supplemental/multiplemedia.json b/adapters/pubmatic/pubmatictest/supplemental/multiplemedia.json index faf71fec1b6..a576abe6198 100644 --- a/adapters/pubmatic/pubmatictest/supplemental/multiplemedia.json +++ b/adapters/pubmatic/pubmatictest/supplemental/multiplemedia.json @@ -29,7 +29,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://hbopenbid.pubmatic.com/translator?source=prebid-server", + "uri": "https://hbopenbid.pubmatic.com/translator?source=prebid-server", "body": { "id": "multiple-media-request", "imp": [ diff --git a/adapters/pubmatic/usersync_test.go b/adapters/pubmatic/usersync_test.go index ef81d223377..dd4a086c453 100644 --- a/adapters/pubmatic/usersync_test.go +++ b/adapters/pubmatic/usersync_test.go @@ -5,12 +5,13 @@ import ( "text/template" "github.com/prebid/prebid-server/privacy" + "github.com/prebid/prebid-server/privacy/ccpa" "github.com/prebid/prebid-server/privacy/gdpr" "github.com/stretchr/testify/assert" ) func TestPubmaticSyncer(t *testing.T) { - syncURL := "//ads.pubmatic.com/AdServer/js/user_sync.html?predirect=localhost%2Fsetuid%3Fbidder%3Dpubmatic%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D" + syncURL := "//ads.pubmatic.com/AdServer/js/user_sync.html?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&predirect=localhost%2Fsetuid%3Fbidder%3Dpubmatic%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D" syncURLTemplate := template.Must( template.New("sync-template").Parse(syncURL), ) @@ -18,13 +19,16 @@ func TestPubmaticSyncer(t *testing.T) { syncer := NewPubmaticSyncer(syncURLTemplate) syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{ GDPR: gdpr.Policy{ - Signal: "1", - Consent: "BONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw", + Signal: "A", + Consent: "B", + }, + CCPA: ccpa.Policy{ + Value: "C", }, }) assert.NoError(t, err) - assert.Equal(t, "//ads.pubmatic.com/AdServer/js/user_sync.html?predirect=localhost%2Fsetuid%3Fbidder%3Dpubmatic%26gdpr%3D1%26gdpr_consent%3DBONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw%26uid%3D", syncInfo.URL) + assert.Equal(t, "//ads.pubmatic.com/AdServer/js/user_sync.html?gdpr=A&gdpr_consent=B&us_privacy=C&predirect=localhost%2Fsetuid%3Fbidder%3Dpubmatic%26gdpr%3DA%26gdpr_consent%3DB%26uid%3D", syncInfo.URL) assert.Equal(t, "iframe", syncInfo.Type) assert.EqualValues(t, 76, syncer.GDPRVendorID()) assert.Equal(t, false, syncInfo.SupportCORS) diff --git a/adapters/rhythmone/usersync_test.go b/adapters/rhythmone/usersync_test.go index 0dcf4fbda7e..cee6e9b0259 100644 --- a/adapters/rhythmone/usersync_test.go +++ b/adapters/rhythmone/usersync_test.go @@ -5,12 +5,13 @@ import ( "text/template" "github.com/prebid/prebid-server/privacy" + "github.com/prebid/prebid-server/privacy/ccpa" "github.com/prebid/prebid-server/privacy/gdpr" "github.com/stretchr/testify/assert" ) func TestRhythmoneSyncer(t *testing.T) { - syncURL := "https://sync.1rx.io/usersync2/rmphb?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&redir=localhost%2Fsetuid%3Fbidder%3Drhythmone%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%5BRX_UUID%5D" + syncURL := "https://sync.1rx.io/usersync2/rmphb?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir=localhost%2Fsetuid%3Fbidder%3Drhythmone%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%5BRX_UUID%5D" syncURLTemplate := template.Must( template.New("sync-template").Parse(syncURL), ) @@ -21,10 +22,13 @@ func TestRhythmoneSyncer(t *testing.T) { Signal: "1", Consent: "BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA", }, + CCPA: ccpa.Policy{ + Value: "1NYN", + }, }) assert.NoError(t, err) - assert.Equal(t, "https://sync.1rx.io/usersync2/rmphb?gdpr=1&gdpr_consent=BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA&redir=localhost%2Fsetuid%3Fbidder%3Drhythmone%26gdpr%3D1%26gdpr_consent%3DBOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA%26uid%3D%5BRX_UUID%5D", syncInfo.URL) + assert.Equal(t, "https://sync.1rx.io/usersync2/rmphb?gdpr=1&gdpr_consent=BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA&us_privacy=1NYN&redir=localhost%2Fsetuid%3Fbidder%3Drhythmone%26gdpr%3D1%26gdpr_consent%3DBOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA%26uid%3D%5BRX_UUID%5D", syncInfo.URL) assert.Equal(t, "redirect", syncInfo.Type) assert.EqualValues(t, 36, syncer.GDPRVendorID()) assert.Equal(t, false, syncInfo.SupportCORS) diff --git a/adapters/rubicon/rubicon.go b/adapters/rubicon/rubicon.go index 7f8de46bcfe..46caf262108 100644 --- a/adapters/rubicon/rubicon.go +++ b/adapters/rubicon/rubicon.go @@ -5,13 +5,14 @@ import ( "context" "encoding/json" "fmt" - "github.com/golang/glog" - "github.com/prebid/prebid-server/pbs" "io/ioutil" "net/http" "net/url" "strings" + "github.com/golang/glog" + "github.com/prebid/prebid-server/pbs" + "golang.org/x/net/context/ctxhttp" "github.com/mxmCherry/openrtb" @@ -128,6 +129,7 @@ type rubiconVideoParams struct { type rubiconVideoExt struct { Skip int `json:"skip,omitempty"` SkipDelay int `json:"skipdelay,omitempty"` + VideoType string `json:"videotype,omitempty"` RP rubiconVideoExtRP `json:"rp"` } @@ -685,8 +687,21 @@ func (a *RubiconAdapter) MakeRequests(request *openrtb.BidRequest, reqInfo *adap isVideo := isVideo(thisImp) if isVideo { + if rubiconExt.Video.VideoSizeID == 0 { + errs = append(errs, &errortypes.BadInput{ + Message: fmt.Sprintf("imp[%d].ext.bidder.rubicon.video.size_id must be defined for video impression", i), + }) + continue + } + + // if imp.ext.is_rewarded_inventory = 1, set imp.video.ext.videotype = "rewarded" + var videoType = "" + if bidderExt.Prebid != nil && bidderExt.Prebid.IsRewardedInventory == 1 { + videoType = "rewarded" + } + videoCopy := *thisImp.Video - videoExt := rubiconVideoExt{Skip: rubiconExt.Video.Skip, SkipDelay: rubiconExt.Video.SkipDelay, RP: rubiconVideoExtRP{SizeID: rubiconExt.Video.VideoSizeID}} + videoExt := rubiconVideoExt{Skip: rubiconExt.Video.Skip, SkipDelay: rubiconExt.Video.SkipDelay, VideoType: videoType, RP: rubiconVideoExtRP{SizeID: rubiconExt.Video.VideoSizeID}} videoCopy.Ext, err = json.Marshal(&videoExt) thisImp.Video = &videoCopy thisImp.Banner = nil diff --git a/adapters/rubicon/rubicon_test.go b/adapters/rubicon/rubicon_test.go index bc3d2e8ae9e..d386daed5b1 100644 --- a/adapters/rubicon/rubicon_test.go +++ b/adapters/rubicon/rubicon_test.go @@ -1244,8 +1244,9 @@ func TestOpenRTBRequestWithVideoImpEvenIfImpHasBannerButAllRequiredVideoFields(t "zoneId": 8394, "siteId": 283282, "accountId": 7891, - "inventory": {"key1" : "val1"}, - "visitor": {"key2" : "val2"} + "inventory": {"key1": "val1"}, + "visitor": {"key2": "val2"}, + "video": {"size_id": 1} }}`), }}, } @@ -1269,6 +1270,48 @@ func TestOpenRTBRequestWithVideoImpEvenIfImpHasBannerButAllRequiredVideoFields(t assert.NotNil(t, rubiconReq.Imp[0].Video, "Video object must be in request impression") } +func TestOpenRTBRequestWithVideoImpAndEnabledRewardedInventoryFlag(t *testing.T) { + bidder := new(RubiconAdapter) + + request := &openrtb.BidRequest{ + ID: "test-request-id", + Imp: []openrtb.Imp{{ + ID: "test-imp-id", + Video: &openrtb.Video{ + W: 640, + H: 360, + MIMEs: []string{"video/mp4"}, + Protocols: []openrtb.Protocol{openrtb.ProtocolVAST10}, + MaxDuration: 30, + Linearity: 1, + API: []openrtb.APIFramework{}, + }, + Ext: json.RawMessage(`{ + "prebid":{ + "is_rewarded_inventory": 1 + }, + "bidder": { + "video": {"size_id": 1} + }}`), + }}, + } + + reqs, _ := bidder.MakeRequests(request, &adapters.ExtraRequestInfo{}) + + rubiconReq := &openrtb.BidRequest{} + if err := json.Unmarshal(reqs[0].Body, rubiconReq); err != nil { + t.Fatalf("Unexpected error while decoding request: %s", err) + } + + videoExt := &rubiconVideoExt{} + if err := json.Unmarshal(rubiconReq.Imp[0].Video.Ext, &videoExt); err != nil { + t.Fatal("Error unmarshalling request.imp[i].video.ext object.") + } + + assert.Equal(t, "rewarded", videoExt.VideoType, + "Unexpected VideoType. Got %s. Expected %s", videoExt.VideoType, "rewarded") +} + func TestOpenRTBEmptyResponse(t *testing.T) { httpResp := &adapters.ResponseData{ StatusCode: http.StatusNoContent, diff --git a/adapters/rubicon/rubicontest/supplemental/required-video-size-id.json b/adapters/rubicon/rubicontest/supplemental/required-video-size-id.json new file mode 100644 index 00000000000..cf0a594e13c --- /dev/null +++ b/adapters/rubicon/rubicontest/supplemental/required-video-size-id.json @@ -0,0 +1,31 @@ +{ + "mockBidRequest": { + "id": "test-req-id", + "imp": [ + { + "id": "test-imp-1", + "video": { + "w": 640, + "h": 480, + "linearity": 1 + }, + "ext": { + "bidder": { + "accountId": 1001, + "siteId":113932, + "zoneId":535510 + } + } + } + ], + "site": { + "page": "prebid.org" + } + }, + "expectedMakeRequestsErrors": [ + { + "value": "imp[0].ext.bidder.rubicon.video.size_id must be defined for video impression", + "comparison": "literal" + } + ] +} diff --git a/adapters/smartrtb/smartrtb.go b/adapters/smartrtb/smartrtb.go new file mode 100644 index 00000000000..5edaae6f289 --- /dev/null +++ b/adapters/smartrtb/smartrtb.go @@ -0,0 +1,189 @@ +package smartrtb + +import ( + "encoding/json" + "fmt" + "net/http" + "text/template" + + "github.com/golang/glog" + "github.com/mxmCherry/openrtb" + "github.com/prebid/prebid-server/adapters" + "github.com/prebid/prebid-server/errortypes" + "github.com/prebid/prebid-server/macros" + "github.com/prebid/prebid-server/openrtb_ext" +) + +// Base adapter structure. +type SmartRTBAdapter struct { + EndpointTemplate template.Template +} + +// Bid request extension appended to downstream request. +// PubID are non-empty iff request.{App,Site} or +// request.{App,Site}.Publisher are nil, respectively. +type bidRequestExt struct { + PubID string `json:"pub_id,omitempty"` + ZoneID string `json:"zone_id,omitempty"` + ForceBid bool `json:"force_bid,omitempty"` +} + +// bidExt.CreativeType values. +const ( + creativeTypeBanner string = "BANNER" + creativeTypeVideo = "VIDEO" + creativeTypeNative = "NATIVE" + creativeTypeAudio = "AUDIO" +) + +// Bid response extension from downstream. +type bidExt struct { + CreativeType string `json:"format"` +} + +func NewSmartRTBBidder(endpointTemplate string) adapters.Bidder { + template, err := template.New("endpointTemplate").Parse(endpointTemplate) + if err != nil { + glog.Fatal("Template URL error") + return nil + } + return &SmartRTBAdapter{EndpointTemplate: *template} +} + +func (adapter *SmartRTBAdapter) buildEndpointURL(pubID string) (string, error) { + endpointParams := macros.EndpointTemplateParams{PublisherID: pubID} + return macros.ResolveMacros(adapter.EndpointTemplate, endpointParams) +} + +func parseExtImp(dst *bidRequestExt, imp *openrtb.Imp) error { + var ext adapters.ExtImpBidder + if err := json.Unmarshal(imp.Ext, &ext); err != nil { + return adapters.BadInput(err.Error()) + } + + var src openrtb_ext.ExtImpSmartRTB + if err := json.Unmarshal(ext.Bidder, &src); err != nil { + return adapters.BadInput(err.Error()) + } + + if dst.PubID == "" { + dst.PubID = src.PubID + } + + if src.ZoneID != "" { + imp.TagID = src.ZoneID + } + return nil +} + +func (s *SmartRTBAdapter) MakeRequests(brq *openrtb.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { + var imps []openrtb.Imp + var err error + ext := bidRequestExt{} + nrImps := len(brq.Imp) + errs := make([]error, 0, nrImps) + + for i := 0; i < nrImps; i++ { + imp := brq.Imp[i] + if imp.Banner == nil && imp.Video == nil { + continue + } + + err = parseExtImp(&ext, &imp) + if err != nil { + errs = append(errs, err) + continue + } + + imps = append(imps, imp) + } + + if len(imps) == 0 { + return nil, errs + } + + if ext.PubID == "" { + return nil, append(errs, adapters.BadInput("Cannot infer publisher ID from bid ext")) + } + + brq.Ext, err = json.Marshal(ext) + if err != nil { + return nil, append(errs, err) + } + + brq.Imp = imps + + rq, err := json.Marshal(brq) + if err != nil { + return nil, append(errs, err) + } + + url, err := s.buildEndpointURL(ext.PubID) + if err != nil { + return nil, append(errs, err) + } + + headers := http.Header{} + headers.Add("Content-Type", "application/json;charset=utf-8") + headers.Add("Accept", "application/json") + headers.Add("x-openrtb-version", "2.5") + return []*adapters.RequestData{{ + Method: "POST", + Uri: url, + Body: rq, + Headers: headers, + }}, errs +} + +func (s *SmartRTBAdapter) MakeBids( + brq *openrtb.BidRequest, drq *adapters.RequestData, + rs *adapters.ResponseData, +) (*adapters.BidderResponse, []error) { + if rs.StatusCode == http.StatusNoContent { + return nil, nil + } else if rs.StatusCode == http.StatusBadRequest { + return nil, []error{adapters.BadInput("Invalid request.")} + } else if rs.StatusCode != http.StatusOK { + return nil, []error{&errortypes.BadServerResponse{ + Message: fmt.Sprintf("Unexpected HTTP status %d.", rs.StatusCode), + }} + } + + var brs openrtb.BidResponse + if err := json.Unmarshal(rs.Body, &brs); err != nil { + return nil, []error{err} + } + + rv := adapters.NewBidderResponseWithBidsCapacity(5) + for _, seat := range brs.SeatBid { + for i := range seat.Bid { + var ext bidExt + if err := json.Unmarshal(seat.Bid[i].Ext, &ext); err != nil { + return nil, []error{&errortypes.BadServerResponse{ + Message: "Invalid bid extension from endpoint.", + }} + } + + var btype openrtb_ext.BidType + switch ext.CreativeType { + case creativeTypeBanner: + btype = openrtb_ext.BidTypeBanner + case creativeTypeVideo: + btype = openrtb_ext.BidTypeVideo + default: + return nil, []error{&errortypes.BadServerResponse{ + Message: fmt.Sprintf("Unsupported creative type %s.", + ext.CreativeType), + }} + } + + seat.Bid[i].Ext = nil + + rv.Bids = append(rv.Bids, &adapters.TypedBid{ + Bid: &seat.Bid[i], + BidType: btype, + }) + } + } + return rv, nil +} diff --git a/adapters/smartrtb/smartrtb_test.go b/adapters/smartrtb/smartrtb_test.go new file mode 100644 index 00000000000..3f76ed044a8 --- /dev/null +++ b/adapters/smartrtb/smartrtb_test.go @@ -0,0 +1,11 @@ +package smartrtb + +import ( + "testing" + + "github.com/prebid/prebid-server/adapters/adapterstest" +) + +func TestJsonSamples(t *testing.T) { + adapterstest.RunJSONBidderTest(t, "smartrtbtest", NewSmartRTBBidder("http://market-east.smrtb.com/json/publisher/rtb?pubid=test")) +} diff --git a/adapters/smartrtb/smartrtbtest/exemplary/banner.json b/adapters/smartrtb/smartrtbtest/exemplary/banner.json new file mode 100644 index 00000000000..436f6298a16 --- /dev/null +++ b/adapters/smartrtb/smartrtbtest/exemplary/banner.json @@ -0,0 +1,134 @@ +{ + "mockBidRequest": { + "id": "abc", + "site": { + "page": "prebid.org" + }, + "imp": [ + { + "id": "imp123", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ], + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "pub_id": "test", + "zone_id": "N4zTDq3PPEHBIODv7cXK", + "force_bid": true + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://market-east.smrtb.com/json/publisher/rtb?pubid=test", + "body":{ + "id": "abc", + "site": { + "page": "prebid.org" + }, + "imp": [{ + "id": "imp123", + "tagid": "N4zTDq3PPEHBIODv7cXK", + "banner": { + "format": [{ + "w": 300, + "h": 250 + }], + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "pub_id": "test", + "zone_id": "N4zTDq3PPEHBIODv7cXK", + "force_bid": true + } + } + }], + "ext": { + "pub_id": "test" + } + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "abc", + "seatbid": [ + { + "bid": [ + { + "adm": "hi", + "crid": "test_banner_crid", + "cid": "test_cid", + "impid": "imp123", + "id": "1", + "price": 0.01, + "ext": { + "format": "BANNER" + } + } + ] + }, + { + "bid": [ + { + "adm": "", + "crid": "test_video_crid", + "cid": "test_cid", + "impid": "imp123", + "id": "2", + "price": 0.01, + "ext": { + "format": "VIDEO" + } + } + ] + } + ] + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "adm": "hi", + "crid": "test_banner_crid", + "cid": "test_cid", + "impid": "imp123", + "price": 0.01, + "id": "1" + }, + "type": "banner" + }, + { + "bid": { + "adm": "", + "crid": "test_video_crid", + "cid": "test_cid", + "impid": "imp123", + "price": 0.01, + "id": "2" + }, + "type": "video" + } + ] + } + ] +} diff --git a/adapters/smartrtb/smartrtbtest/exemplary/video.json b/adapters/smartrtb/smartrtbtest/exemplary/video.json new file mode 100644 index 00000000000..436f6298a16 --- /dev/null +++ b/adapters/smartrtb/smartrtbtest/exemplary/video.json @@ -0,0 +1,134 @@ +{ + "mockBidRequest": { + "id": "abc", + "site": { + "page": "prebid.org" + }, + "imp": [ + { + "id": "imp123", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ], + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "pub_id": "test", + "zone_id": "N4zTDq3PPEHBIODv7cXK", + "force_bid": true + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://market-east.smrtb.com/json/publisher/rtb?pubid=test", + "body":{ + "id": "abc", + "site": { + "page": "prebid.org" + }, + "imp": [{ + "id": "imp123", + "tagid": "N4zTDq3PPEHBIODv7cXK", + "banner": { + "format": [{ + "w": 300, + "h": 250 + }], + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "pub_id": "test", + "zone_id": "N4zTDq3PPEHBIODv7cXK", + "force_bid": true + } + } + }], + "ext": { + "pub_id": "test" + } + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "abc", + "seatbid": [ + { + "bid": [ + { + "adm": "hi", + "crid": "test_banner_crid", + "cid": "test_cid", + "impid": "imp123", + "id": "1", + "price": 0.01, + "ext": { + "format": "BANNER" + } + } + ] + }, + { + "bid": [ + { + "adm": "", + "crid": "test_video_crid", + "cid": "test_cid", + "impid": "imp123", + "id": "2", + "price": 0.01, + "ext": { + "format": "VIDEO" + } + } + ] + } + ] + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "adm": "hi", + "crid": "test_banner_crid", + "cid": "test_cid", + "impid": "imp123", + "price": 0.01, + "id": "1" + }, + "type": "banner" + }, + { + "bid": { + "adm": "", + "crid": "test_video_crid", + "cid": "test_cid", + "impid": "imp123", + "price": 0.01, + "id": "2" + }, + "type": "video" + } + ] + } + ] +} diff --git a/adapters/smartrtb/smartrtbtest/params/race/banner.json b/adapters/smartrtb/smartrtbtest/params/race/banner.json new file mode 100644 index 00000000000..207a504539f --- /dev/null +++ b/adapters/smartrtb/smartrtbtest/params/race/banner.json @@ -0,0 +1,5 @@ +{ + "pub_id": "test", + "zone_id": "N4zTDq3PPEHBIODv7cXK", + "force_bid": true +} \ No newline at end of file diff --git a/adapters/smartrtb/smartrtbtest/params/race/video.json b/adapters/smartrtb/smartrtbtest/params/race/video.json new file mode 100644 index 00000000000..207a504539f --- /dev/null +++ b/adapters/smartrtb/smartrtbtest/params/race/video.json @@ -0,0 +1,5 @@ +{ + "pub_id": "test", + "zone_id": "N4zTDq3PPEHBIODv7cXK", + "force_bid": true +} \ No newline at end of file diff --git a/adapters/smartrtb/smartrtbtest/supplemental/bad-bidder-ext.json b/adapters/smartrtb/smartrtbtest/supplemental/bad-bidder-ext.json new file mode 100644 index 00000000000..b261415de4d --- /dev/null +++ b/adapters/smartrtb/smartrtbtest/supplemental/bad-bidder-ext.json @@ -0,0 +1,31 @@ +{ + "mockBidRequest": { + "id": "abc", + "site": { + "page": "prebid.org" + }, + "imp": [ + { + "id": "imp123", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ], + "w": 300, + "h": 250 + }, + "ext": null + } + ] + }, + + "expectedMakeRequestsErrors": [ + { + "value": "unexpected end of JSON input", + "comparison": "literal" + } + ] +} diff --git a/adapters/smartrtb/smartrtbtest/supplemental/bad-imp-ext.json b/adapters/smartrtb/smartrtbtest/supplemental/bad-imp-ext.json new file mode 100644 index 00000000000..1c0f57d2f34 --- /dev/null +++ b/adapters/smartrtb/smartrtbtest/supplemental/bad-imp-ext.json @@ -0,0 +1,32 @@ +{ + "mockBidRequest": { + "id": "abc", + "site": { + "page": "prebid.org" + }, + "publisher": { }, + "imp": [ + { + "id": "imp123", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ], + "w": 300, + "h": 250 + }, + "ext": null + } + ] + }, + + "expectedMakeRequestsErrors": [ + { + "value": "unexpected end of JSON input", + "comparison": "literal" + } + ] +} diff --git a/adapters/smartrtb/smartrtbtest/supplemental/bad-pub-value-empty.json b/adapters/smartrtb/smartrtbtest/supplemental/bad-pub-value-empty.json new file mode 100644 index 00000000000..aca21036b24 --- /dev/null +++ b/adapters/smartrtb/smartrtbtest/supplemental/bad-pub-value-empty.json @@ -0,0 +1,37 @@ +{ + "mockBidRequest": { + "id": "abc", + "site": { + "page": "prebid.org" + }, + "publisher": { }, + "imp": [ + { + "id": "imp123", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ], + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "zone_id": "N4zTDq3PPEHBIODv7cXK", + "force_bid": true + } + } + } + ] + }, + + "expectedMakeRequestsErrors": [ + { + "value": "Cannot infer publisher ID from bid ext", + "comparison": "literal" + } + ] +} diff --git a/adapters/smartrtb/smartrtbtest/supplemental/bad-pub-value.json b/adapters/smartrtb/smartrtbtest/supplemental/bad-pub-value.json new file mode 100644 index 00000000000..93b45c747fd --- /dev/null +++ b/adapters/smartrtb/smartrtbtest/supplemental/bad-pub-value.json @@ -0,0 +1,37 @@ +{ + "mockBidRequest": { + "id": "abc", + "site": { + "page": "prebid.org" + }, + "imp": [ + { + "id": "imp123", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ], + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "pub_id": 0, + "zone_id": "N4zTDq3PPEHBIODv7cXK", + "force_bid": true + } + } + } + ] + }, + + "expectedMakeRequestsErrors": [ + { + "value": "json: cannot unmarshal number into Go struct field ExtImpSmartRTB.pub_id of type string", + "comparison": "literal" + } + ] +} diff --git a/adapters/smartrtb/smartrtbtest/supplemental/bad-request.json b/adapters/smartrtb/smartrtbtest/supplemental/bad-request.json new file mode 100644 index 00000000000..cf03832ddff --- /dev/null +++ b/adapters/smartrtb/smartrtbtest/supplemental/bad-request.json @@ -0,0 +1,70 @@ +{ + "mockBidRequest": { + "id": "abc", + "imp": [ + { + "id": "imp123", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ], + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "pub_id": "test", + "zone_id": "fake", + "force_bid": false + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://market-east.smrtb.com/json/publisher/rtb?pubid=test", + "body":{ + "id": "abc", + "imp": [{ + "id": "imp123", + "tagid": "fake", + "banner": { + "format": [{ + "w": 300, + "h": 250 + }], + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "pub_id": "test", + "zone_id": "fake", + "force_bid": false + } + } + }], + "ext": { + "pub_id": "test" + } + } + }, + "mockResponse": { + "status": 400 + } + } + ], + + "expectedMakeBidsErrors": [ + { + "value": "Invalid request.", + "comparison": "literal" + } + ] +} diff --git a/adapters/smartrtb/smartrtbtest/supplemental/empty-imps.json b/adapters/smartrtb/smartrtbtest/supplemental/empty-imps.json new file mode 100644 index 00000000000..a92add70825 --- /dev/null +++ b/adapters/smartrtb/smartrtbtest/supplemental/empty-imps.json @@ -0,0 +1,14 @@ +{ + "mockBidRequest": { + "id": "abc", + "site": { + "page": "prebid.org" + }, + "publisher": { }, + "imp": [ + { + "id": "imp123" + } + ] + } +} diff --git a/adapters/smartrtb/smartrtbtest/supplemental/invalid-bid-ext.json b/adapters/smartrtb/smartrtbtest/supplemental/invalid-bid-ext.json new file mode 100644 index 00000000000..49527e1ecd4 --- /dev/null +++ b/adapters/smartrtb/smartrtbtest/supplemental/invalid-bid-ext.json @@ -0,0 +1,93 @@ +{ + "mockBidRequest": { + "id": "abc", + "site": { + "page": "prebid.org" + }, + "imp": [ + { + "id": "imp123", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ], + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "pub_id": "test", + "zone_id": "N4zTDq3PPEHBIODv7cXK", + "force_bid": true + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://market-east.smrtb.com/json/publisher/rtb?pubid=test", + "body":{ + "id": "abc", + "site": { + "page": "prebid.org" + }, + "imp": [{ + "id": "imp123", + "tagid": "N4zTDq3PPEHBIODv7cXK", + "banner": { + "format": [{ + "w": 300, + "h": 250 + }], + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "pub_id": "test", + "zone_id": "N4zTDq3PPEHBIODv7cXK", + "force_bid": true + } + } + }], + "ext": { + "pub_id": "test" + } + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "abc", + "seatbid": [ + { + "bid": [ + { + "adm": "hi", + "crid": "test_banner_crid", + "cid": "test_cid", + "impid": "imp123", + "id": "1", + "price": 0.01, + "ext": "notvalidjsonhaha" + } + ] + } + ] + } + } + } + ], + "expectedMakeBidsErrors": [ + { + "value": "Invalid bid extension from endpoint.", + "comparison": "literal" + } + ] +} diff --git a/adapters/smartrtb/smartrtbtest/supplemental/invalid-bid-format.json b/adapters/smartrtb/smartrtbtest/supplemental/invalid-bid-format.json new file mode 100644 index 00000000000..2f6bc07edb8 --- /dev/null +++ b/adapters/smartrtb/smartrtbtest/supplemental/invalid-bid-format.json @@ -0,0 +1,95 @@ +{ + "mockBidRequest": { + "id": "abc", + "site": { + "page": "prebid.org" + }, + "imp": [ + { + "id": "imp123", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ], + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "pub_id": "test", + "zone_id": "N4zTDq3PPEHBIODv7cXK", + "force_bid": true + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://market-east.smrtb.com/json/publisher/rtb?pubid=test", + "body":{ + "id": "abc", + "site": { + "page": "prebid.org" + }, + "imp": [{ + "id": "imp123", + "tagid": "N4zTDq3PPEHBIODv7cXK", + "banner": { + "format": [{ + "w": 300, + "h": 250 + }], + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "pub_id": "test", + "zone_id": "N4zTDq3PPEHBIODv7cXK", + "force_bid": true + } + } + }], + "ext": { + "pub_id": "test" + } + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "abc", + "seatbid": [ + { + "bid": [ + { + "adm": "hi", + "crid": "test_banner_crid", + "cid": "test_cid", + "impid": "imp123", + "id": "1", + "price": 0.01, + "ext": { + "format": "ALIEN_FORMAT" + } + } + ] + } + ] + } + } + } + ], + "expectedMakeBidsErrors": [ + { + "value": "Unsupported creative type ALIEN_FORMAT.", + "comparison": "literal" + } + ] +} diff --git a/adapters/smartrtb/smartrtbtest/supplemental/invalid-bid-json.json b/adapters/smartrtb/smartrtbtest/supplemental/invalid-bid-json.json new file mode 100644 index 00000000000..c56e7f21515 --- /dev/null +++ b/adapters/smartrtb/smartrtbtest/supplemental/invalid-bid-json.json @@ -0,0 +1,76 @@ +{ + "mockBidRequest": { + "id": "abc", + "site": { + "page": "prebid.org" + }, + "imp": [ + { + "id": "imp123", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ], + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "pub_id": "test", + "zone_id": "N4zTDq3PPEHBIODv7cXK", + "force_bid": true + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://market-east.smrtb.com/json/publisher/rtb?pubid=test", + "body":{ + "id": "abc", + "site": { + "page": "prebid.org" + }, + "imp": [{ + "id": "imp123", + "tagid": "N4zTDq3PPEHBIODv7cXK", + "banner": { + "format": [{ + "w": 300, + "h": 250 + }], + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "pub_id": "test", + "zone_id": "N4zTDq3PPEHBIODv7cXK", + "force_bid": true + } + } + }], + "ext": { + "pub_id": "test" + } + } + }, + "mockResponse": { + "status": 200, + "body": "imnotyourfather" + } + } + ], + "expectedMakeBidsErrors": [ + { + "value": "json: cannot unmarshal string into Go value of type openrtb.BidResponse", + "comparison": "literal" + } + ] +} diff --git a/adapters/smartrtb/smartrtbtest/supplemental/invalid-imp-ext.json b/adapters/smartrtb/smartrtbtest/supplemental/invalid-imp-ext.json new file mode 100644 index 00000000000..13485f797ba --- /dev/null +++ b/adapters/smartrtb/smartrtbtest/supplemental/invalid-imp-ext.json @@ -0,0 +1,32 @@ +{ + "mockBidRequest": { + "id": "abc", + "site": { + "page": "prebid.org" + }, + "publisher": { }, + "imp": [ + { + "id": "imp123", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ], + "w": 300, + "h": 250 + }, + "ext": "notjsontho" + } + ] + }, + + "expectedMakeRequestsErrors": [ + { + "value": "json: cannot unmarshal string into Go value of type adapters.ExtImpBidder", + "comparison": "literal" + } + ] +} diff --git a/adapters/smartrtb/smartrtbtest/supplemental/nobid.json b/adapters/smartrtb/smartrtbtest/supplemental/nobid.json new file mode 100644 index 00000000000..2733d8dba96 --- /dev/null +++ b/adapters/smartrtb/smartrtbtest/supplemental/nobid.json @@ -0,0 +1,69 @@ +{ + "mockBidRequest": { + "id": "abc", + "site": { + "page": "prebid.org" + }, + "imp": [ + { + "id": "imp123", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ], + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "pub_id": "test", + "zone_id": "N4zTDq3PPEHBIODv7cXKz", + "force_bid": false + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://market-east.smrtb.com/json/publisher/rtb?pubid=test", + "body":{ + "id": "abc", + "site": { + "page": "prebid.org" + }, + "imp": [{ + "id": "imp123", + "tagid": "N4zTDq3PPEHBIODv7cXKz", + "banner": { + "format": [{ + "w": 300, + "h": 250 + }], + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "pub_id": "test", + "zone_id": "N4zTDq3PPEHBIODv7cXKz", + "force_bid": false + } + } + }], + "ext": { + "pub_id": "test" + } + } + }, + "mockResponse": { + "status": 204 + } + } + ] +} diff --git a/adapters/smartrtb/smartrtbtest/supplemental/non-http-ok.json b/adapters/smartrtb/smartrtbtest/supplemental/non-http-ok.json new file mode 100644 index 00000000000..3acafadc62f --- /dev/null +++ b/adapters/smartrtb/smartrtbtest/supplemental/non-http-ok.json @@ -0,0 +1,76 @@ +{ + "mockBidRequest": { + "id": "abc", + "site": { + "page": "prebid.org" + }, + "imp": [ + { + "id": "imp123", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ], + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "pub_id": "test", + "zone_id": "N4zTDq3PPEHBIODv7cXKz", + "force_bid": false + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://market-east.smrtb.com/json/publisher/rtb?pubid=test", + "body":{ + "id": "abc", + "site": { + "page": "prebid.org" + }, + "imp": [{ + "id": "imp123", + "tagid": "N4zTDq3PPEHBIODv7cXKz", + "banner": { + "format": [{ + "w": 300, + "h": 250 + }], + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "pub_id": "test", + "zone_id": "N4zTDq3PPEHBIODv7cXKz", + "force_bid": false + } + } + }], + "ext": { + "pub_id": "test" + } + } + }, + "mockResponse": { + "status": 500 + } + } + ], + + "expectedMakeBidsErrors": [ + { + "value": "Unexpected HTTP status 500.", + "comparison": "literal" + } + ] +} diff --git a/adapters/smartrtb/usersync.go b/adapters/smartrtb/usersync.go new file mode 100644 index 00000000000..2f7b1dc3339 --- /dev/null +++ b/adapters/smartrtb/usersync.go @@ -0,0 +1,12 @@ +package smartrtb + +import ( + "text/template" + + "github.com/prebid/prebid-server/adapters" + "github.com/prebid/prebid-server/usersync" +) + +func NewSmartRTBSyncer(temp *template.Template) usersync.Usersyncer { + return adapters.NewSyncer("smartrtb", 0, temp, adapters.SyncTypeRedirect) +} diff --git a/adapters/smartrtb/usersync_test.go b/adapters/smartrtb/usersync_test.go new file mode 100644 index 00000000000..ae3ae5dc007 --- /dev/null +++ b/adapters/smartrtb/usersync_test.go @@ -0,0 +1,20 @@ +package smartrtb + +import ( + "testing" + "text/template" + + "github.com/prebid/prebid-server/privacy" + "github.com/stretchr/testify/assert" +) + +func TestSmartRTBSyncer(t *testing.T) { + temp := template.Must(template.New("sync-template").Parse("http://market-east.smrtb.com/sync/all?nid=smartrtb&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&url=localhost%2Fsetuid%3Fbidder%smartrtb%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7BUID%7D")) + syncer := NewSmartRTBSyncer(temp) + syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{}) + assert.NoError(t, err) + assert.Equal(t, "http://market-east.smrtb.com/sync/all?nid=smartrtb&gdpr=&gdpr_consent=&url=localhost%2Fsetuid%3Fbidder%smartrtb%26gdpr%3D%26gdpr_consent%3D%26uid%3D%24%7BUID%7D", syncInfo.URL) + assert.Equal(t, "redirect", syncInfo.Type) + assert.EqualValues(t, 0, syncer.GDPRVendorID()) + assert.Equal(t, false, syncInfo.SupportCORS) +} diff --git a/adapters/synacormedia/params_test.go b/adapters/synacormedia/params_test.go index ffd891f4e84..a216818e382 100644 --- a/adapters/synacormedia/params_test.go +++ b/adapters/synacormedia/params_test.go @@ -40,9 +40,9 @@ func TestInvalidParams(t *testing.T) { } var validParams = []string{ - `{"seatId": "123"}`, + `{"seatId": "123", "tagId":"234"}`, } var invalidParams = []string{ - `{"seatId": 123}`, + `{"seatId": 123, "tagId":234}`, } diff --git a/adapters/synacormedia/synacormedia.go b/adapters/synacormedia/synacormedia.go index ccb2798f8cf..2d913f026b4 100644 --- a/adapters/synacormedia/synacormedia.go +++ b/adapters/synacormedia/synacormedia.go @@ -20,6 +20,7 @@ type SynacorMediaAdapter struct { type SyncEndpointTemplateParams struct { SeatId string + TagId string } type ReqExt struct { @@ -55,14 +56,23 @@ func (a *SynacorMediaAdapter) makeRequest(request *openrtb.BidRequest) (*adapter var firstExtImp *openrtb_ext.ExtImpSynacormedia = nil for _, imp := range request.Imp { - validImp, err := getExtImpObj(&imp) + validExtImpObj, err := getExtImpObj(&imp) // getExtImpObj returns {seatId:"", tagId:""} if err != nil { errs = append(errs, err) continue } + // if the bid request is missing seatId or TagId then ignore it + if validExtImpObj.SeatId == "" || validExtImpObj.TagId == "" { + errs = append(errs, &errortypes.BadServerResponse{ + Message: fmt.Sprintf("Invalid Impression"), + }) + continue + } + // right here is where we need to take out the tagId and then add it to imp + imp.TagID = validExtImpObj.TagId validImps = append(validImps, imp) if firstExtImp == nil { - firstExtImp = validImp + firstExtImp = validExtImpObj } } @@ -72,11 +82,12 @@ func (a *SynacorMediaAdapter) makeRequest(request *openrtb.BidRequest) (*adapter var err error - if firstExtImp == nil || firstExtImp.SeatId == "" { + if firstExtImp == nil || firstExtImp.SeatId == "" || firstExtImp.TagId == "" { return nil, append(errs, &errortypes.BadServerResponse{ - Message: fmt.Sprintf("Impression missing seat id"), + Message: fmt.Sprintf("Invalid Impression"), }) } + // this is where the empty seatId is filled re = &ReqExt{SeatId: firstExtImp.SeatId} // create JSON Request Body diff --git a/adapters/synacormedia/synacormediatest/exemplary/simple-banner.json b/adapters/synacormedia/synacormediatest/exemplary/simple-banner.json index 013891b6fa8..944e6e549ab 100644 --- a/adapters/synacormedia/synacormediatest/exemplary/simple-banner.json +++ b/adapters/synacormedia/synacormediatest/exemplary/simple-banner.json @@ -14,7 +14,8 @@ }, "ext": { "bidder": { - "seatId": "1927" + "seatId": "prebid", + "tagId": "demo1" } } } @@ -24,15 +25,16 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://1927.technoratimedia.com/openrtb/bids/1927", + "uri": "http://prebid.technoratimedia.com/openrtb/bids/prebid", "body": { "id": "test-request-id", "ext": { - "seatId": "1927" + "seatId": "prebid" }, "imp": [ { "id":"test-imp-id", + "tagid": "demo1", "banner": { "format": [ {"w":300,"h":250} @@ -40,7 +42,8 @@ }, "ext": { "bidder": { - "seatId": "1927" + "seatId": "prebid", + "tagId": "demo1" } } } diff --git a/adapters/synacormedia/synacormediatest/exemplary/simple-video.json b/adapters/synacormedia/synacormediatest/exemplary/simple-video.json index f12556105db..2cddd5220f9 100644 --- a/adapters/synacormedia/synacormediatest/exemplary/simple-video.json +++ b/adapters/synacormedia/synacormediatest/exemplary/simple-video.json @@ -10,7 +10,6 @@ "imp": [ { "id": "i3", - "tagid": "3020", "video": { "w": 300, "h": 250, @@ -21,8 +20,9 @@ }, "metric": [], "ext": { - "bidder":{ - "seatId":"1927" + "bidder": { + "seatId":"prebid", + "tagId": "demo1" } } } @@ -31,7 +31,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://1927.technoratimedia.com/openrtb/bids/1927", + "uri": "http://prebid.technoratimedia.com/openrtb/bids/prebid", "body": { "id": "1", "site": { @@ -40,12 +40,12 @@ "publisher": {} }, "ext": { - "seatId": "1927" + "seatId": "prebid" }, "imp": [ { "id": "i3", - "tagid": "3020", + "tagid": "demo1", "video": { "w": 300, "h": 250, @@ -56,7 +56,8 @@ }, "ext": { "bidder":{ - "seatId":"1927" + "seatId":"prebid", + "tagId": "demo1" } } } diff --git a/adapters/synacormedia/synacormediatest/params/banner.json b/adapters/synacormedia/synacormediatest/params/banner.json index d6f4e7e9641..bb55ddfc48c 100644 --- a/adapters/synacormedia/synacormediatest/params/banner.json +++ b/adapters/synacormedia/synacormediatest/params/banner.json @@ -1,3 +1,4 @@ { - "seatId": "123" + "seatId": "123", + "tagId": "234" } diff --git a/adapters/synacormedia/synacormediatest/params/video.json b/adapters/synacormedia/synacormediatest/params/video.json index d6f4e7e9641..bb55ddfc48c 100644 --- a/adapters/synacormedia/synacormediatest/params/video.json +++ b/adapters/synacormedia/synacormediatest/params/video.json @@ -1,3 +1,4 @@ { - "seatId": "123" + "seatId": "123", + "tagId": "234" } diff --git a/adapters/synacormedia/synacormediatest/supplemental/audio_response.json b/adapters/synacormedia/synacormediatest/supplemental/audio_response.json index 172a81efa85..752d610aa72 100644 --- a/adapters/synacormedia/synacormediatest/supplemental/audio_response.json +++ b/adapters/synacormedia/synacormediatest/supplemental/audio_response.json @@ -9,7 +9,8 @@ }, "ext": { "bidder": { - "seatId": "1927" + "seatId": "prebid", + "tagId": "demo1" } } } @@ -19,21 +20,23 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://1927.technoratimedia.com/openrtb/bids/1927", + "uri": "http://prebid.technoratimedia.com/openrtb/bids/prebid", "body": { "id": "test-request-id", "ext": { - "seatId": "1927" + "seatId": "prebid" }, "imp": [ { "id":"test-imp-id", + "tagid": "demo1", "audio": { "mimes": ["video/mp4"] }, "ext": { "bidder": { - "seatId": "1927" + "seatId": "prebid", + "tagId": "demo1" } } } diff --git a/adapters/synacormedia/synacormediatest/supplemental/bad_response.json b/adapters/synacormedia/synacormediatest/supplemental/bad_response.json index 0893598bd1d..8e8b9a4d944 100644 --- a/adapters/synacormedia/synacormediatest/supplemental/bad_response.json +++ b/adapters/synacormedia/synacormediatest/supplemental/bad_response.json @@ -18,7 +18,8 @@ }, "ext": { "bidder": { - "seatId": "1927" + "seatId": "prebid", + "tagId": "demo1" } } } @@ -28,15 +29,16 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://1927.technoratimedia.com/openrtb/bids/1927", + "uri": "http://prebid.technoratimedia.com/openrtb/bids/prebid", "body": { "id": "test-request-id", "ext": { - "seatId": "1927" + "seatId": "prebid" }, "imp": [ { "id":"test-imp-id", + "tagid": "demo1", "banner": { "format": [ {"w":300,"h":250}, @@ -45,7 +47,8 @@ }, "ext": { "bidder": { - "seatId": "1927" + "seatId": "prebid", + "tagId": "demo1" } } } diff --git a/adapters/synacormedia/synacormediatest/supplemental/bad_seat_id.json b/adapters/synacormedia/synacormediatest/supplemental/bad_seat_id.json index bb144f1c6db..00dd2c23707 100644 --- a/adapters/synacormedia/synacormediatest/supplemental/bad_seat_id.json +++ b/adapters/synacormedia/synacormediatest/supplemental/bad_seat_id.json @@ -14,7 +14,8 @@ }, "ext": { "bidder": { - "seatId": 1927 + "seatId": 1927, + "tagId": "demo1" } } } diff --git a/adapters/synacormedia/synacormediatest/supplemental/missing_seat_id.json b/adapters/synacormedia/synacormediatest/supplemental/missing_seat_id.json index a085b6e64f9..b85b88e4189 100644 --- a/adapters/synacormedia/synacormediatest/supplemental/missing_seat_id.json +++ b/adapters/synacormedia/synacormediatest/supplemental/missing_seat_id.json @@ -14,6 +14,7 @@ }, "ext": { "bidder": { + "tagId": "demo1" } } } @@ -22,7 +23,7 @@ "expectedMakeRequestsErrors": [ { - "value": "Impression missing seat id", + "value": "Invalid Impression", "comparison": "literal" } ] diff --git a/adapters/synacormedia/synacormediatest/supplemental/missing_tag_id.json b/adapters/synacormedia/synacormediatest/supplemental/missing_tag_id.json new file mode 100644 index 00000000000..2e1ef6ada65 --- /dev/null +++ b/adapters/synacormedia/synacormediatest/supplemental/missing_tag_id.json @@ -0,0 +1,30 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "seatId": "prebid" + } + } + } + ] + }, + + "expectedMakeRequestsErrors": [ + { + "value": "Invalid Impression", + "comparison": "literal" + } + ] +} diff --git a/adapters/synacormedia/synacormediatest/supplemental/native_response.json b/adapters/synacormedia/synacormediatest/supplemental/native_response.json index 89742d6e0df..1428ac1ccd3 100644 --- a/adapters/synacormedia/synacormediatest/supplemental/native_response.json +++ b/adapters/synacormedia/synacormediatest/supplemental/native_response.json @@ -9,7 +9,8 @@ }, "ext": { "bidder": { - "seatId": "1927" + "seatId": "prebid", + "tagId": "demo1" } } } @@ -19,21 +20,23 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://1927.technoratimedia.com/openrtb/bids/1927", + "uri": "http://prebid.technoratimedia.com/openrtb/bids/prebid", "body": { "id": "test-request-id", "ext": { - "seatId": "1927" + "seatId": "prebid" }, "imp": [ { "id":"test-imp-id", + "tagid": "demo1", "native": { "request": "" }, "ext": { "bidder": { - "seatId": "1927" + "seatId": "prebid", + "tagId": "demo1" } } } diff --git a/adapters/synacormedia/synacormediatest/supplemental/one_bad_ext.json b/adapters/synacormedia/synacormediatest/supplemental/one_bad_ext.json new file mode 100644 index 00000000000..5749aadba98 --- /dev/null +++ b/adapters/synacormedia/synacormediatest/supplemental/one_bad_ext.json @@ -0,0 +1,136 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-bad", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "seatId": "", + "tagId": "" + } + } + }, + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "seatId": "prebid", + "tagId": "demo1" + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://prebid.technoratimedia.com/openrtb/bids/prebid", + "body": { + "id": "test-request-id", + "ext": { + "seatId": "prebid" + }, + "imp": [ + { + "id":"test-imp-id", + "tagid": "demo1", + "banner": { + "format": [ + {"w":300,"h":250} + ] + }, + "ext": { + "bidder": { + "seatId": "prebid", + "tagId": "demo1" + } + } + } + ] + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "1", + "seatbid": [ + { + "bid": [ + { + "id": "test-request-id", + "impid": "test-imp-id", + "price": 2.69, + "adomain": [ + "psacentral.org" + ], + "cid": "mock-crid", + "crid": "mock-cid", + "ext": { + "prebid": { + "type": "banner" + } + } + } + ], + "seat": "synacormedia" + } + ], + "ext": { + "responsetimemillis": { + "synacormedia": 339 + } + } + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "adomain": [ + "psacentral.org" + ], + "cid": "mock-crid", + "crid": "mock-cid", + "ext": { + "prebid": { + "type": "banner" + } + }, + "id": "test-request-id", + "impid": "test-imp-id", + "price": 2.69 + }, + "type": "banner" + } + ] + } + ], + "expectedMakeRequestsErrors": [ + { + "value": "Invalid Impression", + "comparison": "literal" + } + ] +} diff --git a/adapters/synacormedia/synacormediatest/supplemental/status_204.json b/adapters/synacormedia/synacormediatest/supplemental/status_204.json index f53ff1ec918..76f97f9cdfa 100644 --- a/adapters/synacormedia/synacormediatest/supplemental/status_204.json +++ b/adapters/synacormedia/synacormediatest/supplemental/status_204.json @@ -18,7 +18,8 @@ }, "ext": { "bidder": { - "seatId": "1927" + "seatId": "prebid", + "tagId": "demo1" } } } @@ -28,15 +29,16 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://1927.technoratimedia.com/openrtb/bids/1927", + "uri": "http://prebid.technoratimedia.com/openrtb/bids/prebid", "body": { "id": "test-request-id", "ext": { - "seatId": "1927" + "seatId": "prebid" }, "imp": [ { "id":"test-imp-id", + "tagid": "demo1", "banner": { "format": [ {"w":300,"h":250}, @@ -45,7 +47,8 @@ }, "ext": { "bidder": { - "seatId": "1927" + "seatId": "prebid", + "tagId": "demo1" } } } diff --git a/adapters/synacormedia/synacormediatest/supplemental/status_400.json b/adapters/synacormedia/synacormediatest/supplemental/status_400.json index a0667658e1d..1bb2cf6fa45 100644 --- a/adapters/synacormedia/synacormediatest/supplemental/status_400.json +++ b/adapters/synacormedia/synacormediatest/supplemental/status_400.json @@ -18,7 +18,8 @@ }, "ext": { "bidder": { - "seatId": "1927" + "seatId": "prebid", + "tagId": "demo1" } } } @@ -28,15 +29,16 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://1927.technoratimedia.com/openrtb/bids/1927", + "uri": "http://prebid.technoratimedia.com/openrtb/bids/prebid", "body": { "id": "test-request-id", "ext": { - "seatId": "1927" + "seatId": "prebid" }, "imp": [ { "id":"test-imp-id", + "tagid": "demo1", "banner": { "format": [ {"w":300,"h":250}, @@ -45,7 +47,8 @@ }, "ext": { "bidder": { - "seatId": "1927" + "seatId": "prebid", + "tagId": "demo1" } } } diff --git a/adapters/synacormedia/synacormediatest/supplemental/status_500.json b/adapters/synacormedia/synacormediatest/supplemental/status_500.json index 125829c2328..37ca398e59e 100644 --- a/adapters/synacormedia/synacormediatest/supplemental/status_500.json +++ b/adapters/synacormedia/synacormediatest/supplemental/status_500.json @@ -18,7 +18,8 @@ }, "ext": { "bidder": { - "seatId": "1927" + "seatId": "prebid", + "tagId": "demo1" } } } @@ -28,15 +29,16 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://1927.technoratimedia.com/openrtb/bids/1927", + "uri": "http://prebid.technoratimedia.com/openrtb/bids/prebid", "body": { "id": "test-request-id", "ext": { - "seatId": "1927" + "seatId": "prebid" }, "imp": [ { "id":"test-imp-id", + "tagid": "demo1", "banner": { "format": [ {"w":300,"h":250}, @@ -45,7 +47,8 @@ }, "ext": { "bidder": { - "seatId": "1927" + "seatId": "prebid", + "tagId": "demo1" } } } diff --git a/adapters/triplelift/usersync_test.go b/adapters/triplelift/usersync_test.go index b4bc845915b..1731b22dffb 100644 --- a/adapters/triplelift/usersync_test.go +++ b/adapters/triplelift/usersync_test.go @@ -9,7 +9,7 @@ import ( ) func TestTripleliftSyncer(t *testing.T) { - syncURL := "//eb2.3lift.com/getuid?gdpr={{.GDPR}}&cmp_cs={{.GDPRConsent}}&redir=https%3A%2F%2Feb2.3lift.com%2Fsetuid%3Fbidder%3Dtriplelift%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID" + syncURL := "//eb2.3lift.com/getuid?gdpr={{.GDPR}}&cmp_cs={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir=https%3A%2F%2Feb2.3lift.com%2Fsetuid%3Fbidder%3Dtriplelift%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID" syncURLTemplate := template.Must( template.New("sync-template").Parse(syncURL), ) @@ -18,7 +18,7 @@ func TestTripleliftSyncer(t *testing.T) { syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{}) assert.NoError(t, err) - assert.Equal(t, "//eb2.3lift.com/getuid?gdpr=&cmp_cs=&redir=https%3A%2F%2Feb2.3lift.com%2Fsetuid%3Fbidder%3Dtriplelift%26gdpr%3D%26gdpr_consent%3D%26uid%3D%24UID", syncInfo.URL) + assert.Equal(t, "//eb2.3lift.com/getuid?gdpr=&cmp_cs=&us_privacy=&redir=https%3A%2F%2Feb2.3lift.com%2Fsetuid%3Fbidder%3Dtriplelift%26gdpr%3D%26gdpr_consent%3D%26uid%3D%24UID", syncInfo.URL) assert.Equal(t, "redirect", syncInfo.Type) assert.EqualValues(t, 28, syncer.GDPRVendorID()) assert.Equal(t, false, syncInfo.SupportCORS) diff --git a/adapters/triplelift_native/usersync_test.go b/adapters/triplelift_native/usersync_test.go index 2fb66c2bd2a..df0757edc9f 100644 --- a/adapters/triplelift_native/usersync_test.go +++ b/adapters/triplelift_native/usersync_test.go @@ -9,7 +9,7 @@ import ( ) func TestTripleliftSyncer(t *testing.T) { - syncURL := "//eb2.3lift.com/getuid?gdpr={{.GDPR}}&cmp_cs={{.GDPRConsent}}&redir=https%3A%2F%2Feb2.3lift.com%2Fsetuid%3Fbidder%3Dtriplelift%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID" + syncURL := "//eb2.3lift.com/getuid?gdpr={{.GDPR}}&cmp_cs={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir=https%3A%2F%2Feb2.3lift.com%2Fsetuid%3Fbidder%3Dtriplelift%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID" syncURLTemplate := template.Must( template.New("sync-template").Parse(syncURL), ) @@ -18,7 +18,7 @@ func TestTripleliftSyncer(t *testing.T) { syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{}) assert.NoError(t, err) - assert.Equal(t, "//eb2.3lift.com/getuid?gdpr=&cmp_cs=&redir=https%3A%2F%2Feb2.3lift.com%2Fsetuid%3Fbidder%3Dtriplelift%26gdpr%3D%26gdpr_consent%3D%26uid%3D%24UID", syncInfo.URL) + assert.Equal(t, "//eb2.3lift.com/getuid?gdpr=&cmp_cs=&us_privacy=&redir=https%3A%2F%2Feb2.3lift.com%2Fsetuid%3Fbidder%3Dtriplelift%26gdpr%3D%26gdpr_consent%3D%26uid%3D%24UID", syncInfo.URL) assert.Equal(t, "redirect", syncInfo.Type) assert.EqualValues(t, 28, syncer.GDPRVendorID()) assert.Equal(t, false, syncInfo.SupportCORS) diff --git a/adapters/ucfunnel/params_test.go b/adapters/ucfunnel/params_test.go index 7be1e26e4ce..94c20cfddad 100644 --- a/adapters/ucfunnel/params_test.go +++ b/adapters/ucfunnel/params_test.go @@ -32,7 +32,7 @@ func TestInvalidParams(t *testing.T) { } for _, invalidParam := range invalidParams { - if err := validator.Validate(openrtb_ext.BidderUcfunnel, json.RawMessage(invalidParam)); err == nil { + if err := validator.Validate(openrtb_ext.BidderUcfunnel, json.RawMessage(invalidParam)); err != nil { t.Errorf("Schema allowed unexpected params: %s", invalidParam) } } diff --git a/adapters/ucfunnel/ucfunnel.go b/adapters/ucfunnel/ucfunnel.go index 9c7cd4845d4..e7bb4f97817 100644 --- a/adapters/ucfunnel/ucfunnel.go +++ b/adapters/ucfunnel/ucfunnel.go @@ -11,20 +11,12 @@ import ( ) type UcfunnelAdapter struct { - http *adapters.HTTPAdapter - URI string -} - -func NewUcfunnelAdapter(config *adapters.HTTPAdapterConfig, endpoint string) *UcfunnelAdapter { - return NewUcfunnelBidder(adapters.NewHTTPAdapter(config).Client, endpoint) + URI string } func NewUcfunnelBidder(client *http.Client, endpoint string) *UcfunnelAdapter { - clientAdapter := &adapters.HTTPAdapter{Client: client} return &UcfunnelAdapter{ - http: clientAdapter, - URI: endpoint, - } + URI: endpoint} } func (a *UcfunnelAdapter) Name() string { @@ -67,11 +59,13 @@ func (a *UcfunnelAdapter) MakeBids(internalRequest *openrtb.BidRequest, external for _, sb := range bidResp.SeatBid { for i := range sb.Bid { bidType := getBidType(bidReq, sb.Bid[i].ImpID) - b := &adapters.TypedBid{ - Bid: &sb.Bid[i], - BidType: bidType, + if (bidType == openrtb_ext.BidTypeBanner) || (bidType == openrtb_ext.BidTypeVideo) { + b := &adapters.TypedBid{ + Bid: &sb.Bid[i], + BidType: bidType, + } + bidResponse.Bids = append(bidResponse.Bids, b) } - bidResponse.Bids = append(bidResponse.Bids, b) } } return bidResponse, errs @@ -99,7 +93,7 @@ func (a *UcfunnelAdapter) MakeRequests(request *openrtb.BidRequest, reqInfo *ada headers := http.Header{} headers.Add("Content-Type", "application/json") - uri := a.URI + partnerId + "/request" + uri := a.URI + "/" + partnerId + "/request" return []*adapters.RequestData{{ Method: "POST", Uri: uri, @@ -114,14 +108,11 @@ func getPartnerId(request *openrtb.BidRequest) string { if err != nil { return "" } - return ext.Bidder.PartnerId -} + if len(ext.Bidder.PartnerId) == 0 || len(ext.Bidder.AdUnitId) == 0 { + return "" + } -func AddHeadersToRequest() http.Header { - headers := http.Header{} - headers.Add("Content-Type", "application/json;charset=utf-8") - headers.Add("Accept", "application/json") - return headers + return ext.Bidder.PartnerId } func getBidType(bidReq openrtb.BidRequest, impid string) openrtb_ext.BidType { @@ -131,10 +122,14 @@ func getBidType(bidReq openrtb.BidRequest, impid string) openrtb_ext.BidType { return openrtb_ext.BidTypeBanner } else if bidReq.Imp[i].Video != nil { return openrtb_ext.BidTypeVideo + } else if bidReq.Imp[i].Audio != nil { + return openrtb_ext.BidTypeAudio + } else if bidReq.Imp[i].Native != nil { + return openrtb_ext.BidTypeNative } } } - return openrtb_ext.BidTypeBanner + return openrtb_ext.BidTypeNative } type ExtBidderUcfunnel struct { diff --git a/adapters/ucfunnel/ucfunnel_test.go b/adapters/ucfunnel/ucfunnel_test.go index f4e8b1befab..6fc369fa3c7 100644 --- a/adapters/ucfunnel/ucfunnel_test.go +++ b/adapters/ucfunnel/ucfunnel_test.go @@ -13,29 +13,13 @@ func TestJsonSamples(t *testing.T) { adapterstest.RunJSONBidderTest(t, "ucfunneltest", NewUcfunnelBidder(nil, "http://127.0.0.1:8081/tmp12.json")) } -func TestAddHeadersToRequest(t *testing.T) { - header := AddHeadersToRequest() - - if header == nil { - t.Errorf("actual = %v expected != %v", nil, nil) - } - - if header.Get("Content-Type") != "application/json;charset=utf-8" { - t.Errorf("actual = %s expected != %v", header.Get("Content-Type"), nil) - } - - if header.Get("Accept") != "application/json" { - t.Errorf("actual = %s expected != %v", header.Get("Accept"), nil) - } -} - func TestUcfunnelAdapterNames(t *testing.T) { - adapter := NewUcfunnelAdapter(adapters.DefaultHTTPAdapterConfig, "http://localhost/bid") + adapter := NewUcfunnelBidder(nil, "http://localhost/bid") adapterstest.VerifyStringValue(adapter.Name(), "ucfunnel", t) } func TestSkipNoCookies(t *testing.T) { - adapter := NewUcfunnelAdapter(adapters.DefaultHTTPAdapterConfig, "http://localhost/bid") + adapter := NewUcfunnelBidder(nil, "http://localhost/bid") status := adapter.SkipNoCookies() if status != false { t.Errorf("actual = %t expected != %t", status, false) @@ -53,23 +37,41 @@ func TestMakeRequests(t *testing.T) { Video: &openrtb.Video{}, } - internalRequest := openrtb.BidRequest{Imp: []openrtb.Imp{imp, imp2}} - adapter := NewUcfunnelAdapter(adapters.DefaultHTTPAdapterConfig, "http://localhost/bid") + imp3 := openrtb.Imp{ + ID: "1236", + Audio: &openrtb.Audio{}, + } + + imp4 := openrtb.Imp{ + ID: "1237", + Native: &openrtb.Native{}, + } + imp5 := openrtb.Imp{ + ID: "1237", + Native: &openrtb.Native{}, + } + internalRequest := openrtb.BidRequest{Imp: []openrtb.Imp{imp, imp2, imp3, imp4, imp5}} + adapter := NewUcfunnelBidder(nil, "http://localhost/bid") RequestData, err := adapter.MakeRequests(&internalRequest, nil) internalRequest.Imp[0].Ext = []byte(`{"bidder": {"adunitid": "ad-488663D474E44841E8A293379892348","partnerid": "par-7E6D2DB9A8922AB07B44A444D2BA67"}}`) internalRequest.Imp[1].Ext = []byte(`{"bidder": {"adunitid": "ad-488663D474E44841E8A293379892348","partnerid": "par-7E6D2DB9A8922AB07B44A444D2BA67"}}`) + internalRequest.Imp[2].Ext = []byte(`{"bidder": {"adunitid": "ad-488663D474E44841E8A293379892348","partnerid": "par-7E6D2DB9A8922AB07B44A444D2BA67"}}`) + internalRequest.Imp[3].Ext = []byte(`{"bidder": {"adunitid": "ad-488663D474E44841E8A293379892348","partnerid": "par-7E6D2DB9A8922AB07B44A444D2BA67"}}`) + internalRequest.Imp[4].Ext = []byte(`{"bidder": {"adunitid": "aa","partnerid": ""}}`) - adapter = NewUcfunnelAdapter(adapters.DefaultHTTPAdapterConfig, "http://localhost/bid") + adapter = NewUcfunnelBidder(nil, "http://localhost/bid") RequestData, err = adapter.MakeRequests(&internalRequest, nil) adapterstest.VerifyStringValue(RequestData[0].Method, "POST", t) - adapterstest.VerifyStringValue(RequestData[0].Uri, adapter.URI+"par-7E6D2DB9A8922AB07B44A444D2BA67/request", t) + adapterstest.VerifyStringValue(RequestData[0].Uri, adapter.URI+"/par-7E6D2DB9A8922AB07B44A444D2BA67/request", t) - mockResponse200 := adapters.ResponseData{StatusCode: 200, Body: json.RawMessage(`{"seatbid":[{"bid":[{"impid":"1234"}]},{"bid":[{"impid":"1235"}]}]}`)} + mockResponse200 := adapters.ResponseData{StatusCode: 200, Body: json.RawMessage(`{"seatbid": [{"bid": [{"impid": "1234"}]},{"bid": [{"impid": "1235"}]},{"bid": [{"impid": "1236"}]},{"bid": [{"impid": "1237"}]}]}`)} mockResponse203 := adapters.ResponseData{StatusCode: 203, Body: json.RawMessage(`{"seatbid":[{"bid":[{"impid":"1234"}]},{"bid":[{"impid":"1235"}]}]}`)} mockResponse204 := adapters.ResponseData{StatusCode: 204, Body: json.RawMessage(`{"seatbid":[{"bid":[{"impid":"1234"}]},{"bid":[{"impid":"1235"}]}]}`)} mockResponse400 := adapters.ResponseData{StatusCode: 400, Body: json.RawMessage(`{"seatbid":[{"bid":[{"impid":"1234"}]},{"bid":[{"impid":"1235"}]}]}`)} + mockResponseError := adapters.ResponseData{StatusCode: 200, Body: json.RawMessage(`{"seatbid":[{"bid":[{"impid":"1236"}]},{"bid":[{"impid":"1237"}]}`)} + BidderResponse200, err := adapter.MakeBids(&internalRequest, RequestData[0], &mockResponse200) if BidderResponse200 != nil && err != nil { t.Errorf("actual = %t expected == %v", err, nil) @@ -87,4 +89,8 @@ func TestMakeRequests(t *testing.T) { t.Errorf("actual = %t expected != %v", err, nil) } + BidderResponseBodyError, err := adapter.MakeBids(&internalRequest, RequestData[0], &mockResponseError) + if BidderResponseBodyError == nil && err == nil { + t.Errorf("actual = %t expected != %v", err, nil) + } } diff --git a/adapters/unruly/usersync_test.go b/adapters/unruly/usersync_test.go index 8db8f75059e..bdab254f370 100644 --- a/adapters/unruly/usersync_test.go +++ b/adapters/unruly/usersync_test.go @@ -5,12 +5,13 @@ import ( "text/template" "github.com/prebid/prebid-server/privacy" + "github.com/prebid/prebid-server/privacy/ccpa" "github.com/prebid/prebid-server/privacy/gdpr" "github.com/stretchr/testify/assert" ) func TestUnrulySyncer(t *testing.T) { - syncURL := "//unrulymedia.com/pixel?redir=external.com%2Fsetuid%3Fbidder%3Dunruly%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID" + syncURL := "https://usermatch.targeting.unrulymedia.com/pbsync?gdpr={{.GDPR}}&consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&rurl=%2Fsetuid%3Fbidder%3Dunruly%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID" syncURLTemplate := template.Must( template.New("sync-template").Parse(syncURL), ) @@ -18,12 +19,16 @@ func TestUnrulySyncer(t *testing.T) { syncer := NewUnrulySyncer(syncURLTemplate) syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{ GDPR: gdpr.Policy{ - Signal: "0", + Signal: "A", + Consent: "B", + }, + CCPA: ccpa.Policy{ + Value: "C", }, }) assert.NoError(t, err) - assert.Equal(t, "//unrulymedia.com/pixel?redir=external.com%2Fsetuid%3Fbidder%3Dunruly%26gdpr%3D0%26gdpr_consent%3D%26uid%3D%24UID", syncInfo.URL) + assert.Equal(t, "https://usermatch.targeting.unrulymedia.com/pbsync?gdpr=A&consent=B&us_privacy=C&rurl=%2Fsetuid%3Fbidder%3Dunruly%26gdpr%3DA%26gdpr_consent%3DB%26uid%3D%24UID", syncInfo.URL) assert.Equal(t, "iframe", syncInfo.Type) assert.EqualValues(t, 162, syncer.GDPRVendorID()) assert.Equal(t, false, syncInfo.SupportCORS) diff --git a/adapters/visx/usersync_test.go b/adapters/visx/usersync_test.go index 9133c5dfcfe..01e80e644c5 100644 --- a/adapters/visx/usersync_test.go +++ b/adapters/visx/usersync_test.go @@ -5,12 +5,13 @@ import ( "text/template" "github.com/prebid/prebid-server/privacy" + "github.com/prebid/prebid-server/privacy/ccpa" "github.com/prebid/prebid-server/privacy/gdpr" "github.com/stretchr/testify/assert" ) func TestVisxSyncer(t *testing.T) { - syncURL := "//not_localhost/synclocalhost%2Fsetuid%3Fbidder%3Dvisx%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7BUUID%7D" + syncURL := "https://t.visx.net/s2s_sync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir=%2Fsetuid%3Fbidder%3Dvisx%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7BUUID%7D" syncURLTemplate := template.Must( template.New("sync-template").Parse(syncURL), ) @@ -18,12 +19,16 @@ func TestVisxSyncer(t *testing.T) { syncer := NewVisxSyncer(syncURLTemplate) syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{ GDPR: gdpr.Policy{ - Signal: "0", + Signal: "A", + Consent: "B", + }, + CCPA: ccpa.Policy{ + Value: "C", }, }) assert.NoError(t, err) - assert.Equal(t, "//not_localhost/synclocalhost%2Fsetuid%3Fbidder%3Dvisx%26gdpr%3D0%26gdpr_consent%3D%26uid%3D%24%7BUUID%7D", syncInfo.URL) + assert.Equal(t, "https://t.visx.net/s2s_sync?gdpr=A&gdpr_consent=B&us_privacy=C&redir=%2Fsetuid%3Fbidder%3Dvisx%26gdpr%3DA%26gdpr_consent%3DB%26uid%3D%24%7BUUID%7D", syncInfo.URL) assert.Equal(t, "redirect", syncInfo.Type) assert.EqualValues(t, 0, syncer.GDPRVendorID()) assert.Equal(t, false, syncInfo.SupportCORS) diff --git a/adapters/yieldmo/usersync.go b/adapters/yieldmo/usersync.go index f853bbb86a5..041e7e8f073 100644 --- a/adapters/yieldmo/usersync.go +++ b/adapters/yieldmo/usersync.go @@ -8,5 +8,5 @@ import ( ) func NewYieldmoSyncer(temp *template.Template) usersync.Usersyncer { - return adapters.NewSyncer("yieldmo", 0, temp, adapters.SyncTypeRedirect) + return adapters.NewSyncer("yieldmo", 173, temp, adapters.SyncTypeRedirect) } diff --git a/adapters/yieldmo/usersync_test.go b/adapters/yieldmo/usersync_test.go index 93ab907f202..598710ec742 100644 --- a/adapters/yieldmo/usersync_test.go +++ b/adapters/yieldmo/usersync_test.go @@ -10,7 +10,7 @@ import ( ) func TestYieldmoSyncer(t *testing.T) { - syncURL := "//ads.yieldmo.com/pbsync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&redirectUri=http%3A%2F%2Flocalhost%2F%2Fsetuid%3Fbidder%3Dyieldmo%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID" + syncURL := "//ads.yieldmo.com/pbsync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirectUri=http%3A%2F%2Flocalhost%2F%2Fsetuid%3Fbidder%3Dyieldmo%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID" syncURLTemplate := template.Must( template.New("sync-template").Parse(syncURL), ) @@ -23,8 +23,8 @@ func TestYieldmoSyncer(t *testing.T) { }) assert.NoError(t, err) - assert.Equal(t, "//ads.yieldmo.com/pbsync?gdpr=0&gdpr_consent=&redirectUri=http%3A%2F%2Flocalhost%2F%2Fsetuid%3Fbidder%3Dyieldmo%26gdpr%3D0%26gdpr_consent%3D%26uid%3D%24UID", syncInfo.URL) + assert.Equal(t, "//ads.yieldmo.com/pbsync?gdpr=0&gdpr_consent=&us_privacy=&redirectUri=http%3A%2F%2Flocalhost%2F%2Fsetuid%3Fbidder%3Dyieldmo%26gdpr%3D0%26gdpr_consent%3D%26uid%3D%24UID", syncInfo.URL) assert.Equal(t, "redirect", syncInfo.Type) - assert.EqualValues(t, 0, syncer.GDPRVendorID()) + assert.EqualValues(t, 173, syncer.GDPRVendorID()) assert.False(t, syncInfo.SupportCORS) } diff --git a/analytics/config/config.go b/analytics/config/config.go index 3073c6ca1aa..7be7c8ecca3 100644 --- a/analytics/config/config.go +++ b/analytics/config/config.go @@ -29,6 +29,12 @@ func (ea enabledAnalytics) LogAuctionObject(ao *analytics.AuctionObject) { } } +func (ea enabledAnalytics) LogVideoObject(vo *analytics.VideoObject) { + for _, module := range ea { + module.LogVideoObject(vo) + } +} + func (ea enabledAnalytics) LogCookieSyncObject(cso *analytics.CookieSyncObject) { for _, module := range ea { module.LogCookieSyncObject(cso) diff --git a/analytics/config/config_test.go b/analytics/config/config_test.go index cb2bb049e11..0fd3ec2019e 100644 --- a/analytics/config/config_test.go +++ b/analytics/config/config_test.go @@ -45,6 +45,11 @@ func TestSampleModule(t *testing.T) { if count != 4 { t.Errorf("PBSAnalyticsModule failed at LogAmpObject") } + + am.LogVideoObject(&analytics.VideoObject{}) + if count != 5 { + t.Errorf("PBSAnalyticsModule failed at LogVideoObject") + } } type sampleModule struct { @@ -53,6 +58,8 @@ type sampleModule struct { func (m *sampleModule) LogAuctionObject(ao *analytics.AuctionObject) { *m.count++ } +func (m *sampleModule) LogVideoObject(vo *analytics.VideoObject) { *m.count++ } + func (m *sampleModule) LogCookieSyncObject(cso *analytics.CookieSyncObject) { *m.count++ } func (m *sampleModule) LogSetUIDObject(so *analytics.SetUIDObject) { *m.count++ } diff --git a/analytics/core.go b/analytics/core.go index 3f16ba64c38..6fd5139fd3d 100644 --- a/analytics/core.go +++ b/analytics/core.go @@ -2,6 +2,7 @@ package analytics import ( "github.com/mxmCherry/openrtb" + "github.com/prebid/prebid-server/openrtb_ext" "github.com/prebid/prebid-server/usersync" ) @@ -15,6 +16,7 @@ import ( type PBSAnalyticsModule interface { LogAuctionObject(*AuctionObject) + LogVideoObject(*VideoObject) LogCookieSyncObject(*CookieSyncObject) LogSetUIDObject(*SetUIDObject) LogAmpObject(*AmpObject) @@ -38,6 +40,16 @@ type AmpObject struct { Origin string } +//Loggable object of a transaction at /openrtb2/video endpoint +type VideoObject struct { + Status int + Errors []error + Request *openrtb.BidRequest + Response *openrtb.BidResponse + VideoRequest *openrtb_ext.BidRequestVideo + VideoResponse *openrtb_ext.BidResponseVideo +} + //Loggable object of a transaction at /setuid type SetUIDObject struct { Status int diff --git a/analytics/filesystem/file_module.go b/analytics/filesystem/file_module.go index b9438763c4b..54d492ad97c 100644 --- a/analytics/filesystem/file_module.go +++ b/analytics/filesystem/file_module.go @@ -14,6 +14,7 @@ type RequestType string const ( COOKIE_SYNC RequestType = "/cookie_sync" AUCTION RequestType = "/openrtb2/auction" + VIDEO RequestType = "/openrtb2/video" SETUID RequestType = "/set_uid" AMP RequestType = "/openrtb2/amp" ) @@ -32,6 +33,15 @@ func (f *FileLogger) LogAuctionObject(ao *analytics.AuctionObject) { f.Logger.Flush() } +//Writes VideoObject to file +func (f *FileLogger) LogVideoObject(vo *analytics.VideoObject) { + //Code to parse the object and log in a way required + var b bytes.Buffer + b.WriteString(jsonifyVideoObject(vo)) + f.Logger.Debug(b.String()) + f.Logger.Flush() +} + //Logs SetUIDObject to file func (f *FileLogger) LogSetUIDObject(so *analytics.SetUIDObject) { //Code to parse the object and log in a way required @@ -98,6 +108,23 @@ func jsonifyAuctionObject(ao *analytics.AuctionObject) string { } } +func jsonifyVideoObject(vo *analytics.VideoObject) string { + type alias analytics.VideoObject + b, err := json.Marshal(&struct { + Type RequestType `json:"type"` + *alias + }{ + Type: VIDEO, + alias: (*alias)(vo), + }) + + if err == nil { + return string(b) + } else { + return fmt.Sprintf("Transactional Logs Error: Video object badly formed %v", err) + } +} + func jsonifyCookieSync(cso *analytics.CookieSyncObject) string { type alias analytics.CookieSyncObject diff --git a/analytics/filesystem/file_module_test.go b/analytics/filesystem/file_module_test.go index 4ec2bb6abaa..6e2d9f6263b 100644 --- a/analytics/filesystem/file_module_test.go +++ b/analytics/filesystem/file_module_test.go @@ -34,6 +34,15 @@ func TestAuctionObject_ToJson(t *testing.T) { } } +func TestVideoObject_ToJson(t *testing.T) { + vo := &analytics.VideoObject{ + Status: http.StatusOK, + } + if voJson := jsonifyVideoObject(vo); strings.Contains(voJson, "Transactional Logs Error") { + t.Fatalf("AuctionObject failed to convert to json") + } +} + func TestSetUIDObject_ToJson(t *testing.T) { so := &analytics.SetUIDObject{ Status: http.StatusOK, @@ -64,6 +73,7 @@ func TestFileLogger_LogObjects(t *testing.T) { defer os.RemoveAll(TEST_DIR) if fl, err := NewFileLogger(TEST_DIR + "//test"); err == nil { fl.LogAuctionObject(&analytics.AuctionObject{}) + fl.LogVideoObject(&analytics.VideoObject{}) fl.LogAmpObject(&analytics.AmpObject{}) fl.LogSetUIDObject(&analytics.SetUIDObject{}) fl.LogCookieSyncObject(&analytics.CookieSyncObject{}) diff --git a/config/config.go b/config/config.go index f7ba40eda01..fae3b522605 100644 --- a/config/config.go +++ b/config/config.go @@ -23,6 +23,7 @@ type Configuration struct { Host string `mapstructure:"host"` Port int `mapstructure:"port"` Client HTTPClient `mapstructure:"http_client"` + CacheClient HTTPClient `mapstructure:"http_client_cache"` AdminPort int `mapstructure:"admin_port"` EnableGzip bool `mapstructure:"enable_gzip"` // StatusResponse is the string which will be returned by the /status endpoint when things are OK. @@ -484,52 +485,54 @@ func (cfg *Configuration) GetCachedAssetURL(uuid string) string { // func (cfg *Configuration) setDerivedDefaults() { externalURL := cfg.ExternalURL - setDefaultUsersync(cfg.Adapters, openrtb_ext.Bidder33Across, "https://ic.tynt.com/r/d?m=xch&rt=html&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&ru="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3D33across%26uid%3D33XUSERID33X&id=zzz000000000002zzz") + setDefaultUsersync(cfg.Adapters, openrtb_ext.Bidder33Across, "https://ic.tynt.com/r/d?m=xch&rt=html&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&ru="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3D33across%26uid%3D33XUSERID33X&id=zzz000000000002zzz") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAdform, "https://cm.adform.net/cookie?redirect_url="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dadform%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID") - setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAdkernel, "https://sync.adkernel.com/user-sync?t=image&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dadkernel%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7BUID%7D") - setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAdkernelAdn, "https://tag.adkernel.com/syncr?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3DadkernelAdn%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7BUID%7D") + setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAdkernel, "https://sync.adkernel.com/user-sync?t=image&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dadkernel%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7BUID%7D") + setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAdkernelAdn, "https://tag.adkernel.com/syncr?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3DadkernelAdn%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7BUID%7D") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAdpone, "https://usersync.adpone.com/csync?redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dadpone%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7Buid%7D") 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.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.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}}&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}}&url="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dbrightroll%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID") - setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderConsumable, "https://e.serverbid.com/udb/9969/match?gdpr={{.GDPR}}&euconsent={{.GDPRConsent}}&redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dconsumable%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D") - setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderConversant, "https://prebid-match.dotomi.com/prebid/match?rurl="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dconversant%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D") - setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderDatablocks, "https://sync.v5prebid.datablocks.net/s2ssync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Ddatablocks%26gdpr%3D%24%7Bgdpr%7D%26gdpr_consent%3D%24%7Bgdpr_consent%7D%26uid%3D%24%7Buid%7D") - setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderEmxDigital, "https://cs.emxdgt.com/um?ssp=pbs&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Demx_digital%26uid%3D%24UID") - setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderEngageBDR, "https://match.bnmla.com/usersync/s2s_sync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dvisx%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7BUUID%7D") + 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") + setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderConsumable, "https://e.serverbid.com/udb/9969/match?gdpr={{.GDPR}}&euconsent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dconsumable%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D") + setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderConversant, "https://prebid-match.dotomi.com/prebid/match/bounce/current?rurl="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dconversant%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26networkId%3D72582%26version%3D1%26uid%3D") + setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderCpmstar, "https://server.cpmstar.com/usersync.aspx?gdpr={{.GDPR}}&consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dcpmstar%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID") + setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderDatablocks, "https://sync.v5prebid.datablocks.net/s2ssync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Ddatablocks%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7Buid%7D") + setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderEmxDigital, "https://cs.emxdgt.com/um?ssp=pbs&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Demx_digital%26uid%3D%24UID") + setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderEngageBDR, "https://match.bnmla.com/usersync/s2s_sync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dengagebdr%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7BUUID%7D") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderEPlanning, "https://ads.us.e-planning.net/uspd/1/?du=https%3A%2F%2Fads.us.e-planning.net%2Fgetuid%2F1%2F5a1ad71d2d53a0f5%3F"+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Deplanning%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID") // openrtb_ext.BidderFacebook doesn't have a good default. // openrtb_ext.BidderGamma doesn't have a good default. setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderGamoshi, "https://rtb.gamoshi.io/user_sync_prebid?gdpr={{.GDPR}}&consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&rurl="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dgamoshi%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%5Bgusr%5D") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderGrid, "https://x.bidswitch.net/check_uuid/"+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dgrid%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7BBSW_UUID%7D?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}") - setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderGumGum, "https://rtb.gumgum.com/usync/prbds2s?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dgumgum%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D") - setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderImprovedigital, "https://ad.360yield.com/server_match?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dimprovedigital%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7BPUB_USER_ID%7D") + setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderGumGum, "https://rtb.gumgum.com/usync/prbds2s?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dgumgum%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D") + setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderImprovedigital, "https://ad.360yield.com/server_match?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dimprovedigital%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7BPUB_USER_ID%7D") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderIx, "https://ssum.casalemedia.com/usermatchredir?s=184932&cb="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dix%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderLifestreet, "https://ads.lfstmedia.com/idsync/137062?synced=1&ttl=1s&rurl="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dlifestreet%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%24visitor_cookie%24%24") - setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderLockerDome, "https://lockerdome.com/usync/prebidserver?pid="+cfg.Adapters["lockerdome"].PlatformID+"&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dlockerdome%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7B%7Buid%7D%7D") - setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderMarsmedia, "https://dmp.rtbsrv.com/dmp/profiles/cm?p_id=179&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dmarsmedia%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7BUUID%7D") + setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderLockerDome, "https://lockerdome.com/usync/prebidserver?pid="+cfg.Adapters["lockerdome"].PlatformID+"&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dlockerdome%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7B%7Buid%7D%7D") + setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderMarsmedia, "https://dmp.rtbsrv.com/dmp/profiles/cm?p_id=179&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dmarsmedia%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7BUUID%7D") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderMgid, "https://cm.mgid.com/m?cdsp=363893&adu="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dmgid%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7Bmuidn%7D") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderOpenx, "https://rtb.openx.net/sync/prebid?r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dopenx%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7BUID%7D") - setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderPubmatic, "https://ads.pubmatic.com/AdServer/js/user_sync.html?predirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dpubmatic%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D") + setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderPubmatic, "https://ads.pubmatic.com/AdServer/js/user_sync.html?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&predirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dpubmatic%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderPulsepoint, "https://bh.contextweb.com/rtset?pid=561205&ev=1&rurl="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dpulsepoint%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%25%25VGUID%25%25") - setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderRhythmone, "https://sync.1rx.io/usersync2/rmphb?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Drhythmone%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%5BRX_UUID%5D") + setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderRhythmone, "https://sync.1rx.io/usersync2/rmphb?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Drhythmone%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%5BRX_UUID%5D") // openrtb_ext.BidderRTBHouse doesn't have a good default. // openrtb_ext.BidderRubicon doesn't have a good default. setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderSharethrough, "https://match.sharethrough.com/FGMrCMMc/v1?redirectUri="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dsharethrough%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID") + setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderSmartRTB, "https://market-global.smrtb.com/sync/all?nid=smartrtb&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&rr="+url.QueryEscape(externalURL)+"%252Fsetuid%253Fbidder%253Dsmartrtb%2526gdpr%253D{{.GDPR}}%2526gdpr_consent%253D{{.GDPRConsent}}%2526uid%253D%257BXID%257D") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderSomoaudience, "https://publisher-east.mobileadtrading.com/usersync?ru="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dsomoaudience%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7BUID%7D") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderSonobi, "https://sync.go.sonobi.com/us.gif?loc="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dsonobi%26consent_string%3D{{.GDPR}}%26gdpr%3D{{.GDPRConsent}}%26uid%3D%5BUID%5D") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderSovrn, "https://ap.lijit.com/pixel?redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dsovrn%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderSynacormedia, "https://sync.technoratimedia.com/services?srv=cs&pid=70&cb="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dsynacormedia%26uid%3D%5BUSER_ID%5D") // openrtb_ext.BidderTappx doesn't have a good default. - setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderTriplelift, "https://eb2.3lift.com/getuid?gpdr={{.GDPR}}&cmp_cs={{.GDPRConsent}}&redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dtriplelift%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID") - setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderTripleliftNative, "https://eb2.3lift.com/sync?gpdr={{.GDPR}}&cmp_cs={{.GDPRConsent}}") + setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderTriplelift, "https://eb2.3lift.com/getuid?gdpr={{.GDPR}}&cmp_cs={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dtriplelift%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID") + setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderTripleliftNative, "https://eb2.3lift.com/getuid?gdpr={{.GDPR}}&cmp_cs={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dtriplelift_native%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderUcfunnel, "https://sync.aralego.com/idsync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&usprivacy={{.USPrivacy}}&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Ducfunnel%26uid%3DSspCookieUserId") - setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderUnruly, "https://usermatch.targeting.unrulymedia.com/pbsync?gdpr={{.GDPR}}&consent={{.GDPRConsent}}&rurl="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dunruly%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID") - setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderVisx, "https://t.visx.net/s2s_sync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dvisx%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7BUUID%7D") + setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderUnruly, "https://usermatch.targeting.unrulymedia.com/pbsync?gdpr={{.GDPR}}&consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&rurl="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dunruly%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID") + setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderVisx, "https://t.visx.net/s2s_sync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dvisx%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7BUUID%7D") // openrtb_ext.BidderVrtcal doesn't have a good default. - setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderYieldmo, "https://ads.yieldmo.com/pbsync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&redirectUri="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dyieldmo%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID") + setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderYieldmo, "https://ads.yieldmo.com/pbsync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirectUri="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dyieldmo%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID") } func setDefaultUsersync(m map[string]Adapter, bidder openrtb_ext.BidderName, defaultValue string) { @@ -582,6 +585,9 @@ func SetupViper(v *viper.Viper, filename string) { v.SetDefault("http_client.max_idle_connections", 400) v.SetDefault("http_client.max_idle_connections_per_host", 10) v.SetDefault("http_client.idle_connection_timeout_seconds", 60) + v.SetDefault("http_client_cache.max_idle_connections", 10) + v.SetDefault("http_client_cache.max_idle_connections_per_host", 2) + v.SetDefault("http_client_cache.idle_connection_timeout_seconds", 60) // no metrics configured by default (metrics{host|database|username|password}) v.SetDefault("metrics.disabled_metrics.account_adapter_details", false) v.SetDefault("metrics.influxdb.host", "") @@ -671,16 +677,18 @@ 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.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") v.SetDefault("adapters.beachfront.endpoint", "https://display.bfmio.com/prebid_display") v.SetDefault("adapters.brightroll.endpoint", "http://east-bid.ybp.yahoo.com/bid/appnexuspbs") v.SetDefault("adapters.consumable.endpoint", "https://e.serverbid.com/api/v2") v.SetDefault("adapters.conversant.endpoint", "http://api.hb.ad.cpe.dotomi.com/s2s/header/24") + v.SetDefault("adapters.cpmstar.endpoint", "https://server.cpmstar.com/openrtbbidrq.aspx") v.SetDefault("adapters.datablocks.endpoint", "http://{{.Host}}/openrtb2?sid={{.SourceId}}") v.SetDefault("adapters.emx_digital.endpoint", "https://hb.emxdgt.com") v.SetDefault("adapters.engagebdr.endpoint", "http://dsp.bnmla.com/hb") - v.SetDefault("adapters.eplanning.endpoint", "http://ads.us.e-planning.net/hb/1") + v.SetDefault("adapters.eplanning.endpoint", "https://ads.us.e-planning.net/hb/1") v.SetDefault("adapters.gamma.endpoint", "https://hb.gammaplatform.com/adx/request/") v.SetDefault("adapters.gamoshi.endpoint", "https://rtb.gamoshi.io") v.SetDefault("adapters.grid.endpoint", "http://grid.bidswitch.net/sp_bid?sp=prebid") @@ -693,13 +701,14 @@ func SetupViper(v *viper.Viper, filename string) { v.SetDefault("adapters.marsmedia.endpoint", "https://bid306.rtbsrv.com/bidder/?bid=f3xtet") v.SetDefault("adapters.mgid.endpoint", "https://prebid.mgid.com/prebid/") v.SetDefault("adapters.openx.endpoint", "http://rtb.openx.net/prebid") - v.SetDefault("adapters.pubmatic.endpoint", "http://hbopenbid.pubmatic.com/translator?source=prebid-server") + v.SetDefault("adapters.pubmatic.endpoint", "https://hbopenbid.pubmatic.com/translator?source=prebid-server") v.SetDefault("adapters.pubnative.endpoint", "http://dsp.pubnative.net/bid/v1/request") v.SetDefault("adapters.pulsepoint.endpoint", "http://bid.contextweb.com/header/s/ortb/prebid-s2s") v.SetDefault("adapters.rhythmone.endpoint", "http://tag.1rx.io/rmp") v.SetDefault("adapters.rtbhouse.endpoint", "http://prebidserver-s2s-ams.creativecdn.com/bidder/prebidserver/bids") v.SetDefault("adapters.rubicon.endpoint", "http://exapi-us-east.rubiconproject.com/a/api/exchange.json") v.SetDefault("adapters.sharethrough.endpoint", "http://btlr.sharethrough.com/FGMrCMMc/v1") + v.SetDefault("adapters.smartrtb.endpoint", "http://market-east.smrtb.com/json/publisher/rtb?pubid={{.PublisherID}}") v.SetDefault("adapters.somoaudience.endpoint", "http://publisher-east.mobileadtrading.com/rtb/bid") v.SetDefault("adapters.sonobi.endpoint", "https://apex.go.sonobi.com/prebid?partnerid=71d9d3d8af") v.SetDefault("adapters.sovrn.endpoint", "http://ap.lijit.com/rtb/bid?src=prebid_server") diff --git a/config/config_test.go b/config/config_test.go index cd143c61a5c..78630e071d9 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -27,7 +27,7 @@ func TestDefaults(t *testing.T) { cmpInts(t, "host_cookie.ttl_days", int(cfg.HostCookie.TTL), 90) cmpInts(t, "host_cookie.max_cookie_size_bytes", cfg.HostCookie.MaxCookieSizeBytes, 0) cmpStrings(t, "datacache.type", cfg.DataCache.Type, "dummy") - cmpStrings(t, "adapters.pubmatic.endpoint", cfg.Adapters[string(openrtb_ext.BidderPubmatic)].Endpoint, "http://hbopenbid.pubmatic.com/translator?source=prebid-server") + cmpStrings(t, "adapters.pubmatic.endpoint", cfg.Adapters[string(openrtb_ext.BidderPubmatic)].Endpoint, "https://hbopenbid.pubmatic.com/translator?source=prebid-server") cmpInts(t, "currency_converter.fetch_interval_seconds", cfg.CurrencyConverter.FetchIntervalSeconds, 1800) cmpStrings(t, "currency_converter.fetch_url", cfg.CurrencyConverter.FetchURL, "https://cdn.jsdelivr.net/gh/prebid/currency-file@1/latest.json") cmpBools(t, "account_required", cfg.AccountRequired, false) @@ -68,6 +68,10 @@ http_client: max_idle_connections: 500 max_idle_connections_per_host: 20 idle_connection_timeout_seconds: 30 +http_client_cache: + max_idle_connections: 1 + max_idle_connections_per_host: 2 + idle_connection_timeout_seconds: 3 currency_converter: fetch_url: https://currency.prebid.org fetch_interval_seconds: 1800 @@ -214,6 +218,9 @@ func TestFullConfig(t *testing.T) { cmpInts(t, "http_client.max_idle_connections", cfg.Client.MaxIdleConns, 500) cmpInts(t, "http_client.max_idle_connections_per_host", cfg.Client.MaxIdleConnsPerHost, 20) cmpInts(t, "http_client.idle_connection_timeout_seconds", cfg.Client.IdleConnTimeout, 30) + cmpInts(t, "http_client_cache.max_idle_connections", cfg.CacheClient.MaxIdleConns, 1) + cmpInts(t, "http_client_cache.max_idle_connections_per_host", cfg.CacheClient.MaxIdleConnsPerHost, 2) + cmpInts(t, "http_client_cache.idle_connection_timeout_seconds", cfg.CacheClient.IdleConnTimeout, 3) cmpInts(t, "gdpr.host_vendor_id", cfg.GDPR.HostVendorID, 15) cmpBools(t, "gdpr.usersync_if_ambiguous", cfg.GDPR.UsersyncIfAmbiguous, true) @@ -272,7 +279,7 @@ func TestFullConfig(t *testing.T) { cmpStrings(t, "adapters.brightroll.usersync_url", cfg.Adapters[string(openrtb_ext.BidderBrightroll)].UserSyncURL, "http://test-bh.ybp.yahoo.com/sync/appnexuspbs?gdpr={{.GDPR}}&euconsent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&url=%s") cmpStrings(t, "adapters.adkerneladn.usersync_url", cfg.Adapters[strings.ToLower(string(openrtb_ext.BidderAdkernelAdn))].UserSyncURL, "https://tag.adkernel.com/syncr?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&r=") cmpStrings(t, "adapters.rhythmone.endpoint", cfg.Adapters[string(openrtb_ext.BidderRhythmone)].Endpoint, "http://tag.1rx.io/rmp") - cmpStrings(t, "adapters.rhythmone.usersync_url", cfg.Adapters[string(openrtb_ext.BidderRhythmone)].UserSyncURL, "https://sync.1rx.io/usersync2/rmphb?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&redir=http%3A%2F%2Fprebid-server.prebid.org%2F%2Fsetuid%3Fbidder%3Drhythmone%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%5BRX_UUID%5D") + cmpStrings(t, "adapters.rhythmone.usersync_url", cfg.Adapters[string(openrtb_ext.BidderRhythmone)].UserSyncURL, "https://sync.1rx.io/usersync2/rmphb?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir=http%3A%2F%2Fprebid-server.prebid.org%2F%2Fsetuid%3Fbidder%3Drhythmone%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%5BRX_UUID%5D") cmpBools(t, "account_required", cfg.AccountRequired, true) cmpBools(t, "account_adapter_details", cfg.Metrics.Disabled.AccountAdapterDetails, true) cmpStrings(t, "certificates_file", cfg.PemCertsFile, "/etc/ssl/cert.pem") diff --git a/currencies/rate_converter.go b/currencies/rate_converter.go index 63f09bd3c2e..6c6ed172652 100644 --- a/currencies/rate_converter.go +++ b/currencies/rate_converter.go @@ -172,11 +172,15 @@ func (rc *RateConverter) Rates() Conversions { // GetInfo returns setup information about the converter func (rc *RateConverter) GetInfo() ConverterInfo { + var rates *map[string]map[string]float64 + if rc.Rates() != nil { + rates = rc.Rates().GetRates() + } return converterInfo{ source: rc.syncSourceURL, fetchingInterval: rc.fetchingInterval, lastUpdated: rc.LastUpdated(), - rates: rc.Rates().GetRates(), + rates: rates, } } diff --git a/currencies/rate_converter_test.go b/currencies/rate_converter_test.go index a1807a63ffb..cb5e2a0be54 100644 --- a/currencies/rate_converter_test.go +++ b/currencies/rate_converter_test.go @@ -66,6 +66,7 @@ func TestFetch_Success(t *testing.T) { rates := currencyConverter.Rates() assert.NotNil(t, rates, "Rates() should not return nil") assert.Equal(t, expectedRates, rates, "Rates() doesn't return expected rates") + assert.NotNil(t, currencyConverter.GetInfo(), "GetInfo() should not return nil") } func TestFetch_Fail404(t *testing.T) { @@ -92,6 +93,7 @@ func TestFetch_Fail404(t *testing.T) { assert.Equal(t, 1, len(calledURLs), "sync URL should have been called %d times but was %d", 1, len(calledURLs)) assert.Equal(t, currencyConverter.LastUpdated(), (time.Time{}), "LastUpdated() shouldn't return a time set") assert.Nil(t, currencyConverter.Rates(), "Rates() should return nil") + assert.NotNil(t, currencyConverter.GetInfo(), "GetInfo() should not return nil") } func TestFetch_FailErrorHttpClient(t *testing.T) { @@ -118,6 +120,7 @@ func TestFetch_FailErrorHttpClient(t *testing.T) { assert.Equal(t, 1, len(calledURLs), "sync URL should have been called %d times but was %d", 1, len(calledURLs)) assert.Equal(t, currencyConverter.LastUpdated(), (time.Time{}), "LastUpdated() shouldn't return a time set") assert.Nil(t, currencyConverter.Rates(), "Rates() should return nil") + assert.NotNil(t, currencyConverter.GetInfo(), "GetInfo() should not return nil") } func TestFetch_FailBadSyncURL(t *testing.T) { @@ -134,6 +137,7 @@ func TestFetch_FailBadSyncURL(t *testing.T) { // Verify: assert.Equal(t, currencyConverter.LastUpdated(), (time.Time{}), "LastUpdated() shouldn't return a time set") assert.Nil(t, currencyConverter.Rates(), "Rates() should return nil") + assert.NotNil(t, currencyConverter.GetInfo(), "GetInfo() should not return nil") } func TestFetch_FailBadJSON(t *testing.T) { @@ -174,6 +178,7 @@ func TestFetch_FailBadJSON(t *testing.T) { assert.Equal(t, 1, len(calledURLs), "sync URL should have been called %d times but was %d", 1, len(calledURLs)) assert.Equal(t, currencyConverter.LastUpdated(), (time.Time{}), "LastUpdated() shouldn't return a time set") assert.Nil(t, currencyConverter.Rates(), "Rates() should return nil") + assert.NotNil(t, currencyConverter.GetInfo(), "GetInfo() should not return nil") } func TestFetch_InvalidRemoteResponseContent(t *testing.T) { @@ -201,6 +206,7 @@ func TestFetch_InvalidRemoteResponseContent(t *testing.T) { assert.Equal(t, 1, len(calledURLs), "sync URL should have been called %d times but was %d", 1, len(calledURLs)) assert.Equal(t, currencyConverter.LastUpdated(), (time.Time{}), "LastUpdated() shouldn't return a time set") assert.Nil(t, currencyConverter.Rates(), "Rates() should return nil") + assert.NotNil(t, currencyConverter.GetInfo(), "GetInfo() should not return nil") } func TestInit(t *testing.T) { @@ -264,6 +270,7 @@ func TestInit(t *testing.T) { assert.NotEqual(t, currencyConverter.LastUpdated(), (time.Time{}), "LastUpdated should be set") rates := currencyConverter.Rates() assert.Equal(t, expectedRates, rates, "Conversions.Rates weren't the expected ones") + assert.NotNil(t, currencyConverter.GetInfo(), "GetInfo() should not return nil") if ticksCount == expectedTicks { currencyConverter.StopPeriodicFetching() @@ -361,6 +368,7 @@ func TestInitWithZeroDuration(t *testing.T) { assert.Equal(t, (time.Time{}), currencyConverter.LastUpdated(), "LastUpdated() shouldn't be set") _, ok := currencyConverter.Rates().(*currencies.ConstantRates) assert.True(t, ok, "Rates should be type of `currencies.ConstantRates`") + assert.NotNil(t, currencyConverter.GetInfo(), "GetInfo() should not return nil") } func TestRates(t *testing.T) { @@ -379,6 +387,7 @@ func TestRates(t *testing.T) { {from: "", to: "EUR", expectedRate: 0, hasError: true}, {from: "CNY", to: "", expectedRate: 0, hasError: true}, {from: "", to: "", expectedRate: 0, hasError: true}, + {from: "USD", to: "USD", expectedRate: 1, hasError: false}, } mockedHttpServer := httptest.NewServer(http.HandlerFunc( diff --git a/docs/bidders/smartrtb.md b/docs/bidders/smartrtb.md new file mode 100644 index 00000000000..ffa88f663e8 --- /dev/null +++ b/docs/bidders/smartrtb.md @@ -0,0 +1,39 @@ +# SmartRTB Bidder + +[SmartRTB](https://smrtb.com/) supports the following parameters to be present in the `ext` object of impression requests: + +- "pub_id" type string - Required. Publisher ID assigned to you. +- "zone_id" type string - Optional. Enables mapping for further settings and reporting in the Marketplace UI. +- "force_bid" type bool - Optional. If zone ID is mapped, this may be set to always return fake sample bids (banner, video) + +Please contact us to create a new Smart RTB Marketplace account, and for any assistance in configuration. +You may email info@smrtb.com for inquiries. + +## Test Request + +This sample request is our global test placement and should always return a branded banner bid. + +``` + { + "id": "abc", + "site": { + "page": "prebid.org" + }, + "imp": [{ + "id": "test", + "banner": { + "format": [{ + "w": 300, + "h": 250 + }] + }, + "ext": { + "smartrtb": { + "pub_id": "test", + "zone_id": "N4zTDq3PPEHBIODv7cXK", + "force_bid": true + } + } + }] + } +``` diff --git a/docs/developers/stored-requests.md b/docs/developers/stored-requests.md index 4b54b4e945f..8b7177160c3 100644 --- a/docs/developers/stored-requests.md +++ b/docs/developers/stored-requests.md @@ -34,7 +34,7 @@ Add the file `stored_requests/data/by_id/stored_imps/{id}.json` and populate it }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } @@ -88,7 +88,7 @@ You can also store _part_ of the Imp on the server. For example: }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/amp_auction_test.go b/endpoints/openrtb2/amp_auction_test.go index 0eafaa05b12..c62a6a710d5 100644 --- a/endpoints/openrtb2/amp_auction_test.go +++ b/endpoints/openrtb2/amp_auction_test.go @@ -966,7 +966,7 @@ func getTestBidRequest(nilUser bool, nilExt bool, consentString string, digitrus Imp: []openrtb.Imp{ { ID: "/19968336/header-bid-tag-0", - Ext: json.RawMessage(`{"appnexus": { "placementId":10433394 }}`), + Ext: json.RawMessage(`{"appnexus": { "placementId":12883451 }}`), Banner: &openrtb.Banner{ Format: []openrtb.Format{ { diff --git a/endpoints/openrtb2/auction_benchmark_test.go b/endpoints/openrtb2/auction_benchmark_test.go index 430b0361eb6..93d7575e865 100644 --- a/endpoints/openrtb2/auction_benchmark_test.go +++ b/endpoints/openrtb2/auction_benchmark_test.go @@ -21,7 +21,7 @@ import ( // dummyServer returns the header bidding test ad. This response was scraped from a real appnexus server response. func dummyServer(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(`{"id":"some-request-id","seatbid":[{"bid":[{"id":"4625436751433509010","impid":"my-imp-id","price":0.5,"adm":"\u003cscript type=\"application/javascript\" src=\"http://nym1-ib.adnxs.com/ab?e=wqT_3QKABqAAAwAAAwDWAAUBCM-OiNAFELuV09Pqi86EVRj6t-7QyLin_REqLQkAAAECCOA_EQEHNAAA4D8ZAAAAgOtR4D8hERIAKREJoDDy5vwEOL4HQL4HSAJQ1suTDljhgEhgAGiRQHixhQSAAQGKAQNVU0SSBQbwUpgBrAKgAfoBqAEBsAEAuAECwAEDyAEC0AEA2AEA4AEB8AEAigI6dWYoJ2EnLCA0OTQ0NzIsIDE1MTAwODIzODMpO3VmKCdyJywgMjk2ODExMTAsMh4A8JySAvkBIVR6WGNkQWk2MEljRUVOYkxrdzRZQUNEaGdFZ3dBRGdBUUFSSXZnZFE4dWI4QkZnQVlQX19fXzhQYUFCd0FYZ0JnQUVCaUFFQmtBRUJtQUVCb0FFQnFBRURzQUVBdVFFcGk0aURBQURnUDhFQktZdUlnd0FBNERfSkFTZlJKRUdtbi00XzJRRUFBQUFBQUFEd1AtQUJBUFVCBQ8oSmdDQUtBQ0FMVUMFEARMMAkI8ExNQUNBY2dDQWRBQ0FkZ0NBZUFDQU9nQ0FQZ0NBSUFEQVpBREFKZ0RBYWdEdXRDSEJMb0RDVTVaVFRJNk16STNOdy4umgItITh3aENuZzb8ALg0WUJJSUFRb0FEb0pUbGxOTWpvek1qYzPYAugH4ALH0wHyAhAKBkFEVl9JRBIGNCV1HPICEQoGQ1BHARMcBzE5Nzc5MzMBJwgFQ1AFE_B-ODUxMzU5NIADAYgDAZADAJgDFKADAaoDAMADrALIAwDYAwDgAwDoAwD4AwCABACSBAkvb3BlbnJ0YjKYBACoBACyBAwIABAAGAAgADAAOAC4BADABADIBADSBAlOWU0yOjMyNzfaBAIIAeAEAPAE1suTDogFAZgFAKAF_____wUDXAGqBQ9zb21lLXJlcXVlc3QtaWTABQDJBUmbTPA_0gUJCQAAAAAAAAAA2AUB4AUB\u0026s=61dc0e8770543def5a3a77b4589830d1274b26f1\u0026test=1\u0026pp=${AUCTION_PRICE}\u0026\"\u003e\u003c/script\u003e","adid":"29681110","adomain":["appnexus.com"],"iurl":"http://nym1-ib.adnxs.com/cr?id=29681110","cid":"958","crid":"29681110","w":300,"h":250,"ext":{"bidder":{"appnexus":{"brand_id":1,"auction_id":6127490747252132539,"bidder_id":2}}}}],"seat":"appnexus"}],"ext":{"debug":{"httpcalls":{"appnexus":[{"uri":"http://ib.adnxs.com/openrtb2","requestbody":"{\"id\":\"some-request-id\",\"imp\":[{\"id\":\"my-imp-id\",\"banner\":{\"format\":[{\"w\":300,\"h\":250},{\"w\":300,\"h\":600}]},\"ext\":{\"appnexus\":{\"placement_id\":10433394}}}],\"test\":1,\"tmax\":500}","responsebody":"{\"id\":\"some-request-id\",\"seatbid\":[{\"bid\":[{\"id\":\"4625436751433509010\",\"impid\":\"my-imp-id\",\"price\": 0.500000,\"adid\":\"29681110\",\"adm\":\"\u003cscript type=\\\"application/javascript\\\" src=\\\"http://nym1-ib.adnxs.com/ab?e=wqT_3QKABqAAAwAAAwDWAAUBCM-OiNAFELuV09Pqi86EVRj6t-7QyLin_REqLQkAAAECCOA_EQEHNAAA4D8ZAAAAgOtR4D8hERIAKREJoDDy5vwEOL4HQL4HSAJQ1suTDljhgEhgAGiRQHixhQSAAQGKAQNVU0SSBQbwUpgBrAKgAfoBqAEBsAEAuAECwAEDyAEC0AEA2AEA4AEB8AEAigI6dWYoJ2EnLCA0OTQ0NzIsIDE1MTAwODIzODMpO3VmKCdyJywgMjk2ODExMTAsMh4A8JySAvkBIVR6WGNkQWk2MEljRUVOYkxrdzRZQUNEaGdFZ3dBRGdBUUFSSXZnZFE4dWI4QkZnQVlQX19fXzhQYUFCd0FYZ0JnQUVCaUFFQmtBRUJtQUVCb0FFQnFBRURzQUVBdVFFcGk0aURBQURnUDhFQktZdUlnd0FBNERfSkFTZlJKRUdtbi00XzJRRUFBQUFBQUFEd1AtQUJBUFVCBQ8oSmdDQUtBQ0FMVUMFEARMMAkI8ExNQUNBY2dDQWRBQ0FkZ0NBZUFDQU9nQ0FQZ0NBSUFEQVpBREFKZ0RBYWdEdXRDSEJMb0RDVTVaVFRJNk16STNOdy4umgItITh3aENuZzb8ALg0WUJJSUFRb0FEb0pUbGxOTWpvek1qYzPYAugH4ALH0wHyAhAKBkFEVl9JRBIGNCV1HPICEQoGQ1BHARMcBzE5Nzc5MzMBJwgFQ1AFE_B-ODUxMzU5NIADAYgDAZADAJgDFKADAaoDAMADrALIAwDYAwDgAwDoAwD4AwCABACSBAkvb3BlbnJ0YjKYBACoBACyBAwIABAAGAAgADAAOAC4BADABADIBADSBAlOWU0yOjMyNzfaBAIIAeAEAPAE1suTDogFAZgFAKAF_____wUDXAGqBQ9zb21lLXJlcXVlc3QtaWTABQDJBUmbTPA_0gUJCQAAAAAAAAAA2AUB4AUB\u0026s=61dc0e8770543def5a3a77b4589830d1274b26f1\u0026test=1\u0026pp=${AUCTION_PRICE}\u0026\\\"\u003e\u003c/script\u003e\",\"adomain\":[\"appnexus.com\"],\"iurl\":\"http://nym1-ib.adnxs.com/cr?id=29681110\",\"cid\":\"958\",\"crid\":\"29681110\",\"h\": 250,\"w\": 300,\"ext\":{\"appnexus\":{\"brand_id\": 1,\"auction_id\": 6127490747252132539,\"bidder_id\": 2}}}],\"seat\":\"958\"}],\"bidid\":\"8271358638249766712\",\"cur\":\"USD\"}","status":200}]}},"responsetimemillis":{"appnexus":42}}}`)) + w.Write([]byte(`{"id":"some-request-id","seatbid":[{"bid":[{"id":"4625436751433509010","impid":"my-imp-id","price":0.5,"adm":"\u003cscript type=\"application/javascript\" src=\"http://nym1-ib.adnxs.com/ab?e=wqT_3QKABqAAAwAAAwDWAAUBCM-OiNAFELuV09Pqi86EVRj6t-7QyLin_REqLQkAAAECCOA_EQEHNAAA4D8ZAAAAgOtR4D8hERIAKREJoDDy5vwEOL4HQL4HSAJQ1suTDljhgEhgAGiRQHixhQSAAQGKAQNVU0SSBQbwUpgBrAKgAfoBqAEBsAEAuAECwAEDyAEC0AEA2AEA4AEB8AEAigI6dWYoJ2EnLCA0OTQ0NzIsIDE1MTAwODIzODMpO3VmKCdyJywgMjk2ODExMTAsMh4A8JySAvkBIVR6WGNkQWk2MEljRUVOYkxrdzRZQUNEaGdFZ3dBRGdBUUFSSXZnZFE4dWI4QkZnQVlQX19fXzhQYUFCd0FYZ0JnQUVCaUFFQmtBRUJtQUVCb0FFQnFBRURzQUVBdVFFcGk0aURBQURnUDhFQktZdUlnd0FBNERfSkFTZlJKRUdtbi00XzJRRUFBQUFBQUFEd1AtQUJBUFVCBQ8oSmdDQUtBQ0FMVUMFEARMMAkI8ExNQUNBY2dDQWRBQ0FkZ0NBZUFDQU9nQ0FQZ0NBSUFEQVpBREFKZ0RBYWdEdXRDSEJMb0RDVTVaVFRJNk16STNOdy4umgItITh3aENuZzb8ALg0WUJJSUFRb0FEb0pUbGxOTWpvek1qYzPYAugH4ALH0wHyAhAKBkFEVl9JRBIGNCV1HPICEQoGQ1BHARMcBzE5Nzc5MzMBJwgFQ1AFE_B-ODUxMzU5NIADAYgDAZADAJgDFKADAaoDAMADrALIAwDYAwDgAwDoAwD4AwCABACSBAkvb3BlbnJ0YjKYBACoBACyBAwIABAAGAAgADAAOAC4BADABADIBADSBAlOWU0yOjMyNzfaBAIIAeAEAPAE1suTDogFAZgFAKAF_____wUDXAGqBQ9zb21lLXJlcXVlc3QtaWTABQDJBUmbTPA_0gUJCQAAAAAAAAAA2AUB4AUB\u0026s=61dc0e8770543def5a3a77b4589830d1274b26f1\u0026test=1\u0026pp=${AUCTION_PRICE}\u0026\"\u003e\u003c/script\u003e","adid":"29681110","adomain":["appnexus.com"],"iurl":"http://nym1-ib.adnxs.com/cr?id=29681110","cid":"958","crid":"29681110","w":300,"h":250,"ext":{"bidder":{"appnexus":{"brand_id":1,"auction_id":6127490747252132539,"bidder_id":2}}}}],"seat":"appnexus"}],"ext":{"debug":{"httpcalls":{"appnexus":[{"uri":"http://ib.adnxs.com/openrtb2","requestbody":"{\"id\":\"some-request-id\",\"imp\":[{\"id\":\"my-imp-id\",\"banner\":{\"format\":[{\"w\":300,\"h\":250},{\"w\":300,\"h\":600}]},\"ext\":{\"appnexus\":{\"placement_id\":12883451}}}],\"test\":1,\"tmax\":500}","responsebody":"{\"id\":\"some-request-id\",\"seatbid\":[{\"bid\":[{\"id\":\"4625436751433509010\",\"impid\":\"my-imp-id\",\"price\": 0.500000,\"adid\":\"29681110\",\"adm\":\"\u003cscript type=\\\"application/javascript\\\" src=\\\"http://nym1-ib.adnxs.com/ab?e=wqT_3QKABqAAAwAAAwDWAAUBCM-OiNAFELuV09Pqi86EVRj6t-7QyLin_REqLQkAAAECCOA_EQEHNAAA4D8ZAAAAgOtR4D8hERIAKREJoDDy5vwEOL4HQL4HSAJQ1suTDljhgEhgAGiRQHixhQSAAQGKAQNVU0SSBQbwUpgBrAKgAfoBqAEBsAEAuAECwAEDyAEC0AEA2AEA4AEB8AEAigI6dWYoJ2EnLCA0OTQ0NzIsIDE1MTAwODIzODMpO3VmKCdyJywgMjk2ODExMTAsMh4A8JySAvkBIVR6WGNkQWk2MEljRUVOYkxrdzRZQUNEaGdFZ3dBRGdBUUFSSXZnZFE4dWI4QkZnQVlQX19fXzhQYUFCd0FYZ0JnQUVCaUFFQmtBRUJtQUVCb0FFQnFBRURzQUVBdVFFcGk0aURBQURnUDhFQktZdUlnd0FBNERfSkFTZlJKRUdtbi00XzJRRUFBQUFBQUFEd1AtQUJBUFVCBQ8oSmdDQUtBQ0FMVUMFEARMMAkI8ExNQUNBY2dDQWRBQ0FkZ0NBZUFDQU9nQ0FQZ0NBSUFEQVpBREFKZ0RBYWdEdXRDSEJMb0RDVTVaVFRJNk16STNOdy4umgItITh3aENuZzb8ALg0WUJJSUFRb0FEb0pUbGxOTWpvek1qYzPYAugH4ALH0wHyAhAKBkFEVl9JRBIGNCV1HPICEQoGQ1BHARMcBzE5Nzc5MzMBJwgFQ1AFE_B-ODUxMzU5NIADAYgDAZADAJgDFKADAaoDAMADrALIAwDYAwDgAwDoAwD4AwCABACSBAkvb3BlbnJ0YjKYBACoBACyBAwIABAAGAAgADAAOAC4BADABADIBADSBAlOWU0yOjMyNzfaBAIIAeAEAPAE1suTDogFAZgFAKAF_____wUDXAGqBQ9zb21lLXJlcXVlc3QtaWTABQDJBUmbTPA_0gUJCQAAAAAAAAAA2AUB4AUB\u0026s=61dc0e8770543def5a3a77b4589830d1274b26f1\u0026test=1\u0026pp=${AUCTION_PRICE}\u0026\\\"\u003e\u003c/script\u003e\",\"adomain\":[\"appnexus.com\"],\"iurl\":\"http://nym1-ib.adnxs.com/cr?id=29681110\",\"cid\":\"958\",\"crid\":\"29681110\",\"h\": 250,\"w\": 300,\"ext\":{\"appnexus\":{\"brand_id\": 1,\"auction_id\": 6127490747252132539,\"bidder_id\": 2}}}],\"seat\":\"958\"}],\"bidid\":\"8271358638249766712\",\"cur\":\"USD\"}","status":200}]}},"responsetimemillis":{"appnexus":42}}}`)) } // newDummyRequest returns a request which fetches the header bidding test ad. @@ -45,7 +45,7 @@ func newDummyRequest() *http.Request { }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/auction_test.go b/endpoints/openrtb2/auction_test.go index c1d57e9c297..89f0fa255df 100644 --- a/endpoints/openrtb2/auction_test.go +++ b/endpoints/openrtb2/auction_test.go @@ -88,7 +88,7 @@ func TestExplicitUserId(t *testing.T) { }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } @@ -425,7 +425,7 @@ func buildNativeRequest(t *testing.T, nativeData []byte) []byte { buf := bytes.NewBuffer(nil) buf.WriteString(`{"id":"req-id","site":{"page":"some.page.com"},"tmax":500,"imp":[{"id":"some-imp","native":{"request":`) buf.Write(serialized) - buf.WriteString(`},"ext":{"appnexus":{"placementId":10433394}}}]}`) + buf.WriteString(`},"ext":{"appnexus":{"placementId":12883451}}}]}`) return buf.Bytes() } diff --git a/endpoints/openrtb2/interstitial_test.go b/endpoints/openrtb2/interstitial_test.go index e680478e63e..1c6eb2555db 100644 --- a/endpoints/openrtb2/interstitial_test.go +++ b/endpoints/openrtb2/interstitial_test.go @@ -22,7 +22,7 @@ var request = &openrtb.BidRequest{ }, }, Instl: 1, - Ext: json.RawMessage(`{"appnexus": {"placementId": 10433394}}`), + Ext: json.RawMessage(`{"appnexus": {"placementId": 12883451}}`), }, }, Device: &openrtb.Device{ diff --git a/endpoints/openrtb2/sample-requests/account-required/no-acct.json b/endpoints/openrtb2/sample-requests/account-required/no-acct.json index 4ba8dec52c3..d84d797017d 100644 --- a/endpoints/openrtb2/sample-requests/account-required/no-acct.json +++ b/endpoints/openrtb2/sample-requests/account-required/no-acct.json @@ -28,7 +28,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/account-required/with-acct.json b/endpoints/openrtb2/sample-requests/account-required/with-acct.json index d1ab715cdbe..fb4c6313051 100644 --- a/endpoints/openrtb2/sample-requests/account-required/with-acct.json +++ b/endpoints/openrtb2/sample-requests/account-required/with-acct.json @@ -29,7 +29,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/aliased/simple.json b/endpoints/openrtb2/sample-requests/aliased/simple.json index e656be43ed5..e7f6ba21b83 100644 --- a/endpoints/openrtb2/sample-requests/aliased/simple.json +++ b/endpoints/openrtb2/sample-requests/aliased/simple.json @@ -13,7 +13,7 @@ }, "ext": { "test1": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/aliased/site.json b/endpoints/openrtb2/sample-requests/aliased/site.json index 981b69b5524..cf7e9a77533 100644 --- a/endpoints/openrtb2/sample-requests/aliased/site.json +++ b/endpoints/openrtb2/sample-requests/aliased/site.json @@ -23,10 +23,10 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 }, "test1": { - "placementId": 10433394 + "placementId": 12883451 }, "test2": { "accountId": 1001, diff --git a/endpoints/openrtb2/sample-requests/blacklisted/blacklisted-acct.json b/endpoints/openrtb2/sample-requests/blacklisted/blacklisted-acct.json index 8977480de33..ee04a9464e9 100644 --- a/endpoints/openrtb2/sample-requests/blacklisted/blacklisted-acct.json +++ b/endpoints/openrtb2/sample-requests/blacklisted/blacklisted-acct.json @@ -42,7 +42,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 }, "districtm": { "placementId": 105 diff --git a/endpoints/openrtb2/sample-requests/blacklisted/blacklisted-app.json b/endpoints/openrtb2/sample-requests/blacklisted/blacklisted-app.json index 219595e409a..1ace4b53666 100644 --- a/endpoints/openrtb2/sample-requests/blacklisted/blacklisted-app.json +++ b/endpoints/openrtb2/sample-requests/blacklisted/blacklisted-app.json @@ -39,7 +39,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 }, "districtm": { "placementId": 105 diff --git a/endpoints/openrtb2/sample-requests/disabled/bad/bad-alias.json b/endpoints/openrtb2/sample-requests/disabled/bad/bad-alias.json index 8299f96ce6b..096c028cfe9 100644 --- a/endpoints/openrtb2/sample-requests/disabled/bad/bad-alias.json +++ b/endpoints/openrtb2/sample-requests/disabled/bad/bad-alias.json @@ -15,7 +15,7 @@ }, "ext": { "test1": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/disabled/bad/bad-bidder.json b/endpoints/openrtb2/sample-requests/disabled/bad/bad-bidder.json index f0313824456..1fa21b203e3 100644 --- a/endpoints/openrtb2/sample-requests/disabled/bad/bad-bidder.json +++ b/endpoints/openrtb2/sample-requests/disabled/bad/bad-bidder.json @@ -15,7 +15,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/disabled/good/partial.json b/endpoints/openrtb2/sample-requests/disabled/good/partial.json index 0f6bf1dd005..fe0c492be2d 100644 --- a/endpoints/openrtb2/sample-requests/disabled/good/partial.json +++ b/endpoints/openrtb2/sample-requests/disabled/good/partial.json @@ -23,7 +23,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 }, "rubicon": { "accountId": 1001, diff --git a/endpoints/openrtb2/sample-requests/invalid-stored/bad_incoming_1.json b/endpoints/openrtb2/sample-requests/invalid-stored/bad_incoming_1.json index ccb54c0547e..2a647d7d8c8 100644 --- a/endpoints/openrtb2/sample-requests/invalid-stored/bad_incoming_1.json +++ b/endpoints/openrtb2/sample-requests/invalid-stored/bad_incoming_1.json @@ -24,7 +24,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/invalid-stored/bad_incoming_2.json b/endpoints/openrtb2/sample-requests/invalid-stored/bad_incoming_2.json index 6023f86970e..d18a20d7a13 100644 --- a/endpoints/openrtb2/sample-requests/invalid-stored/bad_incoming_2.json +++ b/endpoints/openrtb2/sample-requests/invalid-stored/bad_incoming_2.json @@ -24,7 +24,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/alias-bidder-self.json b/endpoints/openrtb2/sample-requests/invalid-whole/alias-bidder-self.json index f081b365dd9..666253ec85b 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/alias-bidder-self.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/alias-bidder-self.json @@ -13,7 +13,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/alias-unknown-core.json b/endpoints/openrtb2/sample-requests/invalid-whole/alias-unknown-core.json index acf3bc0dd4f..6c1925d65b1 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/alias-unknown-core.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/alias-unknown-core.json @@ -15,7 +15,7 @@ }, "ext": { "unknown": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/app-bad-ext.json b/endpoints/openrtb2/sample-requests/invalid-whole/app-bad-ext.json index 2516a268754..672b05724c8 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/app-bad-ext.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/app-bad-ext.json @@ -32,7 +32,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/banner-h-only.json b/endpoints/openrtb2/sample-requests/invalid-whole/banner-h-only.json index 7040e8dfc3c..515824e65d9 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/banner-h-only.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/banner-h-only.json @@ -13,7 +13,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/banner-h-zero.json b/endpoints/openrtb2/sample-requests/invalid-whole/banner-h-zero.json index d98cfba100b..f18f63e5e28 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/banner-h-zero.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/banner-h-zero.json @@ -14,7 +14,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/banner-w-only.json b/endpoints/openrtb2/sample-requests/invalid-whole/banner-w-only.json index 52a7bdd2ba2..70739a65834 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/banner-w-only.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/banner-w-only.json @@ -13,7 +13,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/banner-w-zero.json b/endpoints/openrtb2/sample-requests/invalid-whole/banner-w-zero.json index 0b927f26e3c..b3453ab4cb7 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/banner-w-zero.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/banner-w-zero.json @@ -14,7 +14,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/bid-adjustment-invalid-bidder.json b/endpoints/openrtb2/sample-requests/invalid-whole/bid-adjustment-invalid-bidder.json index 985f99126c4..569e16d2d20 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/bid-adjustment-invalid-bidder.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/bid-adjustment-invalid-bidder.json @@ -13,7 +13,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/bid-adjustment-negative.json b/endpoints/openrtb2/sample-requests/invalid-whole/bid-adjustment-negative.json index 984998000c5..4db6ee09bd8 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/bid-adjustment-negative.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/bid-adjustment-negative.json @@ -13,7 +13,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/cache-nothing.json b/endpoints/openrtb2/sample-requests/invalid-whole/cache-nothing.json index 605040c6cfc..d4b875498ae 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/cache-nothing.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/cache-nothing.json @@ -15,7 +15,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/digitrust.json b/endpoints/openrtb2/sample-requests/invalid-whole/digitrust.json index 2b65ed19db0..1be93853a0b 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/digitrust.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/digitrust.json @@ -25,7 +25,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/format-empty-array.json b/endpoints/openrtb2/sample-requests/invalid-whole/format-empty-array.json index e159601b6e8..15e41cc5fb2 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/format-empty-array.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/format-empty-array.json @@ -13,7 +13,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/imp-id-duplicates.json b/endpoints/openrtb2/sample-requests/invalid-whole/imp-id-duplicates.json index 095542ef59e..53517c268b6 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/imp-id-duplicates.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/imp-id-duplicates.json @@ -18,7 +18,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } }, diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/interstital-bad-perc.json b/endpoints/openrtb2/sample-requests/invalid-whole/interstital-bad-perc.json index f04f3d8aa25..6854ea9a470 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/interstital-bad-perc.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/interstital-bad-perc.json @@ -20,7 +20,7 @@ "instl": 1, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/interstitial-empty.json b/endpoints/openrtb2/sample-requests/invalid-whole/interstitial-empty.json index 5fa28059b0d..a69f287dfab 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/interstitial-empty.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/interstitial-empty.json @@ -14,7 +14,7 @@ "instl": 1, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/no-site-or-app.json b/endpoints/openrtb2/sample-requests/invalid-whole/no-site-or-app.json index 1cbfdd501c2..c56dae324fc 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/no-site-or-app.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/no-site-or-app.json @@ -12,7 +12,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/regs-ext-gdpr-invalid.json b/endpoints/openrtb2/sample-requests/invalid-whole/regs-ext-gdpr-invalid.json index 6737295ae82..dff3023c702 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/regs-ext-gdpr-invalid.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/regs-ext-gdpr-invalid.json @@ -17,7 +17,7 @@ "id": "/19968336/header-bid-tag-0", "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } }, "banner": { diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/regs-ext-gdpr-string.json b/endpoints/openrtb2/sample-requests/invalid-whole/regs-ext-gdpr-string.json index 3abc88c70da..ce887889034 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/regs-ext-gdpr-string.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/regs-ext-gdpr-string.json @@ -17,7 +17,7 @@ "id": "/19968336/header-bid-tag-0", "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } }, "banner": { diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/regs-ext-malformed.json b/endpoints/openrtb2/sample-requests/invalid-whole/regs-ext-malformed.json index 7c2805fcdbb..a403103d6fb 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/regs-ext-malformed.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/regs-ext-malformed.json @@ -17,7 +17,7 @@ "id": "/19968336/header-bid-tag-0", "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } }, "banner": { diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/site-app-both.json b/endpoints/openrtb2/sample-requests/invalid-whole/site-app-both.json index abbcdac325f..4b643705640 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/site-app-both.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/site-app-both.json @@ -16,7 +16,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/site-empty.json b/endpoints/openrtb2/sample-requests/invalid-whole/site-empty.json index 430b25f67a0..3d53314dbb7 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/site-empty.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/site-empty.json @@ -13,7 +13,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/site-ext-amp.json b/endpoints/openrtb2/sample-requests/invalid-whole/site-ext-amp.json index 17cd68b9232..bebe4625578 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/site-ext-amp.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/site-ext-amp.json @@ -28,7 +28,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/storedrequest-id-int.json b/endpoints/openrtb2/sample-requests/invalid-whole/storedrequest-id-int.json index 3fe94a993ad..5d510d21dbd 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/storedrequest-id-int.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/storedrequest-id-int.json @@ -15,7 +15,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/unknown-bidder.json b/endpoints/openrtb2/sample-requests/invalid-whole/unknown-bidder.json index f11be6fd51c..3914ae7ae49 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/unknown-bidder.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/unknown-bidder.json @@ -24,7 +24,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 }, "unknownbidder": { "param1": "foobar", diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-consent-int.json b/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-consent-int.json index c7a6a53b087..5bc0ed33eab 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-consent-int.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-consent-int.json @@ -17,7 +17,7 @@ "id": "/19968336/header-bid-tag-0", "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } }, "banner": { diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-eids-eids-uids-empty.json b/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-eids-eids-uids-empty.json index e9914e3b7db..ebbb4e2701c 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-eids-eids-uids-empty.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-eids-eids-uids-empty.json @@ -17,7 +17,7 @@ "id": "/19968336/header-bid-tag-0", "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } }, "banner": { diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-eids-empty.json b/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-eids-empty.json index 4f66917ff3f..3d73d73117e 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-eids-empty.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-eids-empty.json @@ -17,7 +17,7 @@ "id": "/19968336/header-bid-tag-0", "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } }, "banner": { diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-eids-id-uids-empty.json b/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-eids-id-uids-empty.json index 1ca50079a9a..bbd0dadfd70 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-eids-id-uids-empty.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-eids-id-uids-empty.json @@ -17,7 +17,7 @@ "id": "/19968336/header-bid-tag-0", "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } }, "banner": { diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-eids-source-empty.json b/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-eids-source-empty.json index 8526298047f..5efff0626ef 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-eids-source-empty.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-eids-source-empty.json @@ -17,7 +17,7 @@ "id": "/19968336/header-bid-tag-0", "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } }, "banner": { diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-eids-source-unique.json b/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-eids-source-unique.json index 52565d47228..e508b113aff 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-eids-source-unique.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-eids-source-unique.json @@ -17,7 +17,7 @@ "id": "/19968336/header-bid-tag-0", "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } }, "banner": { diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-eids-uids-id-empty.json b/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-eids-uids-id-empty.json index 33a33b9f416..3a9659b7327 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-eids-uids-id-empty.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-eids-uids-id-empty.json @@ -17,7 +17,7 @@ "id": "/19968336/header-bid-tag-0", "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } }, "banner": { diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-prebid-buyeruids-empty.json b/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-prebid-buyeruids-empty.json index d967463d2d1..44bee775844 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-prebid-buyeruids-empty.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-prebid-buyeruids-empty.json @@ -18,7 +18,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-prebid-buyeruids-unknown.json b/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-prebid-buyeruids-unknown.json index bad67e2d3d8..78773066744 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-prebid-buyeruids-unknown.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-prebid-buyeruids-unknown.json @@ -18,7 +18,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-prebid-empty.json b/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-prebid-empty.json index 8113a70be68..f2e497514b7 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-prebid-empty.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/user-ext-prebid-empty.json @@ -18,7 +18,7 @@ }, "ext": { "appnexus":{ - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/user-gdpr-badtype.json b/endpoints/openrtb2/sample-requests/invalid-whole/user-gdpr-badtype.json index 3abc88c70da..ce887889034 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/user-gdpr-badtype.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/user-gdpr-badtype.json @@ -17,7 +17,7 @@ "id": "/19968336/header-bid-tag-0", "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } }, "banner": { diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/user-gdpr-invalid.json b/endpoints/openrtb2/sample-requests/invalid-whole/user-gdpr-invalid.json index b2b554846ca..0729a22db80 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/user-gdpr-invalid.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/user-gdpr-invalid.json @@ -17,7 +17,7 @@ "id": "/19968336/header-bid-tag-0", "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } }, "banner": { diff --git a/endpoints/openrtb2/sample-requests/valid-whole/exemplary/all-ext.json b/endpoints/openrtb2/sample-requests/valid-whole/exemplary/all-ext.json index 17b249a1494..3e2beedefac 100644 --- a/endpoints/openrtb2/sample-requests/valid-whole/exemplary/all-ext.json +++ b/endpoints/openrtb2/sample-requests/valid-whole/exemplary/all-ext.json @@ -39,7 +39,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 }, "districtm": { "placementId": 105 diff --git a/endpoints/openrtb2/sample-requests/valid-whole/exemplary/prebid-test-ad.json b/endpoints/openrtb2/sample-requests/valid-whole/exemplary/prebid-test-ad.json index b4fd8693953..fc4794328a4 100644 --- a/endpoints/openrtb2/sample-requests/valid-whole/exemplary/prebid-test-ad.json +++ b/endpoints/openrtb2/sample-requests/valid-whole/exemplary/prebid-test-ad.json @@ -23,7 +23,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/aliased-buyeruids.json b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/aliased-buyeruids.json index 1eb74614340..82125592e46 100644 --- a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/aliased-buyeruids.json +++ b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/aliased-buyeruids.json @@ -16,7 +16,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/aliases.json b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/aliases.json index 6c8608ba3c6..f6137e4a019 100644 --- a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/aliases.json +++ b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/aliases.json @@ -13,7 +13,7 @@ }, "ext": { "unknown": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/app.json b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/app.json index cad5e852e69..66e05d7636b 100644 --- a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/app.json +++ b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/app.json @@ -28,7 +28,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/bid-adjustments.json b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/bid-adjustments.json index 2ce81b97b25..0cf52a8915f 100644 --- a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/bid-adjustments.json +++ b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/bid-adjustments.json @@ -13,7 +13,7 @@ }, "ext": { "unknown": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/cache-bids.json b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/cache-bids.json index 884ec898dab..a4c93b3d3cb 100644 --- a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/cache-bids.json +++ b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/cache-bids.json @@ -13,7 +13,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/cache-vast.json b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/cache-vast.json index 7878767af78..fe9445358ba 100644 --- a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/cache-vast.json +++ b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/cache-vast.json @@ -13,7 +13,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/ccpa-invalid.json b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/ccpa-invalid.json index bf04930420b..f3b677635c0 100644 --- a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/ccpa-invalid.json +++ b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/ccpa-invalid.json @@ -15,7 +15,7 @@ "id": "/19968336/header-bid-tag-0", "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } }, "banner": { diff --git a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/digitrust.json b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/digitrust.json index 0017f5e7203..ca8e090760d 100644 --- a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/digitrust.json +++ b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/digitrust.json @@ -23,7 +23,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/gdpr-no-consentstring.json b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/gdpr-no-consentstring.json index 77f1f86bede..5a63c6d11ce 100644 --- a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/gdpr-no-consentstring.json +++ b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/gdpr-no-consentstring.json @@ -15,7 +15,7 @@ "id": "/19968336/header-bid-tag-0", "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } }, "banner": { diff --git a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/gdpr.json b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/gdpr.json index 1234f58ddce..ef9f10d0cd0 100644 --- a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/gdpr.json +++ b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/gdpr.json @@ -15,7 +15,7 @@ "id": "/19968336/header-bid-tag-0", "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } }, "banner": { diff --git a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/interstitial-device-only.json b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/interstitial-device-only.json index 2c85ef143d3..64146eaebe8 100644 --- a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/interstitial-device-only.json +++ b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/interstitial-device-only.json @@ -10,7 +10,7 @@ "instl": 1, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/interstitial-no-extension.json b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/interstitial-no-extension.json index 1e6604e7d2a..15cd832053f 100644 --- a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/interstitial-no-extension.json +++ b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/interstitial-no-extension.json @@ -17,7 +17,7 @@ "instl": 1, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/interstitial.json b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/interstitial.json index c5d373797ff..64fc2fe2653 100644 --- a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/interstitial.json +++ b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/interstitial.json @@ -17,7 +17,7 @@ "instl": 1, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/site-amp.json b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/site-amp.json index c0dbb355fea..30c0afc800a 100644 --- a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/site-amp.json +++ b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/site-amp.json @@ -26,7 +26,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/site.json b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/site.json index f0a02103c34..7a25249c763 100644 --- a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/site.json +++ b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/site.json @@ -23,7 +23,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/timeout.json b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/timeout.json index 611d96ca581..b3dbe1f5d4b 100644 --- a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/timeout.json +++ b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/timeout.json @@ -22,7 +22,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/user.json b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/user.json index 951a7774fe4..243b0739b7b 100644 --- a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/user.json +++ b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/user.json @@ -23,7 +23,7 @@ }, "ext": { "appnexus": { - "placementId": 10433394 + "placementId": 12883451 } } } diff --git a/endpoints/openrtb2/video_auction.go b/endpoints/openrtb2/video_auction.go index eecdc5f99d1..b8b21b762d7 100644 --- a/endpoints/openrtb2/video_auction.go +++ b/endpoints/openrtb2/video_auction.go @@ -65,7 +65,7 @@ func NewVideoEndpoint(ex exchange.Exchange, validator openrtb_ext.BidderParamVal */ func (deps *endpointDeps) VideoAuctionEndpoint(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - ao := analytics.AuctionObject{ + vo := analytics.VideoObject{ Status: http.StatusOK, Errors: make([]error, 0), } @@ -82,7 +82,7 @@ func (deps *endpointDeps) VideoAuctionEndpoint(w http.ResponseWriter, r *http.Re defer func() { deps.metricsEngine.RecordRequest(labels) deps.metricsEngine.RecordRequestTime(labels, time.Since(start)) - deps.analytics.LogAuctionObject(&ao) + deps.analytics.LogVideoObject(&vo) }() lr := &io.LimitedReader{ @@ -91,7 +91,7 @@ func (deps *endpointDeps) VideoAuctionEndpoint(w http.ResponseWriter, r *http.Re } requestJson, err := ioutil.ReadAll(lr) if err != nil { - handleError(&labels, w, []error{err}, &ao) + handleError(&labels, w, []error{err}, &vo) return } @@ -102,35 +102,37 @@ func (deps *endpointDeps) VideoAuctionEndpoint(w http.ResponseWriter, r *http.Re if err != nil { if deps.cfg.VideoStoredRequestRequired { - handleError(&labels, w, []error{err}, &ao) + handleError(&labels, w, []error{err}, &vo) return } } else { storedRequest, errs := deps.loadStoredVideoRequest(context.Background(), storedRequestId) if len(errs) > 0 { - handleError(&labels, w, errs, &ao) + handleError(&labels, w, errs, &vo) return } //merge incoming req with stored video req resolvedRequest, err = jsonpatch.MergePatch(storedRequest, requestJson) if err != nil { - handleError(&labels, w, []error{err}, &ao) + handleError(&labels, w, []error{err}, &vo) return } } //unmarshal and validate combined result videoBidReq, errL, podErrors := deps.parseVideoRequest(resolvedRequest) if len(errL) > 0 { - handleError(&labels, w, errL, &ao) + handleError(&labels, w, errL, &vo) return } + vo.VideoRequest = videoBidReq + var bidReq = &openrtb.BidRequest{} if deps.defaultRequest { if err := json.Unmarshal(deps.defReqJSON, bidReq); err != nil { err = fmt.Errorf("Invalid JSON in Default Request Settings: %s", err) - handleError(&labels, w, []error{err}, &ao) + handleError(&labels, w, []error{err}, &vo) return } } @@ -154,7 +156,7 @@ func (deps *endpointDeps) VideoAuctionEndpoint(w http.ResponseWriter, r *http.Re } err := errors.New(fmt.Sprintf("all pods are incorrect: %s", strings.Join(resPodErr, "; "))) errL = append(errL, err) - handleError(&labels, w, errL, &ao) + handleError(&labels, w, errL, &vo) return } @@ -166,7 +168,7 @@ func (deps *endpointDeps) VideoAuctionEndpoint(w http.ResponseWriter, r *http.Re errL = deps.validateRequest(bidReq) if len(errL) > 0 { - handleError(&labels, w, errL, &ao) + handleError(&labels, w, errL, &vo) return } @@ -194,16 +196,16 @@ func (deps *endpointDeps) VideoAuctionEndpoint(w http.ResponseWriter, r *http.Re if acctIdErr := validateAccount(deps.cfg, labels.PubID); acctIdErr != nil { errL = append(errL, acctIdErr) - handleError(&labels, w, errL, &ao) + handleError(&labels, w, errL, &vo) return } //execute auction logic response, err := deps.ex.HoldAuction(ctx, bidReq, usersyncs, labels, &deps.categories) - ao.Request = bidReq - ao.Response = response + vo.Request = bidReq + vo.Response = response if err != nil { errL := []error{err} - handleError(&labels, w, errL, &ao) + handleError(&labels, w, errL, &vo) return } @@ -211,18 +213,20 @@ func (deps *endpointDeps) VideoAuctionEndpoint(w http.ResponseWriter, r *http.Re bidResp, err := buildVideoResponse(response, podErrors) if err != nil { errL := []error{err} - handleError(&labels, w, errL, &ao) + handleError(&labels, w, errL, &vo) return } if bidReq.Test == 1 { bidResp.Ext = response.Ext } + vo.VideoResponse = bidResp + resp, err := json.Marshal(bidResp) //resp, err := json.Marshal(response) if err != nil { errL := []error{err} - handleError(&labels, w, errL, &ao) + handleError(&labels, w, errL, &vo) return } @@ -238,7 +242,7 @@ func cleanupVideoBidRequest(videoReq *openrtb_ext.BidRequestVideo, podErrors []P return videoReq } -func handleError(labels *pbsmetrics.Labels, w http.ResponseWriter, errL []error, ao *analytics.AuctionObject) { +func handleError(labels *pbsmetrics.Labels, w http.ResponseWriter, errL []error, vo *analytics.VideoObject) { labels.RequestStatus = pbsmetrics.RequestStatusErr var errors string var status int = http.StatusInternalServerError @@ -256,10 +260,10 @@ func handleError(labels *pbsmetrics.Labels, w http.ResponseWriter, errL []error, errors = fmt.Sprintf("%s %s", errors, er.Error()) } w.WriteHeader(status) - ao.Status = status + vo.Status = status fmt.Fprintf(w, "Critical error while running the video endpoint: %v", errors) glog.Errorf("/openrtb2/video Critical error: %v", errors) - ao.Errors = append(ao.Errors, errL...) + vo.Errors = append(vo.Errors, errL...) } func (deps *endpointDeps) createImpressions(videoReq *openrtb_ext.BidRequestVideo, podErrors []PodError) ([]openrtb.Imp, []PodError) { diff --git a/endpoints/openrtb2/video_auction_test.go b/endpoints/openrtb2/video_auction_test.go index e49a9f9cd1a..cd87041055a 100644 --- a/endpoints/openrtb2/video_auction_test.go +++ b/endpoints/openrtb2/video_auction_test.go @@ -650,7 +650,7 @@ func TestMergeOpenRTBToVideoRequest(t *testing.T) { } func TestHandleError(t *testing.T) { - ao := analytics.AuctionObject{ + vo := analytics.VideoObject{ Status: 200, Errors: make([]error, 0), } @@ -667,14 +667,14 @@ func TestHandleError(t *testing.T) { recorder := httptest.NewRecorder() err1 := errors.New("Error for testing handleError 1") err2 := errors.New("Error for testing handleError 2") - handleError(&labels, recorder, []error{err1, err2}, &ao) + handleError(&labels, recorder, []error{err1, err2}, &vo) assert.Equal(t, pbsmetrics.RequestStatusErr, labels.RequestStatus, "labels.RequestStatus should indicate an error") assert.Equal(t, 500, recorder.Code, "Error status should be written to writer") - assert.Equal(t, 500, ao.Status, "AnalyticsObject should have error status") - assert.Equal(t, 2, len(ao.Errors), "New errors should be appended to AnalyticsObject Errors") - assert.Equal(t, "Error for testing handleError 1", ao.Errors[0].Error(), "Error in AnalyticsObject should have test error message for first error") - assert.Equal(t, "Error for testing handleError 2", ao.Errors[1].Error(), "Error in AnalyticsObject should have test error message for second error") + assert.Equal(t, 500, vo.Status, "Analytics object should have error status") + assert.Equal(t, 2, len(vo.Errors), "New errors should be appended to Analytics object Errors") + assert.Equal(t, "Error for testing handleError 1", vo.Errors[0].Error(), "Error in Analytics object should have test error message for first error") + assert.Equal(t, "Error for testing handleError 2", vo.Errors[1].Error(), "Error in Analytics object should have test error message for second error") } func TestHandleErrorMetrics(t *testing.T) { @@ -692,11 +692,11 @@ func TestHandleErrorMetrics(t *testing.T) { assert.Equal(t, int64(0), met.RequestStatuses[pbsmetrics.ReqTypeVideo][pbsmetrics.RequestStatusOK].Count(), "OK requests count should be 0") assert.Equal(t, int64(1), met.RequestStatuses[pbsmetrics.ReqTypeVideo][pbsmetrics.RequestStatusErr].Count(), "Error requests count should be 1") - assert.Equal(t, 1, len(mod.auctionObjects), "Mock AnalyticsModule should have 1 AuctionObject") - assert.Equal(t, 500, mod.auctionObjects[0].Status, "AnalyticsObject should have 500 status") - assert.Equal(t, 2, len(mod.auctionObjects[0].Errors), "AnalyticsObject should have Errors length of 2") - assert.Equal(t, "request missing required field: PodConfig.DurationRangeSec", mod.auctionObjects[0].Errors[0].Error(), "First error in AnalyticsObject should have message regarding DurationRangeSec") - assert.Equal(t, "request missing required field: PodConfig.Pods", mod.auctionObjects[0].Errors[1].Error(), "Second error in AnalyticsObject should have message regarding Pods") + assert.Equal(t, 1, len(mod.videoObjects), "Mock AnalyticsModule should have 1 AuctionObject") + assert.Equal(t, 500, mod.videoObjects[0].Status, "AnalyticsObject should have 500 status") + assert.Equal(t, 2, len(mod.videoObjects[0].Errors), "AnalyticsObject should have Errors length of 2") + assert.Equal(t, "request missing required field: PodConfig.DurationRangeSec", mod.videoObjects[0].Errors[0].Error(), "First error in AnalyticsObject should have message regarding DurationRangeSec") + assert.Equal(t, "request missing required field: PodConfig.Pods", mod.videoObjects[0].Errors[1].Error(), "Second error in AnalyticsObject should have message regarding Pods") } func mockDepsWithMetrics(t *testing.T, ex *mockExchangeVideo) (*endpointDeps, *pbsmetrics.Metrics, *mockAnalyticsModule) { @@ -722,12 +722,17 @@ func mockDepsWithMetrics(t *testing.T, ex *mockExchangeVideo) (*endpointDeps, *p type mockAnalyticsModule struct { auctionObjects []*analytics.AuctionObject + videoObjects []*analytics.VideoObject } func (m *mockAnalyticsModule) LogAuctionObject(ao *analytics.AuctionObject) { m.auctionObjects = append(m.auctionObjects, ao) } +func (m *mockAnalyticsModule) LogVideoObject(vo *analytics.VideoObject) { + m.videoObjects = append(m.videoObjects, vo) +} + func (m *mockAnalyticsModule) LogCookieSyncObject(cso *analytics.CookieSyncObject) { return } func (m *mockAnalyticsModule) LogSetUIDObject(so *analytics.SetUIDObject) { return } diff --git a/exchange/adapter_map.go b/exchange/adapter_map.go index 87931b32d14..3cb65275f1b 100644 --- a/exchange/adapter_map.go +++ b/exchange/adapter_map.go @@ -15,12 +15,14 @@ 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/applogy" "github.com/prebid/prebid-server/adapters/appnexus" "github.com/prebid/prebid-server/adapters/audienceNetwork" "github.com/prebid/prebid-server/adapters/beachfront" "github.com/prebid/prebid-server/adapters/brightroll" "github.com/prebid/prebid-server/adapters/consumable" "github.com/prebid/prebid-server/adapters/conversant" + "github.com/prebid/prebid-server/adapters/cpmstar" "github.com/prebid/prebid-server/adapters/datablocks" "github.com/prebid/prebid-server/adapters/emx_digital" "github.com/prebid/prebid-server/adapters/engagebdr" @@ -43,6 +45,7 @@ import ( "github.com/prebid/prebid-server/adapters/rtbhouse" "github.com/prebid/prebid-server/adapters/rubicon" "github.com/prebid/prebid-server/adapters/sharethrough" + "github.com/prebid/prebid-server/adapters/smartrtb" "github.com/prebid/prebid-server/adapters/somoaudience" "github.com/prebid/prebid-server/adapters/sonobi" "github.com/prebid/prebid-server/adapters/sovrn" @@ -72,11 +75,13 @@ 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.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 openrtb_ext.BidderBeachfront: beachfront.NewBeachfrontBidder(), openrtb_ext.BidderBrightroll: brightroll.NewBrightrollBidder(cfg.Adapters[string(openrtb_ext.BidderBrightroll)].Endpoint), openrtb_ext.BidderConsumable: consumable.NewConsumableBidder(cfg.Adapters[string(openrtb_ext.BidderConsumable)].Endpoint), + openrtb_ext.BidderCpmstar: cpmstar.NewCpmstarBidder(cfg.Adapters[string(openrtb_ext.BidderCpmstar)].Endpoint), openrtb_ext.BidderDatablocks: datablocks.NewDatablocksBidder(cfg.Adapters[string(openrtb_ext.BidderDatablocks)].Endpoint), openrtb_ext.BidderEmxDigital: emx_digital.NewEmxDigitalBidder(cfg.Adapters[string(openrtb_ext.BidderEmxDigital)].Endpoint), openrtb_ext.BidderEngageBDR: engagebdr.NewEngageBDRBidder(client, cfg.Adapters[string(openrtb_ext.BidderEngageBDR)].Endpoint), @@ -107,6 +112,7 @@ func newAdapterMap(client *http.Client, cfg *config.Configuration, infos adapter cfg.Adapters[string(openrtb_ext.BidderRubicon)].XAPI.Tracker), openrtb_ext.BidderSharethrough: sharethrough.NewSharethroughBidder(cfg.Adapters[string(openrtb_ext.BidderSharethrough)].Endpoint), + openrtb_ext.BidderSmartRTB: smartrtb.NewSmartRTBBidder(cfg.Adapters[string(openrtb_ext.BidderSmartRTB)].Endpoint), openrtb_ext.BidderSomoaudience: somoaudience.NewSomoaudienceBidder(cfg.Adapters[string(openrtb_ext.BidderSomoaudience)].Endpoint), openrtb_ext.BidderSonobi: sonobi.NewSonobiBidder(client, cfg.Adapters[string(openrtb_ext.BidderSonobi)].Endpoint), openrtb_ext.BidderSovrn: sovrn.NewSovrnBidder(client, cfg.Adapters[string(openrtb_ext.BidderSovrn)].Endpoint), diff --git a/exchange/bidder.go b/exchange/bidder.go index 5708660057f..d9a28fee175 100644 --- a/exchange/bidder.go +++ b/exchange/bidder.go @@ -8,6 +8,7 @@ import ( "fmt" "io/ioutil" "net/http" + "time" "github.com/mxmCherry/openrtb" nativeRequests "github.com/mxmCherry/openrtb/native/request" @@ -295,6 +296,14 @@ func (bidder *bidderAdapter) doRequest(ctx context.Context, req *adapters.Reques if err != nil { if err == context.DeadlineExceeded { err = &errortypes.Timeout{Message: err.Error()} + if tb, ok := bidder.Bidder.(adapters.TimeoutBidder); ok { + // Toss the timeout notification call into a go routine, as we are out of time' + // and cannot delay processing. We don't do anything result, as there is not much + // we can do about a timeout notification failure. We do not want to get stuck in + // a loop of trying to report timeouts to the timeout notifications. + go bidder.doTimeoutNotification(tb, req) + } + } return &httpCallInfo{ request: req, @@ -328,6 +337,21 @@ func (bidder *bidderAdapter) doRequest(ctx context.Context, req *adapters.Reques } } +func (bidder *bidderAdapter) doTimeoutNotification(timeoutBidder adapters.TimeoutBidder, req *adapters.RequestData) { + ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond) + defer cancel() + toReq, errL := timeoutBidder.MakeTimeoutNotification(req) + if toReq != nil && len(errL) == 0 { + httpReq, err := http.NewRequest(toReq.Method, toReq.Uri, bytes.NewBuffer(toReq.Body)) + if err == nil { + httpReq.Header = req.Headers + ctxhttp.Do(ctx, bidder.Client, httpReq) + // No validation yet on sending notifications + } + } + +} + type httpCallInfo struct { request *adapters.RequestData response *adapters.ResponseData diff --git a/exchange/exchange.go b/exchange/exchange.go index 071b4f8d771..8c6cac4cfcd 100644 --- a/exchange/exchange.go +++ b/exchange/exchange.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "encoding/json" + "errors" "fmt" "math/rand" "net/http" @@ -146,10 +147,14 @@ func (e *exchange) HoldAuction(ctx context.Context, bidRequest *openrtb.BidReque //If includebrandcategory is present in ext then CE feature is on. if requestExt.Prebid.Targeting != nil && requestExt.Prebid.Targeting.IncludeBrandCategory != nil { var err error - bidCategory, adapterBids, err = applyCategoryMapping(ctx, requestExt, adapterBids, *categoriesFetcher, targData) + var rejections []string + bidCategory, adapterBids, rejections, err = applyCategoryMapping(ctx, requestExt, adapterBids, *categoriesFetcher, targData) if err != nil { return nil, fmt.Errorf("Error in category mapping : %s", err.Error()) } + for _, message := range rejections { + errs = append(errs, errors.New(message)) + } } auc = newAuction(adapterBids, len(bidRequest.Imp)) @@ -324,6 +329,7 @@ func (e *exchange) buildBidResponse(ctx context.Context, liveAdapters []openrtb_ if adapterBids[a] != nil && len(adapterBids[a].bids) > 0 { sb := e.makeSeatBid(adapterBids[a], a, adapterExtra, auc) seatBids = append(seatBids, *sb) + bidResponse.Cur = adapterBids[a].currency } } @@ -339,7 +345,7 @@ func (e *exchange) buildBidResponse(ctx context.Context, liveAdapters []openrtb_ return bidResponse, err } -func applyCategoryMapping(ctx context.Context, requestExt openrtb_ext.ExtRequest, seatBids map[openrtb_ext.BidderName]*pbsOrtbSeatBid, categoriesFetcher stored_requests.CategoryFetcher, targData *targetData) (map[string]string, map[openrtb_ext.BidderName]*pbsOrtbSeatBid, error) { +func applyCategoryMapping(ctx context.Context, requestExt openrtb_ext.ExtRequest, seatBids map[openrtb_ext.BidderName]*pbsOrtbSeatBid, categoriesFetcher stored_requests.CategoryFetcher, targData *targetData) (map[string]string, map[openrtb_ext.BidderName]*pbsOrtbSeatBid, []string, error) { res := make(map[string]string) type bidDedupe struct { @@ -358,6 +364,7 @@ func applyCategoryMapping(ctx context.Context, requestExt openrtb_ext.ExtRequest var primaryAdServer string var publisher string var err error + var rejections []string var translateCategories = true if includeBrandCategory && brandCatExt.WithCategory { @@ -369,7 +376,7 @@ func applyCategoryMapping(ctx context.Context, requestExt openrtb_ext.ExtRequest //if ext.prebid.targeting.includebrandcategory present but primaryadserver/publisher not present then error out the request right away. primaryAdServer, err = getPrimaryAdServer(brandCatExt.PrimaryAdServer) //1-Freewheel 2-DFP if err != nil { - return res, seatBids, err + return res, seatBids, rejections, err } publisher = brandCatExt.Publisher } @@ -381,6 +388,7 @@ func applyCategoryMapping(ctx context.Context, requestExt openrtb_ext.ExtRequest bidsToRemove := make([]int, 0) for bidInd := range seatBid.bids { bid := seatBid.bids[bidInd] + bidID := bid.bid.ID var duration int var category string var pb string @@ -395,6 +403,7 @@ func applyCategoryMapping(ctx context.Context, requestExt openrtb_ext.ExtRequest //TODO: add metrics //on receiving bids from adapters if no unique IAB category is returned or if no ad server category is returned discard the bid bidsToRemove = append(bidsToRemove, bidInd) + rejections = updateRejections(rejections, bidID, "Bid did not contain a category") continue } if translateCategories { @@ -404,6 +413,8 @@ func applyCategoryMapping(ctx context.Context, requestExt openrtb_ext.ExtRequest //TODO: add metrics //if mapping required but no mapping file is found then discard the bid bidsToRemove = append(bidsToRemove, bidInd) + reason := fmt.Sprintf("Category mapping file for primary ad server: '%s', publisher: '%s' not found", primaryAdServer, publisher) + rejections = updateRejections(rejections, bidID, reason) continue } } else { @@ -423,6 +434,7 @@ func applyCategoryMapping(ctx context.Context, requestExt openrtb_ext.ExtRequest //if the bid is above the range of the listed durations (and outside the buffer), reject the bid if duration > durationRange[len(durationRange)-1] { bidsToRemove = append(bidsToRemove, bidInd) + rejections = updateRejections(rejections, bidID, "Bid duration exceeds maximum allowed") continue } for _, dur := range durationRange { @@ -446,11 +458,13 @@ func applyCategoryMapping(ctx context.Context, requestExt openrtb_ext.ExtRequest if dupe.bidderName == bidderName { // An older bid from the current bidder bidsToRemove = append(bidsToRemove, dupe.bidIndex) + rejections = updateRejections(rejections, dupe.bidID, "Bid was deduplicated") } else { // An older bid from a different seatBid we've already finished with oldSeatBid := (seatBids)[dupe.bidderName] if len(oldSeatBid.bids) == 1 { seatBidsToRemove = append(seatBidsToRemove, bidderName) + rejections = updateRejections(rejections, dupe.bidID, "Bid was deduplicated") } else { oldSeatBid.bids = append(oldSeatBid.bids[:dupe.bidIndex], oldSeatBid.bids[dupe.bidIndex+1:]...) } @@ -459,11 +473,12 @@ func applyCategoryMapping(ctx context.Context, requestExt openrtb_ext.ExtRequest } else { // Remove this bid bidsToRemove = append(bidsToRemove, bidInd) + rejections = updateRejections(rejections, bidID, "Bid was deduplicated") continue } } - res[bid.bid.ID] = categoryDuration - dedupe[categoryDuration] = bidDedupe{bidderName: bidderName, bidIndex: bidInd, bidID: bid.bid.ID} + res[bidID] = categoryDuration + dedupe[categoryDuration] = bidDedupe{bidderName: bidderName, bidIndex: bidInd, bidID: bidID} } if len(bidsToRemove) > 0 { @@ -482,19 +497,16 @@ func applyCategoryMapping(ctx context.Context, requestExt openrtb_ext.ExtRequest } } - if len(seatBidsToRemove) > 0 { - if len(seatBidsToRemove) == len(seatBids) { - //delete all seat bids - seatBids = nil - } else { - for _, seatBidInd := range seatBidsToRemove { - delete(seatBids, seatBidInd) - } - - } + for _, seatBidInd := range seatBidsToRemove { + seatBids[seatBidInd].bids = nil } - return res, seatBids, nil + return res, seatBids, rejections, nil +} + +func updateRejections(rejections []string, bidID string, reason string) []string { + message := fmt.Sprintf("bid rejected [bid ID: %s] reason: %s", bidID, reason) + return append(rejections, message) } func getPrimaryAdServer(adServerId int) (string, error) { diff --git a/exchange/exchange_test.go b/exchange/exchange_test.go index 6718eb7df80..7e199d4b750 100644 --- a/exchange/exchange_test.go +++ b/exchange/exchange_test.go @@ -9,6 +9,7 @@ import ( "io/ioutil" "net/http" "net/http/httptest" + "regexp" "strconv" "strings" "testing" @@ -103,17 +104,17 @@ func TestCharacterEscape(t *testing.T) { Imp: []openrtb.Imp{{ ID: "some-impression-id", Banner: &openrtb.Banner{Format: []openrtb.Format{{W: 300, H: 250}, {W: 300, H: 600}}}, - Ext: json.RawMessage(`{"appnexus": {"placementId": 10433394}}`), + Ext: json.RawMessage(`{"appnexus": {"placementId": 1}}`), }}, Site: &openrtb.Site{Page: "prebid.org", Ext: json.RawMessage(`{"amp":0}`)}, Device: &openrtb.Device{UA: "curl/7.54.0", IP: "::1"}, AT: 1, TMax: 500, - Ext: json.RawMessage(`{"id": "some-request-id","site": {"page": "prebid.org"},"imp": [{"id": "some-impression-id","banner": {"format": [{"w": 300,"h": 250},{"w": 300,"h": 600}]},"ext": {"appnexus": {"placementId": 10433394}}}],"tmax": 500}`), + Ext: json.RawMessage(`{"id": "some-request-id","site": {"page": "prebid.org"},"imp": [{"id": "some-impression-id","banner": {"format": [{"w": 300,"h": 250},{"w": 300,"h": 600}]},"ext": {"appnexus": {"placementId": 1}}}],"tmax": 500}`), } //resolvedRequest json.RawMessage - resolvedRequest := json.RawMessage(`{"id": "some-request-id","site": {"page": "prebid.org"},"imp": [{"id": "some-impression-id","banner": {"format": [{"w": 300,"h": 250},{"w": 300,"h": 600}]},"ext": {"appnexus": {"placementId": 10433394}}}],"tmax": 500}`) + resolvedRequest := json.RawMessage(`{"id": "some-request-id","site": {"page": "prebid.org"},"imp": [{"id": "some-impression-id","banner": {"format": [{"w": 300,"h": 250},{"w": 300,"h": 600}]},"ext": {"appnexus": {"placementId": 1}}}],"tmax": 500}`) //adapterExtra map[openrtb_ext.BidderName]*seatResponseExtra, adapterExtra := make(map[openrtb_ext.BidderName]*seatResponseExtra, 1) @@ -170,7 +171,7 @@ func TestGetBidCacheInfo(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(handlerNoBidServer)) defer server.Close() - e := NewExchange(server.Client(), pbc.NewClient(&cfg.CacheURL, &cfg.ExtCacheURL, testEngine), cfg, pbsmetrics.NewMetrics(metrics.NewRegistry(), openrtb_ext.BidderList(), config.DisabledMetrics{}), adapters.ParseBidderInfos(cfg.Adapters, "../static/bidder-info", openrtb_ext.BidderList()), gdpr.AlwaysAllow{}, currencies.NewRateConverterDefault()).(*exchange) + e := NewExchange(server.Client(), pbc.NewClient(&http.Client{}, &cfg.CacheURL, &cfg.ExtCacheURL, testEngine), cfg, pbsmetrics.NewMetrics(metrics.NewRegistry(), openrtb_ext.BidderList(), config.DisabledMetrics{}), adapters.ParseBidderInfos(cfg.Adapters, "../static/bidder-info", openrtb_ext.BidderList()), gdpr.AlwaysAllow{}, currencies.NewRateConverterDefault()).(*exchange) /* 3) Build all the parameters e.buildBidResponse(ctx.Background(), liveA... ) needs */ liveAdapters := []openrtb_ext.BidderName{bidderName} @@ -231,7 +232,7 @@ func TestGetBidCacheInfo(t *testing.T) { } //resolvedRequest json.RawMessage - resolvedRequest := json.RawMessage(`{"id": "some-request-id","site": {"page": "prebid.org"},"imp": [{"id": "some-impression-id","banner": {"format": [{"w": 300,"h": 250},{"w": 300,"h": 600}]},"ext": {"appnexus": {"placementId": 10433394}}}],"tmax": 500}`) + resolvedRequest := json.RawMessage(`{"id": "some-request-id","site": {"page": "prebid.org"},"imp": [{"id": "some-impression-id","banner": {"format": [{"w": 300,"h": 250},{"w": 300,"h": 600}]},"ext": {"appnexus": {"placementId": 1}}}],"tmax": 500}`) //adapterExtra map[openrtb_ext.BidderName]*seatResponseExtra, adapterExtra := map[openrtb_ext.BidderName]*seatResponseExtra{ @@ -259,7 +260,7 @@ func TestGetBidCacheInfo(t *testing.T) { "siteId": 113932, "zoneId": 535510 }, - "appnexus": { "placementId": 10433394 }, + "appnexus": { "placementId": 1 }, "pubmatic": { "publisherId": "156209", "adSlot": "pubmatic_test2@300x250" }, "pulsepoint": { "cf": "300X250", "cp": 512379, "ct": 486653 }, "conversant": { "site_id": "108060" }, @@ -314,51 +315,145 @@ func TestGetBidCacheInfo(t *testing.T) { assert.Equal(t, expCacheURL, cacheURL, "[TestGetBidCacheInfo] cacheId field in ext should equal \"%s\" \n", expCacheURL) } -func buildBidResponseParams(bidderName openrtb_ext.BidderName, bidRequest *openrtb.BidRequest) ([]openrtb_ext.BidderName, map[openrtb_ext.BidderName]*pbsOrtbSeatBid, json.RawMessage, map[openrtb_ext.BidderName]*seatResponseExtra) { - //liveAdapters []openrtb_ext.BidderName, - liveAdapters := []openrtb_ext.BidderName{bidderName} +func TestBidResponseCurrency(t *testing.T) { + // Init objects + cfg := &config.Configuration{Adapters: make(map[string]config.Adapter, 1)} + cfg.Adapters["appnexus"] = config.Adapter{Endpoint: "http://ib.adnxs.com"} - //adapterBids map[openrtb_ext.BidderName]*pbsOrtbSeatBid, - adapterBids := map[openrtb_ext.BidderName]*pbsOrtbSeatBid{ - bidderName: { - bids: []*pbsOrtbBid{ + handlerNoBidServer := func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(204) } + server := httptest.NewServer(http.HandlerFunc(handlerNoBidServer)) + defer server.Close() + + e := NewExchange(server.Client(), nil, cfg, pbsmetrics.NewMetrics(metrics.NewRegistry(), openrtb_ext.BidderList(), config.DisabledMetrics{}), adapters.ParseBidderInfos(cfg.Adapters, "../static/bidder-info", openrtb_ext.BidderList()), gdpr.AlwaysAllow{}, currencies.NewRateConverterDefault()).(*exchange) + + liveAdapters := make([]openrtb_ext.BidderName, 1) + liveAdapters[0] = "appnexus" + + bidRequest := &openrtb.BidRequest{ + ID: "some-request-id", + Imp: []openrtb.Imp{{ + ID: "some-impression-id", + Banner: &openrtb.Banner{Format: []openrtb.Format{{W: 300, H: 250}, {W: 300, H: 600}}}, + Ext: json.RawMessage(`{"appnexus": {"placementId": 10433394}}`), + }}, + Site: &openrtb.Site{Page: "prebid.org", Ext: json.RawMessage(`{"amp":0}`)}, + Device: &openrtb.Device{UA: "curl/7.54.0", IP: "::1"}, + AT: 1, + TMax: 500, + Ext: json.RawMessage(`{"id": "some-request-id","site": {"page": "prebid.org"},"imp": [{"id": "some-impression-id","banner": {"format": [{"w": 300,"h": 250},{"w": 300,"h": 600}]},"ext": {"appnexus": {"placementId": 10433394}}}],"tmax": 500}`), + } + + resolvedRequest := json.RawMessage(`{"id": "some-request-id","site": {"page": "prebid.org"},"imp": [{"id": "some-impression-id","banner": {"format": [{"w": 300,"h": 250},{"w": 300,"h": 600}]},"ext": {"appnexus": {"placementId": 1}}}],"tmax": 500}`) + + adapterExtra := map[openrtb_ext.BidderName]*seatResponseExtra{ + "appnexus": {ResponseTimeMillis: 5}, + } + + var errList []error + + sampleBid := &openrtb.Bid{ + ID: "some-imp-id", + Price: 9.517803, + W: 300, + H: 250, + Ext: nil, + } + aPbsOrtbBidArr := []*pbsOrtbBid{{bid: sampleBid, bidType: openrtb_ext.BidTypeBanner}} + sampleSeatBid := []openrtb.SeatBid{ + { + Seat: "appnexus", + Bid: []openrtb.Bid{ { - bid: &openrtb.Bid{ - ID: "some-imp-id", - Price: 9.517803, - W: 300, - H: 250, - }, - bidType: openrtb_ext.BidTypeBanner, - bidTargets: map[string]string{ - "pricegranularity": "med", - "includewinners": "true", - "includebidderkeys": "false", - }, + ID: "some-imp-id", + Price: 9.517803, + W: 300, + H: 250, + Ext: json.RawMessage(`{"prebid":{"type":"banner"}}`), }, }, - currency: "USD", - //ext: bidRequest.Ext, }, } + emptySeatBid := []openrtb.SeatBid{} - //resolvedRequest json.RawMessage - resolvedRequest := json.RawMessage(`{"id": "some-request-id","site": {"page": "prebid.org"},"imp": [{"id": "some-impression-id","banner": {"format": [{"w": 300,"h": 250},{"w": 300,"h": 600}]},"ext": {"appnexus": {"placementId": 10433394}}}],"tmax": 500}`) - - //adapterExtra map[openrtb_ext.BidderName]*seatResponseExtra, - adapterExtra := map[openrtb_ext.BidderName]*seatResponseExtra{ - bidderName: { - ResponseTimeMillis: 5, - Errors: []openrtb_ext.ExtBidderError{ - { - Code: 999, - Message: "Post ib.adnxs.com/openrtb2?query1&query2: unsupported protocol scheme \"\"", + // Test cases + type aTest struct { + description string + adapterBids map[openrtb_ext.BidderName]*pbsOrtbSeatBid + expectedBidResponse *openrtb.BidResponse + } + testCases := []aTest{ + { + description: "1) Adapter to bids map comes with a non-empty currency field and non-empty bid array", + adapterBids: map[openrtb_ext.BidderName]*pbsOrtbSeatBid{ + openrtb_ext.BidderName("appnexus"): { + bids: aPbsOrtbBidArr, + currency: "USD", + }, + }, + expectedBidResponse: &openrtb.BidResponse{ + ID: "some-request-id", + SeatBid: sampleSeatBid, + Cur: "USD", + Ext: json.RawMessage(`{"responsetimemillis":{"appnexus":5},"tmaxrequest":500} +`), + }, + }, + { + description: "2) Adapter to bids map comes with a non-empty currency field but an empty bid array", + adapterBids: map[openrtb_ext.BidderName]*pbsOrtbSeatBid{ + openrtb_ext.BidderName("appnexus"): { + bids: nil, + currency: "USD", + }, + }, + expectedBidResponse: &openrtb.BidResponse{ + ID: "some-request-id", + SeatBid: emptySeatBid, + Cur: "", + Ext: json.RawMessage(`{"responsetimemillis":{"appnexus":5},"tmaxrequest":500} +`), + }, + }, + { + description: "3) Adapter to bids map comes with an empty currency string and a non-empty bid array", + adapterBids: map[openrtb_ext.BidderName]*pbsOrtbSeatBid{ + openrtb_ext.BidderName("appnexus"): { + bids: aPbsOrtbBidArr, + currency: "", + }, + }, + expectedBidResponse: &openrtb.BidResponse{ + ID: "some-request-id", + SeatBid: sampleSeatBid, + Cur: "", + Ext: json.RawMessage(`{"responsetimemillis":{"appnexus":5},"tmaxrequest":500} +`), + }, + }, + { + description: "4) Adapter to bids map comes with an empty currency string and an empty bid array", + adapterBids: map[openrtb_ext.BidderName]*pbsOrtbSeatBid{ + openrtb_ext.BidderName("appnexus"): { + bids: nil, + currency: "", }, }, + expectedBidResponse: &openrtb.BidResponse{ + ID: "some-request-id", + SeatBid: emptySeatBid, + Cur: "", + Ext: json.RawMessage(`{"responsetimemillis":{"appnexus":5},"tmaxrequest":500} +`), + }, }, } - return liveAdapters, adapterBids, resolvedRequest, adapterExtra + // Run tests + for i := range testCases { + actualBidResp, err := e.buildBidResponse(context.Background(), liveAdapters, testCases[i].adapterBids, bidRequest, resolvedRequest, adapterExtra, nil, errList) + assert.NoError(t, err, fmt.Sprintf("[TEST_FAILED] e.buildBidResponse resturns error in test: %s Error message: %s \n", testCases[i].description, err)) + assert.Equalf(t, testCases[i].expectedBidResponse, actualBidResp, fmt.Sprintf("[TEST_FAILED] Objects must be equal for test: %s \n Expected: >>%s<< \n Actual: >>%s<< ", testCases[i].description, testCases[i].expectedBidResponse.Ext, actualBidResp.Ext)) + } } // TestRaceIntegration runs an integration test using all the sample params from @@ -836,9 +931,11 @@ func TestCategoryMapping(t *testing.T) { adapterBids[bidderName1] = &seatBid - bidCategory, adapterBids, err := applyCategoryMapping(nil, requestExt, adapterBids, categoriesFetcher, targData) + bidCategory, adapterBids, rejections, err := applyCategoryMapping(nil, requestExt, adapterBids, categoriesFetcher, targData) assert.Equal(t, nil, err, "Category mapping error should be empty") + assert.Equal(t, 1, len(rejections), "There should be 1 bid rejection message") + assert.Equal(t, "bid rejected [bid ID: bid_id4] reason: Category mapping file for primary ad server: 'freewheel', publisher: '' not found", rejections[0], "Rejection message did not match expected") assert.Equal(t, "10.00_Electronics_30s", bidCategory["bid_id1"], "Category mapping doesn't match") assert.Equal(t, "20.00_Sports_50s", bidCategory["bid_id2"], "Category mapping doesn't match") assert.Equal(t, "20.00_AdapterOverride_30s", bidCategory["bid_id3"], "Category mapping override from adapter didn't take") @@ -889,9 +986,10 @@ func TestCategoryMappingNoIncludeBrandCategory(t *testing.T) { adapterBids[bidderName1] = &seatBid - bidCategory, adapterBids, err := applyCategoryMapping(nil, requestExt, adapterBids, categoriesFetcher, targData) + bidCategory, adapterBids, rejections, err := applyCategoryMapping(nil, requestExt, adapterBids, categoriesFetcher, targData) assert.Equal(t, nil, err, "Category mapping error should be empty") + assert.Empty(t, rejections, "There should be no bid rejection messages") assert.Equal(t, "10.00_30s", bidCategory["bid_id1"], "Category mapping doesn't match") assert.Equal(t, "20.00_40s", bidCategory["bid_id2"], "Category mapping doesn't match") assert.Equal(t, "20.00_30s", bidCategory["bid_id3"], "Category mapping doesn't match") @@ -940,9 +1038,11 @@ func TestCategoryMappingTranslateCategoriesNil(t *testing.T) { adapterBids[bidderName1] = &seatBid - bidCategory, adapterBids, err := applyCategoryMapping(nil, requestExt, adapterBids, categoriesFetcher, targData) + bidCategory, adapterBids, rejections, err := applyCategoryMapping(nil, requestExt, adapterBids, categoriesFetcher, targData) assert.Equal(t, nil, err, "Category mapping error should be empty") + assert.Equal(t, 1, len(rejections), "There should be 1 bid rejection message") + assert.Equal(t, "bid rejected [bid ID: bid_id3] reason: Category mapping file for primary ad server: 'freewheel', publisher: '' not found", rejections[0], "Rejection message did not match expected") assert.Equal(t, "10.00_Electronics_30s", bidCategory["bid_id1"], "Category mapping doesn't match") assert.Equal(t, "20.00_Sports_50s", bidCategory["bid_id2"], "Category mapping doesn't match") assert.Equal(t, 2, len(adapterBids[bidderName1].bids), "Bidders number doesn't match") @@ -1020,9 +1120,10 @@ func TestCategoryMappingTranslateCategoriesFalse(t *testing.T) { adapterBids[bidderName1] = &seatBid - bidCategory, adapterBids, err := applyCategoryMapping(nil, requestExt, adapterBids, categoriesFetcher, targData) + bidCategory, adapterBids, rejections, err := applyCategoryMapping(nil, requestExt, adapterBids, categoriesFetcher, targData) assert.Equal(t, nil, err, "Category mapping error should be empty") + assert.Empty(t, rejections, "There should be no bid rejection messages") assert.Equal(t, "10.00_IAB1-3_30s", bidCategory["bid_id1"], "Category should not be translated") assert.Equal(t, "20.00_IAB1-4_50s", bidCategory["bid_id2"], "Category should not be translated") assert.Equal(t, "20.00_IAB1-1000_30s", bidCategory["bid_id3"], "Bid should not be rejected") @@ -1085,9 +1186,12 @@ func TestCategoryDedupe(t *testing.T) { adapterBids[bidderName1] = &seatBid - bidCategory, adapterBids, err := applyCategoryMapping(nil, requestExt, adapterBids, categoriesFetcher, targData) + bidCategory, adapterBids, rejections, err := applyCategoryMapping(nil, requestExt, adapterBids, categoriesFetcher, targData) assert.Equal(t, nil, err, "Category mapping error should be empty") + assert.Equal(t, 2, len(rejections), "There should be 2 bid rejection messages") + assert.Regexpf(t, regexp.MustCompile(`bid rejected \[bid ID: bid_id(1|3)\] reason: Bid was deduplicated`), rejections[0], "Rejection message did not match expected") + assert.Equal(t, "bid rejected [bid ID: bid_id4] reason: Category mapping file for primary ad server: 'freewheel', publisher: '' not found", rejections[1], "Rejection message did not match expected") assert.Equal(t, 2, len(adapterBids[bidderName1].bids), "Bidders number doesn't match") assert.Equal(t, 2, len(bidCategory), "Bidders category mapping doesn't match") @@ -1102,6 +1206,125 @@ func TestCategoryDedupe(t *testing.T) { assert.NotEqual(t, numIterations, selectedBids["bid_id3"], "Bid 3 made it through every time") } +func TestBidRejectionErrors(t *testing.T) { + categoriesFetcher, error := newCategoryFetcher("./test/category-mapping") + if error != nil { + t.Errorf("Failed to create a category Fetcher: %v", error) + } + + requestExt := newExtRequest() + requestExt.Prebid.Targeting.DurationRangeSec = []int{15, 30, 50} + + targData := &targetData{ + priceGranularity: requestExt.Prebid.Targeting.PriceGranularity, + includeWinners: true, + } + + invalidReqExt := newExtRequest() + invalidReqExt.Prebid.Targeting.DurationRangeSec = []int{15, 30, 50} + invalidReqExt.Prebid.Targeting.IncludeBrandCategory.PrimaryAdServer = 2 + invalidReqExt.Prebid.Targeting.IncludeBrandCategory.Publisher = "some_publisher" + + adapterBids := make(map[openrtb_ext.BidderName]*pbsOrtbSeatBid) + bidderName := openrtb_ext.BidderName("appnexus") + + testCases := []struct { + description string + reqExt openrtb_ext.ExtRequest + bids []*openrtb.Bid + duration int + expectedRejections []string + expectedCatDur string + }{ + { + description: "Bid should be rejected due to not containing a category", + reqExt: requestExt, + bids: []*openrtb.Bid{ + {ID: "bid_id1", ImpID: "imp_id1", Price: 10.0000, Cat: []string{}, W: 1, H: 1}, + }, + duration: 30, + expectedRejections: []string{ + "bid rejected [bid ID: bid_id1] reason: Bid did not contain a category", + }, + }, + { + description: "Bid should be rejected due to missing category mapping file", + reqExt: invalidReqExt, + bids: []*openrtb.Bid{ + {ID: "bid_id1", ImpID: "imp_id1", Price: 10.0000, Cat: []string{"IAB1-1"}, W: 1, H: 1}, + }, + duration: 30, + expectedRejections: []string{ + "bid rejected [bid ID: bid_id1] reason: Category mapping file for primary ad server: 'dfp', publisher: 'some_publisher' not found", + }, + }, + { + description: "Bid should be rejected due to duration exceeding maximum", + reqExt: requestExt, + bids: []*openrtb.Bid{ + {ID: "bid_id1", ImpID: "imp_id1", Price: 10.0000, Cat: []string{"IAB1-1"}, W: 1, H: 1}, + }, + duration: 70, + expectedRejections: []string{ + "bid rejected [bid ID: bid_id1] reason: Bid duration exceeds maximum allowed", + }, + }, + { + description: "Bid should be rejected due to duplicate bid", + reqExt: requestExt, + bids: []*openrtb.Bid{ + {ID: "bid_id1", ImpID: "imp_id1", Price: 10.0000, Cat: []string{"IAB1-1"}, W: 1, H: 1}, + {ID: "bid_id1", ImpID: "imp_id1", Price: 10.0000, Cat: []string{"IAB1-1"}, W: 1, H: 1}, + }, + duration: 30, + expectedRejections: []string{ + "bid rejected [bid ID: bid_id1] reason: Bid was deduplicated", + }, + expectedCatDur: "10.00_VideoGames_30s", + }, + } + + for _, test := range testCases { + innerBids := []*pbsOrtbBid{} + for _, bid := range test.bids { + currentBid := pbsOrtbBid{ + bid, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: test.duration}, + } + innerBids = append(innerBids, ¤tBid) + } + + seatBid := pbsOrtbSeatBid{innerBids, "USD", nil, nil} + + adapterBids[bidderName] = &seatBid + + bidCategory, adapterBids, rejections, err := applyCategoryMapping(nil, test.reqExt, adapterBids, categoriesFetcher, targData) + + if len(test.expectedCatDur) > 0 { + // Bid deduplication case + assert.Equal(t, 1, len(adapterBids[bidderName].bids), "Bidders number doesn't match") + assert.Equal(t, 1, len(bidCategory), "Bidders category mapping doesn't match") + assert.Equal(t, test.expectedCatDur, bidCategory["bid_id1"], "Bid category did not contain expected hb_pb_cat_dur") + } else { + assert.Empty(t, adapterBids[bidderName].bids, "Bidders number doesn't match") + assert.Empty(t, bidCategory, "Bidders category mapping doesn't match") + } + + assert.Empty(t, err, "Category mapping error should be empty") + assert.Equal(t, test.expectedRejections, rejections, test.description) + } +} + +func TestUpdateRejections(t *testing.T) { + rejections := []string{} + + rejections = updateRejections(rejections, "bid_id1", "some reason 1") + rejections = updateRejections(rejections, "bid_id2", "some reason 2") + + assert.Equal(t, 2, len(rejections), "Rejections should contain 2 rejection messages") + assert.Containsf(t, rejections, "bid rejected [bid ID: bid_id1] reason: some reason 1", "Rejection message did not match expected") + assert.Containsf(t, rejections, "bid rejected [bid ID: bid_id2] reason: some reason 2", "Rejection message did not match expected") +} + type exchangeSpec struct { IncomingRequest exchangeRequest `json:"incomingRequest"` OutgoingRequests map[string]*bidderSpec `json:"outgoingRequests"` diff --git a/exchange/utils_test.go b/exchange/utils_test.go index 4ccded46c68..edbe04a0d0f 100644 --- a/exchange/utils_test.go +++ b/exchange/utils_test.go @@ -153,7 +153,7 @@ func newAdapterAliasBidRequest(t *testing.T) *openrtb.BidRequest { H: 600, }}, }, - Ext: json.RawMessage(`{"appnexus": {"placementId": 10433394},"brightroll": {"placementId": 105}}`), + Ext: json.RawMessage(`{"appnexus": {"placementId": 1},"brightroll": {"placementId": 105}}`), }}, Ext: json.RawMessage(`{"prebid":{"aliases":{"brightroll":"appnexus"}}}`), } @@ -199,7 +199,7 @@ func newCCPABidRequest(t *testing.T) *openrtb.BidRequest { H: 600, }}, }, - Ext: json.RawMessage(`{"appnexus": {"placementId": 10433394}}`), + Ext: json.RawMessage(`{"appnexus": {"placementId": 1}}`), }}, } } diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go index 80ee84706eb..197260d511e 100644 --- a/openrtb_ext/bidders.go +++ b/openrtb_ext/bidders.go @@ -27,11 +27,13 @@ const ( BidderAdpone BidderName = "adpone" BidderAdtelligent BidderName = "adtelligent" BidderAdvangelists BidderName = "advangelists" + BidderApplogy BidderName = "applogy" BidderAppnexus BidderName = "appnexus" BidderBeachfront BidderName = "beachfront" BidderBrightroll BidderName = "brightroll" BidderConsumable BidderName = "consumable" BidderConversant BidderName = "conversant" + BidderCpmstar BidderName = "cpmstar" BidderDatablocks BidderName = "datablocks" BidderEmxDigital BidderName = "emx_digital" BidderEngageBDR BidderName = "engagebdr" @@ -56,6 +58,7 @@ const ( BidderRTBHouse BidderName = "rtbhouse" BidderRubicon BidderName = "rubicon" BidderSharethrough BidderName = "sharethrough" + BidderSmartRTB BidderName = "smartrtb" BidderSomoaudience BidderName = "somoaudience" BidderSonobi BidderName = "sonobi" BidderSovrn BidderName = "sovrn" @@ -80,11 +83,13 @@ var BidderMap = map[string]BidderName{ "adpone": BidderAdpone, "adtelligent": BidderAdtelligent, "advangelists": BidderAdvangelists, + "applogy": BidderApplogy, "appnexus": BidderAppnexus, "beachfront": BidderBeachfront, "brightroll": BidderBrightroll, "consumable": BidderConsumable, "conversant": BidderConversant, + "cpmstar": BidderCpmstar, "datablocks": BidderDatablocks, "emx_digital": BidderEmxDigital, "engagebdr": BidderEngageBDR, @@ -109,6 +114,7 @@ var BidderMap = map[string]BidderName{ "rtbhouse": BidderRTBHouse, "rubicon": BidderRubicon, "sharethrough": BidderSharethrough, + "smartrtb": BidderSmartRTB, "somoaudience": BidderSomoaudience, "sonobi": BidderSonobi, "sovrn": BidderSovrn, diff --git a/openrtb_ext/imp.go b/openrtb_ext/imp.go index 499d1f631bf..0e8f224b884 100644 --- a/openrtb_ext/imp.go +++ b/openrtb_ext/imp.go @@ -20,6 +20,9 @@ type ExtImp struct { type ExtImpPrebid struct { StoredRequest *ExtStoredRequest `json:"storedrequest"` + // Rewarded inventory signal, can be 0 or 1 + IsRewardedInventory int8 `json:"is_rewarded_inventory"` + // NOTE: This is not part of the official API, we are not expecting clients // migrate from imp[...].ext.${BIDDER} to imp[...].ext.prebid.bidder.${BIDDER} // at this time diff --git a/openrtb_ext/imp_applogy.go b/openrtb_ext/imp_applogy.go new file mode 100644 index 00000000000..45774a05afb --- /dev/null +++ b/openrtb_ext/imp_applogy.go @@ -0,0 +1,5 @@ +package openrtb_ext + +type ExtImpApplogy struct { + Token string `json:"token"` +} diff --git a/openrtb_ext/imp_cpmstar.go b/openrtb_ext/imp_cpmstar.go new file mode 100644 index 00000000000..0b74f4d437d --- /dev/null +++ b/openrtb_ext/imp_cpmstar.go @@ -0,0 +1,6 @@ +package openrtb_ext + +type ExtImpCpmstar struct { + PoolId int `json:"placementId"` + SubPoolId int `json:"subpoolId,omitempty"` +} diff --git a/openrtb_ext/imp_smartrtb.go b/openrtb_ext/imp_smartrtb.go new file mode 100644 index 00000000000..d056046bf9d --- /dev/null +++ b/openrtb_ext/imp_smartrtb.go @@ -0,0 +1,8 @@ +package openrtb_ext + +type ExtImpSmartRTB struct { + PubID string `json:"pub_id,omitempty"` + MedID string `json:"med_id,omitempty"` + ZoneID string `json:"zone_id,omitempty"` + ForceBid bool `json:"force_bid,omitempty"` +} diff --git a/openrtb_ext/imp_synacormedia.go b/openrtb_ext/imp_synacormedia.go index 1b044ceaa9c..af48c7dfd01 100644 --- a/openrtb_ext/imp_synacormedia.go +++ b/openrtb_ext/imp_synacormedia.go @@ -3,4 +3,5 @@ package openrtb_ext // ExtImpSynacormedia defines the contract for bidrequest.imp[i].ext.synacormedia type ExtImpSynacormedia struct { SeatId string `json:"seatId"` + TagId string `json:"tagId"` } diff --git a/pbs/pbsrequest_test.go b/pbs/pbsrequest_test.go index 3e3b37b9fad..52cd6153323 100644 --- a/pbs/pbsrequest_test.go +++ b/pbs/pbsrequest_test.go @@ -199,7 +199,7 @@ var dummyConfig = ` "bidder": "appnexus", "bid_id": "22222224", "params": { - "placementId": "10433394" + "placementId": "1" } } ] diff --git a/prebid_cache_client/client.go b/prebid_cache_client/client.go index 6da69f68243..a5730ce7914 100644 --- a/prebid_cache_client/client.go +++ b/prebid_cache_client/client.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "encoding/json" + "errors" "fmt" "io/ioutil" "net/http" @@ -46,14 +47,9 @@ type Cacheable struct { Key string } -func NewClient(conf *config.Cache, extCache *config.ExternalCache, metrics pbsmetrics.MetricsEngine) Client { +func NewClient(httpClient *http.Client, conf *config.Cache, extCache *config.ExternalCache, metrics pbsmetrics.MetricsEngine) Client { return &clientImpl{ - httpClient: &http.Client{ - Transport: &http.Transport{ - MaxIdleConns: 10, - IdleConnTimeout: 65, - }, - }, + httpClient: httpClient, putUrl: conf.GetBaseURL() + "/cache", externalCacheHost: extCache.Host, externalCachePath: extCache.Path, @@ -92,15 +88,13 @@ func (c *clientImpl) PutJson(ctx context.Context, values []Cacheable) (uuids []s postBody, err := encodeValues(values) if err != nil { - glog.Errorf("Error creating JSON for prebid cache: %v", err) - errs = append(errs, fmt.Errorf("Error creating JSON for prebid cache: %v", err)) + logError(&errs, "Error creating JSON for prebid cache: %v", err) return uuidsToReturn, errs } httpReq, err := http.NewRequest("POST", c.putUrl, bytes.NewReader(postBody)) if err != nil { - glog.Errorf("Error creating POST request to prebid cache: %v", err) - errs = append(errs, fmt.Errorf("Error creating POST request to prebid cache: %v", err)) + logError(&errs, "Error creating POST request to prebid cache: %v", err) return uuidsToReturn, errs } @@ -112,9 +106,7 @@ func (c *clientImpl) PutJson(ctx context.Context, values []Cacheable) (uuids []s elapsedTime := time.Since(startTime) if err != nil { c.metrics.RecordPrebidCacheRequestTime(false, elapsedTime) - friendlyErr := fmt.Errorf("Error sending the request to Prebid Cache: %v; Duration=%v", err, elapsedTime) - glog.Error(friendlyErr) - errs = append(errs, friendlyErr) + logError(&errs, "Error sending the request to Prebid Cache: %v; Duration=%v, Items=%v, Payload Size=%v", err, elapsedTime, len(values), len(postBody)) return uuidsToReturn, errs } defer anResp.Body.Close() @@ -122,23 +114,19 @@ func (c *clientImpl) PutJson(ctx context.Context, values []Cacheable) (uuids []s responseBody, err := ioutil.ReadAll(anResp.Body) if anResp.StatusCode != 200 { - glog.Errorf("Prebid Cache call to %s returned %d: %s", putURL, anResp.StatusCode, responseBody) - errs = append(errs, fmt.Errorf("Prebid Cache call to %s returned %d: %s", putURL, anResp.StatusCode, responseBody)) + logError(&errs, "Prebid Cache call to %s returned %d: %s", putURL, anResp.StatusCode, responseBody) return uuidsToReturn, errs } currentIndex := 0 processResponse := func(uuidObj []byte, _ jsonparser.ValueType, _ int, err error) { if uuid, valueType, _, err := jsonparser.Get(uuidObj, "uuid"); err != nil { - glog.Errorf("Prebid Cache returned a bad value at index %d. Error was: %v. Response body was: %s", currentIndex, err, string(responseBody)) - errs = append(errs, fmt.Errorf("Prebid Cache returned a bad value at index %d. Error was: %v. Response body was: %s", currentIndex, err, string(responseBody))) + logError(&errs, "Prebid Cache returned a bad value at index %d. Error was: %v. Response body was: %s", currentIndex, err, string(responseBody)) } else if valueType != jsonparser.String { - glog.Errorf("Prebid Cache returned a %v at index %d in: %v", valueType, currentIndex, string(responseBody)) - errs = append(errs, fmt.Errorf("Prebid Cache returned a %v at index %d in: %v", valueType, currentIndex, string(responseBody))) + logError(&errs, "Prebid Cache returned a %v at index %d in: %v", valueType, currentIndex, string(responseBody)) } else { if uuidsToReturn[currentIndex], err = jsonparser.ParseString(uuid); err != nil { - glog.Errorf("Prebid Cache response index %d could not be parsed as string: %v", currentIndex, err) - errs = append(errs, fmt.Errorf("Prebid Cache response index %d could not be parsed as string: %v", currentIndex, err)) + logError(&errs, "Prebid Cache response index %d could not be parsed as string: %v", currentIndex, err) uuidsToReturn[currentIndex] = "" } } @@ -146,17 +134,20 @@ func (c *clientImpl) PutJson(ctx context.Context, values []Cacheable) (uuids []s } if _, err := jsonparser.ArrayEach(responseBody, processResponse, "responses"); err != nil { - glog.Errorf("Error interpreting Prebid Cache response: %v\nResponse was: %s", err, string(responseBody)) - errs = append(errs, fmt.Errorf("Error interpreting Prebid Cache response: %v\nResponse was: %s", err, string(responseBody))) + logError(&errs, "Error interpreting Prebid Cache response: %v\nResponse was: %s", err, string(responseBody)) return uuidsToReturn, errs } return uuidsToReturn, errs } +func logError(errs *[]error, format string, a ...interface{}) { + msg := fmt.Sprintf(format, a...) + glog.Error(msg) + *errs = append(*errs, errors.New(msg)) +} + func encodeValues(values []Cacheable) ([]byte, error) { - // This function assumes that m is non-nil and has at least one element. - // clientImp.PutBids should respect this. var buf bytes.Buffer buf.WriteString(`{"puts":[`) for i := 0; i < len(values); i++ { diff --git a/prebid_cache_client/client_test.go b/prebid_cache_client/client_test.go index d3b5ee4bfaf..5840d4ea564 100644 --- a/prebid_cache_client/client_test.go +++ b/prebid_cache_client/client_test.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "encoding/json" + "fmt" "net/http" "net/http/httptest" "strconv" @@ -17,7 +18,6 @@ import ( "github.com/stretchr/testify/mock" ) -// Prevents #197 func TestEmptyPut(t *testing.T) { handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { t.Errorf("The server should not be called.") @@ -72,32 +72,70 @@ func TestBadResponse(t *testing.T) { } func TestCancelledContext(t *testing.T) { - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + testCases := []struct { + description string + cacheable []Cacheable + expectedItems int + expectedPayloadSize int + }{ + { + description: "1 Item", + cacheable: []Cacheable{ + { + Type: TypeJSON, + Data: json.RawMessage("true"), + }, + }, + expectedItems: 1, + expectedPayloadSize: 39, + }, + { + description: "2 Items", + cacheable: []Cacheable{ + { + Type: TypeJSON, + Data: json.RawMessage("true"), + }, + { + Type: TypeJSON, + Data: json.RawMessage("false"), + }, + }, + expectedItems: 2, + expectedPayloadSize: 69, + }, + } + + // Initialize Stub Server + stubHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) }) - server := httptest.NewServer(handler) - defer server.Close() + stubServer := httptest.NewServer(stubHandler) + defer stubServer.Close() - metricsMock := &pbsmetrics.MetricsEngineMock{} - metricsMock.On("RecordPrebidCacheRequestTime", false, mock.Anything).Once() + // Run Tests + for _, testCase := range testCases { + metricsMock := &pbsmetrics.MetricsEngineMock{} + metricsMock.On("RecordPrebidCacheRequestTime", false, mock.Anything).Once() - client := &clientImpl{ - httpClient: server.Client(), - putUrl: server.URL, - metrics: metricsMock, - } + client := &clientImpl{ + httpClient: stubServer.Client(), + putUrl: stubServer.URL, + metrics: metricsMock, + } - ctx, cancel := context.WithCancel(context.Background()) - cancel() - ids, _ := client.PutJson(ctx, []Cacheable{{ - Type: TypeJSON, - Data: json.RawMessage("true"), - }, - }) - assertIntEqual(t, len(ids), 1) - assertStringEqual(t, ids[0], "") + ctx, cancel := context.WithCancel(context.Background()) + cancel() + ids, errs := client.PutJson(ctx, testCase.cacheable) - metricsMock.AssertExpectations(t) + expectedErrorMessage := fmt.Sprintf("Items=%v, Payload Size=%v", testCase.expectedItems, testCase.expectedPayloadSize) + + assert.Equal(t, testCase.expectedItems, len(ids), testCase.description+":ids") + assert.Len(t, errs, 1) + assert.Contains(t, errs[0].Error(), "Error sending the request to Prebid Cache: context canceled", testCase.description+":error") + assert.Contains(t, errs[0].Error(), expectedErrorMessage, testCase.description+":error_dimensions") + metricsMock.AssertExpectations(t) + } } func TestSuccessfulPut(t *testing.T) { @@ -195,11 +233,9 @@ func TestStripCacheHostAndPath(t *testing.T) { }, } for _, test := range testInput { - //start client - cacheClient := NewClient(&inCacheURL, &test.inExtCacheURL, &metricsConf.DummyMetricsEngine{}) + cacheClient := NewClient(&http.Client{}, &inCacheURL, &test.inExtCacheURL, &metricsConf.DummyMetricsEngine{}) cHost, cPath := cacheClient.GetExtCacheData() - //assert assert.Equal(t, test.expectedHost, cHost) assert.Equal(t, test.expectedPath, cPath) } diff --git a/router/router.go b/router/router.go index 1994639110c..449ab65a448 100644 --- a/router/router.go +++ b/router/router.go @@ -183,7 +183,7 @@ func New(cfg *config.Configuration, rateConvertor *currencies.RateConverter) (r glog.Infof("Could not read certificates file: %s \n", readCertErr.Error()) } - theClient := &http.Client{ + generalHttpClient := &http.Client{ Transport: &http.Transport{ MaxIdleConns: cfg.Client.MaxIdleConns, MaxIdleConnsPerHost: cfg.Client.MaxIdleConnsPerHost, @@ -191,13 +191,22 @@ func New(cfg *config.Configuration, rateConvertor *currencies.RateConverter) (r TLSClientConfig: &tls.Config{RootCAs: certPool}, }, } + + cacheHttpClient := &http.Client{ + Transport: &http.Transport{ + MaxIdleConns: cfg.CacheClient.MaxIdleConns, + MaxIdleConnsPerHost: cfg.CacheClient.MaxIdleConnsPerHost, + IdleConnTimeout: time.Duration(cfg.CacheClient.IdleConnTimeout) * time.Second, + }, + } + // Hack because of how legacy handles districtm legacyBidderList := openrtb_ext.BidderList() legacyBidderList = append(legacyBidderList, openrtb_ext.BidderName("districtm")) // Metrics engine r.MetricsEngine = metricsConf.NewMetricsEngine(cfg, legacyBidderList) - db, shutdown, fetcher, ampFetcher, categoriesFetcher, videoFetcher := storedRequestsConf.NewStoredRequests(cfg, r.MetricsEngine, theClient, r.Router) + db, shutdown, fetcher, ampFetcher, categoriesFetcher, videoFetcher := storedRequestsConf.NewStoredRequests(cfg, r.MetricsEngine, generalHttpClient, r.Router) // todo(zachbadgett): better shutdown r.Shutdown = shutdown @@ -223,10 +232,11 @@ func New(cfg *config.Configuration, rateConvertor *currencies.RateConverter) (r defaultAliases, defReqJSON := readDefaultRequest(cfg.DefReqConfig) syncers := usersyncers.NewSyncerMap(cfg) - gdprPerms := gdpr.NewPermissions(context.Background(), cfg.GDPR, adapters.GDPRAwareSyncerIDs(syncers), theClient) + gdprPerms := gdpr.NewPermissions(context.Background(), cfg.GDPR, adapters.GDPRAwareSyncerIDs(syncers), generalHttpClient) exchanges = newExchangeMap(cfg) - theExchange := exchange.NewExchange(theClient, pbc.NewClient(&cfg.CacheURL, &cfg.ExtCacheURL, r.MetricsEngine), cfg, r.MetricsEngine, bidderInfos, gdprPerms, rateConvertor) + cacheClient := pbc.NewClient(cacheHttpClient, &cfg.CacheURL, &cfg.ExtCacheURL, r.MetricsEngine) + theExchange := exchange.NewExchange(generalHttpClient, cacheClient, cfg, r.MetricsEngine, bidderInfos, gdprPerms, rateConvertor) openrtbEndpoint, err := openrtb2.NewEndpoint(theExchange, paramsValidator, fetcher, categoriesFetcher, cfg, r.MetricsEngine, pbsAnalytics, disabledBidders, defReqJSON, activeBiddersMap) diff --git a/static/bidder-info/applogy.yaml b/static/bidder-info/applogy.yaml new file mode 100644 index 00000000000..bb908c94e70 --- /dev/null +++ b/static/bidder-info/applogy.yaml @@ -0,0 +1,13 @@ +maintainer: + email: work@applogy.com +capabilities: + app: + mediaTypes: + - banner + - video + - native + site: + mediaTypes: + - banner + - video + - native diff --git a/static/bidder-info/cpmstar.yaml b/static/bidder-info/cpmstar.yaml new file mode 100644 index 00000000000..097dfddd5b0 --- /dev/null +++ b/static/bidder-info/cpmstar.yaml @@ -0,0 +1,11 @@ +maintainer: + email: "prebid@cpmstar.com" +capabilities: + app: + mediaTypes: + - banner + - video + site: + mediaTypes: + - banner + - video diff --git a/static/bidder-info/smartrtb.yaml b/static/bidder-info/smartrtb.yaml new file mode 100644 index 00000000000..c26184f91b7 --- /dev/null +++ b/static/bidder-info/smartrtb.yaml @@ -0,0 +1,11 @@ +maintainer: + email: "engineering@smrtb.com" +capabilities: + app: + mediaTypes: + - banner + - video + site: + mediaTypes: + - banner + - video diff --git a/static/bidder-params/applogy.json b/static/bidder-params/applogy.json new file mode 100644 index 00000000000..2650640c115 --- /dev/null +++ b/static/bidder-params/applogy.json @@ -0,0 +1,13 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Applogy Adapter Params", + "description": "A schema which validates params accepted by the Applogy adapter", + "type": "object", + "properties": { + "token": { + "type": "string", + "description": "Applogy token" + } + }, + "required": ["token"] +} diff --git a/static/bidder-params/cpmstar.json b/static/bidder-params/cpmstar.json new file mode 100644 index 00000000000..576b503e793 --- /dev/null +++ b/static/bidder-params/cpmstar.json @@ -0,0 +1,19 @@ + +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Cpmstar Adapter Params", + "description": "Schema to validate params accepted by the Cpmstar adapter", + + "type": "object", + "properties": { + "placementId": { + "type": "integer", + "description": "Cpmstar-specific ID for ad pool" + }, + "subpoolId": { + "type": "integer", + "description": "Cpmstar-specific ID for ad subpool" + } + }, + "required": ["placementId"] + } diff --git a/static/bidder-params/smartrtb.json b/static/bidder-params/smartrtb.json new file mode 100644 index 00000000000..3bbaab10736 --- /dev/null +++ b/static/bidder-params/smartrtb.json @@ -0,0 +1,27 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "SmartRTB Adapter Params", + "description": "Required parameters for the SmartRTB server adapter", + "type": "object", + "properties": { + "pub_id": { + "type": "string", + "description": "Assigned publisher ID", + "minLength": 4 + }, + "med_id": { + "type": "string", + "description": "Property ID not zone ID not provided" + }, + "zone_id": { + "type": "string", + "description": "Specific zone ID for this placement, belonging to app/site", + "minLength": 20 + }, + "force_bid": { + "type": "boolean", + "description": "Force bids with a test creative" + } + }, + "required": [ "pub_id" ] + } diff --git a/static/bidder-params/synacormedia.json b/static/bidder-params/synacormedia.json index b2dff8faca1..8c74ada2e85 100644 --- a/static/bidder-params/synacormedia.json +++ b/static/bidder-params/synacormedia.json @@ -8,6 +8,10 @@ "seatId": { "type": "string", "description": "The seat id." + }, + "tagId": { + "type": "string", + "description": "The tag id." } }, diff --git a/static/bidder-params/ucfunnel.json b/static/bidder-params/ucfunnel.json index 32acc4002f6..4ee75ec7ac3 100644 --- a/static/bidder-params/ucfunnel.json +++ b/static/bidder-params/ucfunnel.json @@ -12,6 +12,5 @@ "type": "string", "description": "ID for partner" } - }, - "required": ["adunitid"] + } } diff --git a/usersync/usersyncers/syncer.go b/usersync/usersyncers/syncer.go index c459ff1d510..347857e2024 100644 --- a/usersync/usersyncers/syncer.go +++ b/usersync/usersyncers/syncer.go @@ -19,6 +19,7 @@ import ( "github.com/prebid/prebid-server/adapters/brightroll" "github.com/prebid/prebid-server/adapters/consumable" "github.com/prebid/prebid-server/adapters/conversant" + "github.com/prebid/prebid-server/adapters/cpmstar" "github.com/prebid/prebid-server/adapters/datablocks" "github.com/prebid/prebid-server/adapters/emx_digital" "github.com/prebid/prebid-server/adapters/engagebdr" @@ -40,6 +41,7 @@ import ( "github.com/prebid/prebid-server/adapters/rtbhouse" "github.com/prebid/prebid-server/adapters/rubicon" "github.com/prebid/prebid-server/adapters/sharethrough" + "github.com/prebid/prebid-server/adapters/smartrtb" "github.com/prebid/prebid-server/adapters/somoaudience" "github.com/prebid/prebid-server/adapters/sonobi" "github.com/prebid/prebid-server/adapters/sovrn" @@ -75,6 +77,7 @@ func NewSyncerMap(cfg *config.Configuration) map[openrtb_ext.BidderName]usersync insertIntoMap(cfg, syncers, openrtb_ext.BidderBrightroll, brightroll.NewBrightrollSyncer) insertIntoMap(cfg, syncers, openrtb_ext.BidderConsumable, consumable.NewConsumableSyncer) insertIntoMap(cfg, syncers, openrtb_ext.BidderConversant, conversant.NewConversantSyncer) + insertIntoMap(cfg, syncers, openrtb_ext.BidderCpmstar, cpmstar.NewCpmstarSyncer) insertIntoMap(cfg, syncers, openrtb_ext.BidderDatablocks, datablocks.NewDatablocksSyncer) insertIntoMap(cfg, syncers, openrtb_ext.BidderEmxDigital, emx_digital.NewEMXDigitalSyncer) insertIntoMap(cfg, syncers, openrtb_ext.BidderEngageBDR, engagebdr.NewEngageBDRSyncer) @@ -100,6 +103,7 @@ func NewSyncerMap(cfg *config.Configuration) map[openrtb_ext.BidderName]usersync insertIntoMap(cfg, syncers, openrtb_ext.BidderSomoaudience, somoaudience.NewSomoaudienceSyncer) insertIntoMap(cfg, syncers, openrtb_ext.BidderSonobi, sonobi.NewSonobiSyncer) insertIntoMap(cfg, syncers, openrtb_ext.BidderSovrn, sovrn.NewSovrnSyncer) + insertIntoMap(cfg, syncers, openrtb_ext.BidderSmartRTB, smartrtb.NewSmartRTBSyncer) insertIntoMap(cfg, syncers, openrtb_ext.BidderSynacormedia, synacormedia.NewSynacorMediaSyncer) insertIntoMap(cfg, syncers, openrtb_ext.BidderTriplelift, triplelift.NewTripleliftSyncer) insertIntoMap(cfg, syncers, openrtb_ext.BidderTripleliftNative, triplelift_native.NewTripleliftSyncer) diff --git a/usersync/usersyncers/syncer_test.go b/usersync/usersyncers/syncer_test.go index b120711fb78..f00d4c9c7b5 100644 --- a/usersync/usersyncers/syncer_test.go +++ b/usersync/usersyncers/syncer_test.go @@ -26,6 +26,7 @@ func TestNewSyncerMap(t *testing.T) { string(openrtb_ext.BidderBrightroll): syncConfig, string(openrtb_ext.BidderConsumable): syncConfig, string(openrtb_ext.BidderConversant): syncConfig, + string(openrtb_ext.BidderCpmstar): syncConfig, string(openrtb_ext.BidderDatablocks): syncConfig, string(openrtb_ext.BidderEmxDigital): syncConfig, string(openrtb_ext.BidderEngageBDR): syncConfig, @@ -51,6 +52,7 @@ func TestNewSyncerMap(t *testing.T) { string(openrtb_ext.BidderSomoaudience): syncConfig, string(openrtb_ext.BidderSonobi): syncConfig, string(openrtb_ext.BidderSovrn): syncConfig, + string(openrtb_ext.BidderSmartRTB): syncConfig, string(openrtb_ext.BidderSynacormedia): syncConfig, string(openrtb_ext.BidderTriplelift): syncConfig, string(openrtb_ext.BidderTripleliftNative): syncConfig, @@ -64,6 +66,7 @@ func TestNewSyncerMap(t *testing.T) { } adaptersWithoutSyncers := map[openrtb_ext.BidderName]bool{ + openrtb_ext.BidderApplogy: true, openrtb_ext.BidderTappx: true, openrtb_ext.BidderKubient: true, openrtb_ext.BidderPubnative: true,