@@ -96,6 +96,7 @@ func NewExchange(client *http.Client, cache prebid_cache_client.Client, cfg *con
96
96
97
97
func (e * exchange ) HoldAuction (ctx context.Context , bidRequest * openrtb.BidRequest , usersyncs IdFetcher , labels pbsmetrics.Labels , account * config.Account , categoriesFetcher * stored_requests.CategoryFetcher , debugLog * DebugLog ) (* openrtb.BidResponse , error ) {
98
98
99
+ var err error
99
100
requestExt , err := extractBidRequestExt (bidRequest )
100
101
if err != nil {
101
102
return nil , err
@@ -114,34 +115,11 @@ func (e *exchange) HoldAuction(ctx context.Context, bidRequest *openrtb.BidReque
114
115
115
116
bidAdjustmentFactors := getExtBidAdjustmentFactors (requestExt )
116
117
117
- for _ , impInRequest := range bidRequest .Imp {
118
- var impLabels pbsmetrics.ImpLabels = pbsmetrics.ImpLabels {
119
- BannerImps : impInRequest .Banner != nil ,
120
- VideoImps : impInRequest .Video != nil ,
121
- AudioImps : impInRequest .Audio != nil ,
122
- NativeImps : impInRequest .Native != nil ,
123
- }
124
- e .me .RecordImps (impLabels )
125
- }
118
+ recordImpMetrics (bidRequest , e .me )
126
119
127
120
// Make our best guess if GDPR applies
128
- usersyncIfAmbiguous := e .UsersyncIfAmbiguous
129
- var geo * openrtb.Geo = nil
130
- if bidRequest .User != nil && bidRequest .User .Geo != nil {
131
- geo = bidRequest .User .Geo
132
- } else if bidRequest .Device != nil && bidRequest .Device .Geo != nil {
133
- geo = bidRequest .Device .Geo
134
- }
135
- if geo != nil {
136
- // If we have a country set, and it is on the list, we assume GDPR applies if not set on the request.
137
- // Otherwise we assume it does not apply as long as it appears "valid" (is 3 characters long).
138
- if _ , found := e .privacyConfig .GDPR .EEACountriesMap [strings .ToUpper (geo .Country )]; found {
139
- usersyncIfAmbiguous = false
140
- } else if len (geo .Country ) == 3 {
141
- // The country field is formatted properly as a three character country code
142
- usersyncIfAmbiguous = true
143
- }
144
- }
121
+ usersyncIfAmbiguous := e .parseUsersyncIfAmbiguous (bidRequest )
122
+
145
123
// Slice of BidRequests, each a copy of the original cleaned to only contain bidder data for the named bidder
146
124
blabels := make (map [openrtb_ext.BidderName ]* pbsmetrics.AdapterLabels )
147
125
cleanRequests , aliases , privacyLabels , errs := cleanOpenRTBRequests (ctx , bidRequest , requestExt , usersyncs , blabels , labels , e .gDPR , usersyncIfAmbiguous , e .privacyConfig )
@@ -161,14 +139,13 @@ func (e *exchange) HoldAuction(ctx context.Context, bidRequest *openrtb.BidReque
161
139
162
140
adapterBids , adapterExtra , anyBidsReturned := e .getAllBids (auctionCtx , cleanRequests , aliases , bidAdjustmentFactors , blabels , conversions )
163
141
164
- var auc * auction = nil
165
- var bidResponseExt * openrtb_ext. ExtBidResponse = nil
142
+ var auc * auction
143
+ var cacheErrs [] error
166
144
if anyBidsReturned {
167
145
168
146
var bidCategory map [string ]string
169
147
//If includebrandcategory is present in ext then CE feature is on.
170
148
if requestExt .Prebid .Targeting != nil && requestExt .Prebid .Targeting .IncludeBrandCategory != nil {
171
- var err error
172
149
var rejections []string
173
150
bidCategory , adapterBids , rejections , err = applyCategoryMapping (ctx , requestExt , adapterBids , * categoriesFetcher , targData )
174
151
if err != nil {
@@ -189,42 +166,33 @@ func (e *exchange) HoldAuction(ctx context.Context, bidRequest *openrtb.BidReque
189
166
errs = append (errs , dealErrs ... )
190
167
}
191
168
192
- if debugLog != nil && debugLog .Enabled {
193
- bidResponseExt = e .makeExtBidResponse (adapterBids , adapterExtra , bidRequest , debugInfo , errs )
194
- if bidRespExtBytes , err := json .Marshal (bidResponseExt ); err == nil {
195
- debugLog .Data .Response = string (bidRespExtBytes )
196
- } else {
197
- debugLog .Data .Response = "Unable to marshal response ext for debugging"
198
- errs = append (errs , errors .New (debugLog .Data .Response ))
199
- }
200
- }
201
-
202
169
cacheErrs := auc .doCache (ctx , e .cache , targData , bidRequest , 60 , & account .CacheTTL , bidCategory , debugLog )
203
170
if len (cacheErrs ) > 0 {
204
171
errs = append (errs , cacheErrs ... )
205
172
}
206
173
targData .setTargeting (auc , bidRequest .App != nil , bidCategory )
207
174
208
- // Ensure caching errors are added if the bid response ext has already been created
209
- if bidResponseExt != nil && len (cacheErrs ) > 0 {
210
- bidderCacheErrs := errsToBidderErrors (cacheErrs )
211
- bidResponseExt .Errors [openrtb_ext .PrebidExtKey ] = append (bidResponseExt .Errors [openrtb_ext .PrebidExtKey ], bidderCacheErrs ... )
212
- }
213
175
}
176
+ }
214
177
178
+ bidResponseExt := e .makeExtBidResponse (adapterBids , adapterExtra , bidRequest , debugInfo , errs )
179
+
180
+ // Ensure caching errors are added in case auc.doCache was called and errors were returned
181
+ if len (cacheErrs ) > 0 {
182
+ bidderCacheErrs := errsToBidderErrors (cacheErrs )
183
+ bidResponseExt .Errors [openrtb_ext .PrebidExtKey ] = append (bidResponseExt .Errors [openrtb_ext .PrebidExtKey ], bidderCacheErrs ... )
215
184
}
216
185
217
- if ! anyBidsReturned {
218
- if debugLog != nil && debugLog .Enabled {
186
+ if debugLog != nil && debugLog .Enabled {
187
+ if bidRespExtBytes , err := json .Marshal (bidResponseExt ); err == nil {
188
+ debugLog .Data .Response = string (bidRespExtBytes )
189
+ } else {
190
+ debugLog .Data .Response = "Unable to marshal response ext for debugging"
191
+ errs = append (errs , err )
192
+ }
193
+ if ! anyBidsReturned {
219
194
if rawUUID , err := uuid .NewV4 (); err == nil {
220
195
debugLog .CacheKey = rawUUID .String ()
221
-
222
- bidResponseExt = e .makeExtBidResponse (adapterBids , adapterExtra , bidRequest , debugInfo , errs )
223
- if bidRespExtBytes , err := json .Marshal (bidResponseExt ); err == nil {
224
- debugLog .Data .Response = string (bidRespExtBytes )
225
- } else {
226
- debugLog .Data .Response = "Unable to marshal response ext for debugging"
227
- }
228
196
} else {
229
197
errs = append (errs , err )
230
198
}
@@ -235,6 +203,41 @@ func (e *exchange) HoldAuction(ctx context.Context, bidRequest *openrtb.BidReque
235
203
return e .buildBidResponse (ctx , liveAdapters , adapterBids , bidRequest , adapterExtra , auc , bidResponseExt , cacheInstructions .returnCreative , errs )
236
204
}
237
205
206
+ func (e * exchange ) parseUsersyncIfAmbiguous (bidRequest * openrtb.BidRequest ) bool {
207
+ usersyncIfAmbiguous := e .UsersyncIfAmbiguous
208
+ var geo * openrtb.Geo = nil
209
+
210
+ if bidRequest .User != nil && bidRequest .User .Geo != nil {
211
+ geo = bidRequest .User .Geo
212
+ } else if bidRequest .Device != nil && bidRequest .Device .Geo != nil {
213
+ geo = bidRequest .Device .Geo
214
+ }
215
+ if geo != nil {
216
+ // If we have a country set, and it is on the list, we assume GDPR applies if not set on the request.
217
+ // Otherwise we assume it does not apply as long as it appears "valid" (is 3 characters long).
218
+ if _ , found := e .privacyConfig .GDPR .EEACountriesMap [strings .ToUpper (geo .Country )]; found {
219
+ usersyncIfAmbiguous = false
220
+ } else if len (geo .Country ) == 3 {
221
+ // The country field is formatted properly as a three character country code
222
+ usersyncIfAmbiguous = true
223
+ }
224
+ }
225
+
226
+ return usersyncIfAmbiguous
227
+ }
228
+
229
+ func recordImpMetrics (bidRequest * openrtb.BidRequest , metricsEngine pbsmetrics.MetricsEngine ) {
230
+ for _ , impInRequest := range bidRequest .Imp {
231
+ var impLabels pbsmetrics.ImpLabels = pbsmetrics.ImpLabels {
232
+ BannerImps : impInRequest .Banner != nil ,
233
+ VideoImps : impInRequest .Video != nil ,
234
+ AudioImps : impInRequest .Audio != nil ,
235
+ NativeImps : impInRequest .Native != nil ,
236
+ }
237
+ metricsEngine .RecordImps (impLabels )
238
+ }
239
+ }
240
+
238
241
type DealTierInfo struct {
239
242
Prefix string `json:"prefix"`
240
243
MinDealTier int `json:"minDealTier"`
@@ -479,6 +482,7 @@ func errsToBidderErrors(errs []error) []openrtb_ext.ExtBidderError {
479
482
// This piece takes all the bids supplied by the adapters and crafts an openRTB response to send back to the requester
480
483
func (e * exchange ) buildBidResponse (ctx context.Context , liveAdapters []openrtb_ext.BidderName , adapterBids map [openrtb_ext.BidderName ]* pbsOrtbSeatBid , bidRequest * openrtb.BidRequest , adapterExtra map [openrtb_ext.BidderName ]* seatResponseExtra , auc * auction , bidResponseExt * openrtb_ext.ExtBidResponse , returnCreative bool , errList []error ) (* openrtb.BidResponse , error ) {
481
484
bidResponse := new (openrtb.BidResponse )
485
+ var err error
482
486
483
487
bidResponse .ID = bidRequest .ID
484
488
if len (liveAdapters ) == 0 {
@@ -500,21 +504,19 @@ func (e *exchange) buildBidResponse(ctx context.Context, liveAdapters []openrtb_
500
504
501
505
bidResponse .SeatBid = seatBids
502
506
503
- if bidResponseExt == nil {
504
- contextDebugValue := ctx .Value (DebugContextKey )
505
- var debugInfo bool
506
- if contextDebugValue != nil {
507
- debugInfo = contextDebugValue .(bool )
508
- }
509
- bidResponseExt = e .makeExtBidResponse (adapterBids , adapterExtra , bidRequest , debugInfo , errList )
510
- }
507
+ bidResponse .Ext , err = encodeBidResponseExt (bidResponseExt )
508
+
509
+ return bidResponse , err
510
+ }
511
+
512
+ func encodeBidResponseExt (bidResponseExt * openrtb_ext.ExtBidResponse ) ([]byte , error ) {
511
513
buffer := & bytes.Buffer {}
512
514
enc := json .NewEncoder (buffer )
515
+
513
516
enc .SetEscapeHTML (false )
514
517
err := enc .Encode (bidResponseExt )
515
- bidResponse .Ext = buffer .Bytes ()
516
518
517
- return bidResponse , err
519
+ return buffer . Bytes () , err
518
520
}
519
521
520
522
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 ) {
0 commit comments