Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
* 'master' of https://github.com/wwwyyy/prebid-server:
  Add account-specific error metrics to setuid endpoint (prebid#2337)
  Add iframe usersync support for ix (prebid#2328)
  Ext Fields Exposed to Bidders (prebid#2331)
  Add redirect sync to richaudienceAdapter (prebid#2343)
  • Loading branch information
w00522253 committed Aug 12, 2022
2 parents 94e04d6 + 150cb67 commit f38fdc5
Show file tree
Hide file tree
Showing 27 changed files with 1,075 additions and 466 deletions.
2 changes: 1 addition & 1 deletion adapters/33across/33across.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ type bidExt struct {
}

type bidTtxExt struct {
MediaType string `json:mediaType,omitempty`
MediaType string `json:"mediaType,omitempty"`
}

// MakeRequests create the object for TTX Reqeust.
Expand Down
16 changes: 14 additions & 2 deletions endpoints/setuid.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ func NewSetUIDEndpoint(cfg *config.Configuration, syncersByBidder map[string]use
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
metricsEngine.RecordSetUid(metrics.SetUidSyncerUnknown)
so.Errors = []error{err}
so.Status = http.StatusBadRequest
return
}
Expand All @@ -71,6 +72,7 @@ func NewSetUIDEndpoint(cfg *config.Configuration, syncersByBidder map[string]use
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
metricsEngine.RecordSetUid(metrics.SetUidBadRequest)
so.Errors = []error{err}
so.Status = http.StatusBadRequest
return
}
Expand All @@ -82,8 +84,17 @@ func NewSetUIDEndpoint(cfg *config.Configuration, syncersByBidder map[string]use
account, fetchErrs := accountService.GetAccount(context.Background(), cfg, accountsFetcher, accountID)
if len(fetchErrs) > 0 {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(combineErrors(fetchErrs).Error()))
metricsEngine.RecordSetUid(metrics.SetUidBadRequest)
err := combineErrors(fetchErrs)
w.Write([]byte(err.Error()))
switch err {
case errCookieSyncAccountBlocked:
metricsEngine.RecordSetUid(metrics.SetUidAccountBlocked)
case errCookieSyncAccountInvalid:
metricsEngine.RecordSetUid(metrics.SetUidAccountInvalid)
default:
metricsEngine.RecordSetUid(metrics.SetUidBadRequest)
}
so.Errors = []error{err}
so.Status = http.StatusBadRequest
return
}
Expand All @@ -99,6 +110,7 @@ func NewSetUIDEndpoint(cfg *config.Configuration, syncersByBidder map[string]use
case http.StatusUnavailableForLegalReasons:
metricsEngine.RecordSetUid(metrics.SetUidGDPRHostCookieBlocked)
}
so.Errors = []error{errors.New(body)}
so.Status = status
return
}
Expand Down
168 changes: 159 additions & 9 deletions endpoints/setuid_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"testing"
"time"

"github.com/prebid/prebid-server/analytics"
"github.com/prebid/prebid-server/config"
"github.com/prebid/prebid-server/gdpr"
"github.com/prebid/prebid-server/metrics"
Expand Down Expand Up @@ -255,10 +256,12 @@ func TestSetUIDEndpoint(t *testing.T) {
},
}

analytics := analyticsConf.NewPBSAnalytics(&config.Analytics{})
metrics := &metricsConf.NilMetricsEngine{}

for _, test := range testCases {
response := doRequest(makeRequest(test.uri, test.existingSyncs), metrics,
test.syncersBidderNameToKey, test.gdprAllowsHostCookies, test.gdprReturnsError, test.gdprMalformed)
response := doRequest(makeRequest(test.uri, test.existingSyncs), analytics, metrics,
test.syncersBidderNameToKey, test.gdprAllowsHostCookies, test.gdprReturnsError, test.gdprMalformed, false)
assert.Equal(t, test.expectedStatusCode, response.Code, "Test Case: %s. /setuid returned unexpected error code", test.description)

if test.expectedSyncs != nil {
Expand Down Expand Up @@ -295,8 +298,10 @@ func TestSetUIDEndpointMetrics(t *testing.T) {
cookies []*usersync.Cookie
syncersBidderNameToKey map[string]string
gdprAllowsHostCookies bool
cfgAccountRequired bool
expectedResponseCode int
expectedMetrics func(*metrics.MetricsEngineMock)
expectedAnalytics func(*MockAnalytics)
}{
{
description: "Success - Sync",
Expand All @@ -309,6 +314,16 @@ func TestSetUIDEndpointMetrics(t *testing.T) {
m.On("RecordSetUid", metrics.SetUidOK).Once()
m.On("RecordSyncerSet", "pubmatic", metrics.SyncerSetUidOK).Once()
},
expectedAnalytics: func(a *MockAnalytics) {
expected := analytics.SetUIDObject{
Status: 200,
Bidder: "pubmatic",
UID: "123",
Errors: []error{},
Success: true,
}
a.On("LogSetUIDObject", &expected).Once()
},
},
{
description: "Success - Unsync",
Expand All @@ -321,6 +336,16 @@ func TestSetUIDEndpointMetrics(t *testing.T) {
m.On("RecordSetUid", metrics.SetUidOK).Once()
m.On("RecordSyncerSet", "pubmatic", metrics.SyncerSetUidCleared).Once()
},
expectedAnalytics: func(a *MockAnalytics) {
expected := analytics.SetUIDObject{
Status: 200,
Bidder: "pubmatic",
UID: "",
Errors: []error{},
Success: true,
}
a.On("LogSetUIDObject", &expected).Once()
},
},
{
description: "Cookie Opted Out",
Expand All @@ -332,6 +357,16 @@ func TestSetUIDEndpointMetrics(t *testing.T) {
expectedMetrics: func(m *metrics.MetricsEngineMock) {
m.On("RecordSetUid", metrics.SetUidOptOut).Once()
},
expectedAnalytics: func(a *MockAnalytics) {
expected := analytics.SetUIDObject{
Status: 401,
Bidder: "",
UID: "",
Errors: []error{},
Success: false,
}
a.On("LogSetUIDObject", &expected).Once()
},
},
{
description: "Unknown Syncer Key",
Expand All @@ -343,6 +378,16 @@ func TestSetUIDEndpointMetrics(t *testing.T) {
expectedMetrics: func(m *metrics.MetricsEngineMock) {
m.On("RecordSetUid", metrics.SetUidSyncerUnknown).Once()
},
expectedAnalytics: func(a *MockAnalytics) {
expected := analytics.SetUIDObject{
Status: 400,
Bidder: "",
UID: "",
Errors: []error{errors.New("The bidder name provided is not supported by Prebid Server")},
Success: false,
}
a.On("LogSetUIDObject", &expected).Once()
},
},
{
description: "Unknown Format",
Expand All @@ -354,6 +399,16 @@ func TestSetUIDEndpointMetrics(t *testing.T) {
expectedMetrics: func(m *metrics.MetricsEngineMock) {
m.On("RecordSetUid", metrics.SetUidBadRequest).Once()
},
expectedAnalytics: func(a *MockAnalytics) {
expected := analytics.SetUIDObject{
Status: 400,
Bidder: "pubmatic",
UID: "",
Errors: []error{errors.New(`"f" query param is invalid. must be "b" or "i"`)},
Success: false,
}
a.On("LogSetUIDObject", &expected).Once()
},
},
{
description: "Prevented By GDPR - Invalid Consent String",
Expand All @@ -365,6 +420,16 @@ func TestSetUIDEndpointMetrics(t *testing.T) {
expectedMetrics: func(m *metrics.MetricsEngineMock) {
m.On("RecordSetUid", metrics.SetUidBadRequest).Once()
},
expectedAnalytics: func(a *MockAnalytics) {
expected := analytics.SetUIDObject{
Status: 400,
Bidder: "pubmatic",
UID: "",
Errors: []error{errors.New("gdpr_consent is required when gdpr=1")},
Success: false,
}
a.On("LogSetUIDObject", &expected).Once()
},
},
{
description: "Prevented By GDPR - Permission Denied By Consent String",
Expand All @@ -376,20 +441,99 @@ func TestSetUIDEndpointMetrics(t *testing.T) {
expectedMetrics: func(m *metrics.MetricsEngineMock) {
m.On("RecordSetUid", metrics.SetUidGDPRHostCookieBlocked).Once()
},
expectedAnalytics: func(a *MockAnalytics) {
expected := analytics.SetUIDObject{
Status: 451,
Bidder: "pubmatic",
UID: "",
Errors: []error{errors.New("The gdpr_consent string prevents cookies from being saved")},
Success: false,
}
a.On("LogSetUIDObject", &expected).Once()
},
},
{
description: "Blocked account",
uri: "/setuid?bidder=pubmatic&uid=123&account=blocked_acct",
cookies: []*usersync.Cookie{},
syncersBidderNameToKey: map[string]string{"pubmatic": "pubmatic"},
gdprAllowsHostCookies: true,
expectedResponseCode: 400,
expectedMetrics: func(m *metrics.MetricsEngineMock) {
m.On("RecordSetUid", metrics.SetUidAccountBlocked).Once()
},
expectedAnalytics: func(a *MockAnalytics) {
expected := analytics.SetUIDObject{
Status: 400,
Bidder: "pubmatic",
UID: "",
Errors: []error{errCookieSyncAccountBlocked},
Success: false,
}
a.On("LogSetUIDObject", &expected).Once()
},
},
{
description: "Invalid account",
uri: "/setuid?bidder=pubmatic&uid=123&account=unknown",
cookies: []*usersync.Cookie{},
syncersBidderNameToKey: map[string]string{"pubmatic": "pubmatic"},
gdprAllowsHostCookies: true,
cfgAccountRequired: true,
expectedResponseCode: 400,
expectedMetrics: func(m *metrics.MetricsEngineMock) {
m.On("RecordSetUid", metrics.SetUidAccountInvalid).Once()
},
expectedAnalytics: func(a *MockAnalytics) {
expected := analytics.SetUIDObject{
Status: 400,
Bidder: "pubmatic",
UID: "",
Errors: []error{errCookieSyncAccountInvalid},
Success: false,
}
a.On("LogSetUIDObject", &expected).Once()
},
},
{
description: "Malformed account",
uri: "/setuid?bidder=pubmatic&uid=123&account=malformed_acct",
cookies: []*usersync.Cookie{},
syncersBidderNameToKey: map[string]string{"pubmatic": "pubmatic"},
gdprAllowsHostCookies: true,
cfgAccountRequired: true,
expectedResponseCode: 400,
expectedMetrics: func(m *metrics.MetricsEngineMock) {
m.On("RecordSetUid", metrics.SetUidBadRequest).Once()
},
expectedAnalytics: func(a *MockAnalytics) {
expected := analytics.SetUIDObject{
Status: 400,
Bidder: "pubmatic",
UID: "",
Errors: []error{errors.New("json: cannot unmarshal string into Go struct field Account.disabled of type bool")},
Success: false,
}
a.On("LogSetUIDObject", &expected).Once()
},
},
}

for _, test := range testCases {
analyticsEngine := &MockAnalytics{}
test.expectedAnalytics(analyticsEngine)

metricsEngine := &metrics.MetricsEngineMock{}
test.expectedMetrics(metricsEngine)

req := httptest.NewRequest("GET", test.uri, nil)
for _, v := range test.cookies {
addCookie(req, v)
}
response := doRequest(req, metricsEngine, test.syncersBidderNameToKey, test.gdprAllowsHostCookies, false, false)
response := doRequest(req, analyticsEngine, metricsEngine, test.syncersBidderNameToKey, test.gdprAllowsHostCookies, false, false, test.cfgAccountRequired)

assert.Equal(t, test.expectedResponseCode, response.Code, test.description)
analyticsEngine.AssertExpectations(t)
metricsEngine.AssertExpectations(t)
}
}
Expand All @@ -400,8 +544,9 @@ func TestOptedOut(t *testing.T) {
cookie.SetOptOut(true)
addCookie(request, cookie)
syncersBidderNameToKey := map[string]string{"pubmatic": "pubmatic"}
analytics := analyticsConf.NewPBSAnalytics(&config.Analytics{})
metrics := &metricsConf.NilMetricsEngine{}
response := doRequest(request, metrics, syncersBidderNameToKey, true, false, false)
response := doRequest(request, analytics, metrics, syncersBidderNameToKey, true, false, false, false)

assert.Equal(t, http.StatusUnauthorized, response.Code)
}
Expand Down Expand Up @@ -537,8 +682,13 @@ func makeRequest(uri string, existingSyncs map[string]string) *http.Request {
return request
}

func doRequest(req *http.Request, metrics metrics.MetricsEngine, syncersBidderNameToKey map[string]string, gdprAllowsHostCookies, gdprReturnsError, gdprReturnsMalformedError bool) *httptest.ResponseRecorder {
cfg := config.Configuration{}
func doRequest(req *http.Request, analytics analytics.PBSAnalyticsModule, metrics metrics.MetricsEngine, syncersBidderNameToKey map[string]string, gdprAllowsHostCookies, gdprReturnsError, gdprReturnsMalformedError, cfgAccountRequired bool) *httptest.ResponseRecorder {
cfg := config.Configuration{
AccountRequired: cfgAccountRequired,
BlacklistedAcctMap: map[string]bool{
"blocked_acct": true,
},
}
cfg.MarshalAccountDefaults()

query := req.URL.Query()
Expand All @@ -557,15 +707,15 @@ func doRequest(req *http.Request, metrics metrics.MetricsEngine, syncersBidderNa
cfg: gdpr.NewTCF2Config(config.TCF2{}, config.AccountGDPR{}),
}.Builder

analytics := analyticsConf.NewPBSAnalytics(&cfg.Analytics)
syncersByBidder := make(map[string]usersync.Syncer)
for bidderName, syncerKey := range syncersBidderNameToKey {
syncersByBidder[bidderName] = fakeSyncer{key: syncerKey, defaultSyncType: usersync.SyncTypeIFrame}
}

fakeAccountsFetcher := FakeAccountsFetcher{AccountData: map[string]json.RawMessage{
"valid_acct": json.RawMessage(`{"disabled":false}`),
"disabled_acct": json.RawMessage(`{"disabled":true}`),
"valid_acct": json.RawMessage(`{"disabled":false}`),
"disabled_acct": json.RawMessage(`{"disabled":true}`),
"malformed_acct": json.RawMessage(`{"disabled":"malformed"}`),
}}

endpoint := NewSetUIDEndpoint(&cfg, syncersByBidder, gdprPermsBuilder, tcf2ConfigBuilder, analytics, fakeAccountsFetcher, metrics)
Expand Down
12 changes: 2 additions & 10 deletions exchange/exchangetest/aliases.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,7 @@
}
],
"ext": {
"prebid": {
"aliases": {
"districtm": "appnexus"
}
}
"prebid": {}
}
}
},
Expand Down Expand Up @@ -94,11 +90,7 @@
}
],
"ext": {
"prebid": {
"aliases": {
"districtm": "appnexus"
}
}
"prebid": {}
}
}
},
Expand Down
Loading

0 comments on commit f38fdc5

Please sign in to comment.