Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass Global Privacy Control header to bidders #1789

Merged
merged 9 commits into from
May 19, 2021
3 changes: 2 additions & 1 deletion adapters/bidder.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ func (r *RequestData) SetBasicAuth(username string, password string) {
}

type ExtraRequestInfo struct {
PbsEntryPoint metrics.RequestType
PbsEntryPoint metrics.RequestType
GlobalPrivacyControlHeader string
}

type Builder func(openrtb_ext.BidderName, config.Adapter) (Bidder, error)
15 changes: 9 additions & 6 deletions endpoints/openrtb2/amp_auction.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,13 +182,16 @@ func (deps *endpointDeps) AmpAuction(w http.ResponseWriter, r *http.Request, _ h
return
}

secGPC := r.Header.Get("Sec-GPC")

auctionRequest := exchange.AuctionRequest{
BidRequest: req,
Account: *account,
UserSyncs: usersyncs,
RequestType: labels.RType,
StartTime: start,
LegacyLabels: labels,
BidRequest: req,
Account: *account,
UserSyncs: usersyncs,
RequestType: labels.RType,
StartTime: start,
LegacyLabels: labels,
GlobalPrivacyControlHeader: secGPC,
}

response, err := deps.ex.HoldAuction(ctx, auctionRequest, nil)
Expand Down
17 changes: 10 additions & 7 deletions endpoints/openrtb2/auction.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,14 +173,17 @@ func (deps *endpointDeps) Auction(w http.ResponseWriter, r *http.Request, _ http
return
}

secGPC := r.Header.Get("Sec-GPC")

auctionRequest := exchange.AuctionRequest{
BidRequest: req,
Account: *account,
UserSyncs: usersyncs,
RequestType: labels.RType,
StartTime: start,
LegacyLabels: labels,
Warnings: warnings,
BidRequest: req,
Account: *account,
UserSyncs: usersyncs,
RequestType: labels.RType,
StartTime: start,
LegacyLabels: labels,
Warnings: warnings,
GlobalPrivacyControlHeader: secGPC,
}

response, err := deps.ex.HoldAuction(ctx, auctionRequest, nil)
Expand Down
15 changes: 9 additions & 6 deletions endpoints/openrtb2/video_auction.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,13 +274,16 @@ func (deps *endpointDeps) VideoAuctionEndpoint(w http.ResponseWriter, r *http.Re
return
}

secGPC := r.Header.Get("Sec-GPC")

auctionRequest := exchange.AuctionRequest{
BidRequest: bidReq,
Account: *account,
UserSyncs: usersyncs,
RequestType: labels.RType,
StartTime: start,
LegacyLabels: labels,
BidRequest: bidReq,
Account: *account,
UserSyncs: usersyncs,
RequestType: labels.RType,
StartTime: start,
LegacyLabels: labels,
GlobalPrivacyControlHeader: secGPC,
}

response, err := deps.ex.HoldAuction(ctx, auctionRequest, &debugLog)
Expand Down
13 changes: 13 additions & 0 deletions exchange/bidder.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,19 @@ func (bidder *bidderAdapter) requestBid(ctx context.Context, request *openrtb2.B
return nil, errs
}

if reqInfo.GlobalPrivacyControlHeader == "1" {
for i := 0; i < len(reqData); i++ {
if reqData[i].Headers != nil {
reqHeader := reqData[i].Headers.Clone()
reqHeader.Add("Sec-GPC", reqInfo.GlobalPrivacyControlHeader)
reqData[i].Headers = reqHeader
} else {
reqData[i].Headers = http.Header{}
reqData[i].Headers.Add("Sec-GPC", reqInfo.GlobalPrivacyControlHeader)
}
}
}
SyntaxNode marked this conversation as resolved.
Show resolved Hide resolved
SyntaxNode marked this conversation as resolved.
Show resolved Hide resolved

// Make any HTTP requests in parallel.
// If the bidder only needs to make one, save some cycles by just using the current one.
responseChannel := make(chan *httpCallInfo, len(reqData))
Expand Down
79 changes: 79 additions & 0 deletions exchange/bidder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,85 @@ func TestRequestBidRemovesSensitiveHeaders(t *testing.T) {
assert.ElementsMatch(t, seatBid.httpCalls, expectedHttpCalls)
}

func TestSetGPCHeader(t *testing.T) {
server := httptest.NewServer(mockHandler(200, "getBody", "responseJson"))
defer server.Close()

requestHeaders := http.Header{}
requestHeaders.Add("Content-Type", "application/json")

bidderImpl := &goodSingleBidder{
httpRequest: &adapters.RequestData{
Method: "POST",
Uri: server.URL,
Body: []byte("requestJson"),
Headers: requestHeaders,
},
bidResponse: &adapters.BidderResponse{
Bids: []*adapters.TypedBid{},
},
}

debugInfo := &config.DebugInfo{Allow: true}
ctx := context.Background()
ctx = context.WithValue(ctx, DebugContextKey, true)

bidder := adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.DummyMetricsEngine{}, openrtb_ext.BidderAppnexus, debugInfo)
currencyConverter := currency.NewRateConverter(&http.Client{}, "", time.Duration(0))
seatBid, errs := bidder.requestBid(ctx, &openrtb2.BidRequest{}, "test", 1, currencyConverter.Rates(), &adapters.ExtraRequestInfo{GlobalPrivacyControlHeader: "1"}, true)

expectedHttpCall := []*openrtb_ext.ExtHttpCall{
{
Uri: server.URL,
RequestBody: "requestJson",
RequestHeaders: map[string][]string{"Content-Type": {"application/json"}, "Sec-Gpc": {"1"}},
ResponseBody: "responseJson",
Status: 200,
},
}

assert.Empty(t, errs)
assert.ElementsMatch(t, seatBid.httpCalls, expectedHttpCall)
}

func TestSetGPCHeaderNil(t *testing.T) {
server := httptest.NewServer(mockHandler(200, "getBody", "responseJson"))
defer server.Close()

bidderImpl := &goodSingleBidder{
httpRequest: &adapters.RequestData{
Method: "POST",
Uri: server.URL,
Body: []byte("requestJson"),
Headers: nil,
},
bidResponse: &adapters.BidderResponse{
Bids: []*adapters.TypedBid{},
},
}

debugInfo := &config.DebugInfo{Allow: true}
ctx := context.Background()
ctx = context.WithValue(ctx, DebugContextKey, true)

bidder := adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.DummyMetricsEngine{}, openrtb_ext.BidderAppnexus, debugInfo)
currencyConverter := currency.NewRateConverter(&http.Client{}, "", time.Duration(0))
seatBid, errs := bidder.requestBid(ctx, &openrtb2.BidRequest{}, "test", 1, currencyConverter.Rates(), &adapters.ExtraRequestInfo{GlobalPrivacyControlHeader: "1"}, true)

expectedHttpCall := []*openrtb_ext.ExtHttpCall{
{
Uri: server.URL,
RequestBody: "requestJson",
RequestHeaders: map[string][]string{"Sec-Gpc": {"1"}},
ResponseBody: "responseJson",
Status: 200,
},
}

assert.Empty(t, errs)
assert.ElementsMatch(t, seatBid.httpCalls, expectedHttpCall)
}
SyntaxNode marked this conversation as resolved.
Show resolved Hide resolved

// TestMultiBidder makes sure all the requests get sent, and the responses processed.
// Because this is done in parallel, it should be run under the race detector.
func TestMultiBidder(t *testing.T) {
Expand Down
19 changes: 11 additions & 8 deletions exchange/exchange.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,13 @@ func NewExchange(adapters map[openrtb_ext.BidderName]adaptedBidder, cache prebid
// AuctionRequest holds the bid request for the auction
// and all other information needed to process that request
type AuctionRequest struct {
BidRequest *openrtb2.BidRequest
Account config.Account
UserSyncs IdFetcher
RequestType metrics.RequestType
StartTime time.Time
Warnings []error
BidRequest *openrtb2.BidRequest
Account config.Account
UserSyncs IdFetcher
RequestType metrics.RequestType
StartTime time.Time
Warnings []error
GlobalPrivacyControlHeader string

// LegacyLabels is included here for temporary compatability with cleanOpenRTBRequests
// in HoldAuction until we get to factoring it away. Do not use for anything new.
Expand Down Expand Up @@ -172,7 +173,7 @@ func (e *exchange) HoldAuction(ctx context.Context, r AuctionRequest, debugLog *
// Get currency rates conversions for the auction
conversions := e.currencyConverter.Rates()

adapterBids, adapterExtra, anyBidsReturned := e.getAllBids(auctionCtx, bidderRequests, bidAdjustmentFactors, conversions, r.Account.DebugAllow)
adapterBids, adapterExtra, anyBidsReturned := e.getAllBids(auctionCtx, bidderRequests, bidAdjustmentFactors, conversions, r.Account.DebugAllow, r.GlobalPrivacyControlHeader)

var auc *auction
var cacheErrs []error
Expand Down Expand Up @@ -370,7 +371,8 @@ func (e *exchange) getAllBids(
bidderRequests []BidderRequest,
bidAdjustments map[string]float64,
conversions currency.Conversions,
accountDebugAllowed bool) (
accountDebugAllowed bool,
globalPrivacyControlHeader string) (
map[openrtb_ext.BidderName]*pbsOrtbSeatBid,
map[openrtb_ext.BidderName]*seatResponseExtra, bool) {
// Set up pointers to the bid results
Expand Down Expand Up @@ -401,6 +403,7 @@ func (e *exchange) getAllBids(
}
var reqInfo adapters.ExtraRequestInfo
reqInfo.PbsEntryPoint = bidderRequest.BidderLabels.RType
reqInfo.GlobalPrivacyControlHeader = globalPrivacyControlHeader
bids, err := e.adapterMap[bidderRequest.BidderCoreName].requestBid(ctx, bidderRequest.BidRequest, bidderRequest.BidderName, adjustmentFactor, conversions, &reqInfo, accountDebugAllowed)

// Add in time reporting
Expand Down