github.com/prebid/prebid-server/v2@v2.18.0/adapters/bidder.go (about) 1 package adapters 2 3 import ( 4 "encoding/base64" 5 "encoding/json" 6 "net/http" 7 8 "github.com/prebid/openrtb/v20/openrtb2" 9 "github.com/prebid/prebid-server/v2/config" 10 "github.com/prebid/prebid-server/v2/currency" 11 "github.com/prebid/prebid-server/v2/metrics" 12 "github.com/prebid/prebid-server/v2/openrtb_ext" 13 ) 14 15 // Bidder describes how to connect to external demand. 16 type Bidder interface { 17 // MakeRequests makes the HTTP requests which should be made to fetch bids. 18 // 19 // Bidder implementations can assume that the incoming BidRequest has: 20 // 21 // 1. Only {Imp.Type, Platform} combinations which are valid, as defined by the static/bidder-info.{bidder}.yaml file. 22 // 2. Imp.Ext of the form {"bidder": params}, where "params" has been validated against the static/bidder-params/{bidder}.json JSON Schema. 23 // 24 // nil return values are acceptable, but nil elements *inside* those slices are not. 25 // 26 // The errors should contain a list of errors which explain why this bidder's bids will be 27 // "subpar" in some way. For example: the request contained ad types which this bidder doesn't support. 28 // 29 // If the error is caused by bad user input, return an errortypes.BadInput. 30 MakeRequests(request *openrtb2.BidRequest, reqInfo *ExtraRequestInfo) ([]*RequestData, []error) 31 32 // MakeBids unpacks the server's response into Bids. 33 // 34 // The bids can be nil (for no bids), but should not contain nil elements. 35 // 36 // The errors should contain a list of errors which explain why this bidder's bids will be 37 // "subpar" in some way. For example: the server response didn't have the expected format. 38 // 39 // If the error was caused by bad user input, return a errortypes.BadInput. 40 // If the error was caused by a bad server response, return a errortypes.BadServerResponse 41 MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *RequestData, response *ResponseData) (*BidderResponse, []error) 42 } 43 44 // TimeoutBidder is used to identify bidders that support timeout notifications. 45 type TimeoutBidder interface { 46 Bidder 47 48 // MakeTimeoutNotification functions much the same as MakeRequests, except it is fed the bidder request that timed out, 49 // and expects that only one notification "request" will be generated. A use case for multiple timeout notifications 50 // has not been anticipated. 51 // 52 // Do note that if MakeRequests returns multiple requests, and more than one of these times out, MakeTimeoutNotice will be called 53 // once for each timed out request. 54 MakeTimeoutNotification(req *RequestData) (*RequestData, []error) 55 } 56 57 // BidderResponse wraps the server's response with the list of bids and the currency used by the bidder. 58 // 59 // Currency declaration is not mandatory but helps to detect an eventual currency mismatch issue. 60 // From the bid response, the bidder accepts a list of valid currencies for the bid. 61 // The currency is the same across all bids. 62 type BidderResponse struct { 63 Currency string 64 Bids []*TypedBid 65 FledgeAuctionConfigs []*openrtb_ext.FledgeAuctionConfig 66 } 67 68 // NewBidderResponseWithBidsCapacity create a new BidderResponse initialising the bids array capacity and the default currency value 69 // to "USD". 70 // 71 // bidsCapacity allows to set initial Bids array capacity. 72 // By default, currency is USD but this behavior might be subject to change. 73 func NewBidderResponseWithBidsCapacity(bidsCapacity int) *BidderResponse { 74 return &BidderResponse{ 75 Currency: "USD", 76 Bids: make([]*TypedBid, 0, bidsCapacity), 77 } 78 } 79 80 // NewBidderResponse create a new BidderResponse initialising the bids array and the default currency value 81 // to "USD". 82 // 83 // By default, Bids capacity will be set to 0. 84 // By default, currency is USD but this behavior might be subject to change. 85 func NewBidderResponse() *BidderResponse { 86 return NewBidderResponseWithBidsCapacity(0) 87 } 88 89 // TypedBid packages the openrtb2.Bid with any bidder-specific information that PBS needs to populate an 90 // openrtb_ext.ExtBidPrebid. 91 // 92 // TypedBid.Bid.Ext will become "response.seatbid[i].bid.ext.bidder" in the final OpenRTB response. 93 // TypedBid.BidMeta will become "response.seatbid[i].bid.ext.prebid.meta" in the final OpenRTB response. 94 // TypedBid.BidType will become "response.seatbid[i].bid.ext.prebid.type" in the final OpenRTB response. 95 // TypedBid.BidVideo will become "response.seatbid[i].bid.ext.prebid.video" in the final OpenRTB response. 96 // TypedBid.DealPriority is optionally provided by adapters and used internally by the exchange to support deal targeted campaigns. 97 // TypedBid.Seat new seat under which the bid should pe placed. Default is adapter name 98 type TypedBid struct { 99 Bid *openrtb2.Bid 100 BidMeta *openrtb_ext.ExtBidPrebidMeta 101 BidType openrtb_ext.BidType 102 BidVideo *openrtb_ext.ExtBidPrebidVideo 103 DealPriority int 104 Seat openrtb_ext.BidderName 105 } 106 107 // RequestData and ResponseData exist so that prebid-server core code can implement its "debug" functionality 108 // uniformly across all Bidders. 109 // It will also let us experiment with valyala/vasthttp vs. net/http without changing every adapter (see #152) 110 111 // ResponseData packages together information from the server's http.Response. 112 type ResponseData struct { 113 StatusCode int 114 Body []byte 115 Headers http.Header 116 } 117 118 // RequestData packages together the fields needed to make an http.Request. 119 type RequestData struct { 120 Method string 121 Uri string 122 Body []byte 123 Headers http.Header 124 ImpIDs []string 125 } 126 127 // ExtImpBidder can be used by Bidders to unmarshal any request.imp[i].ext. 128 type ExtImpBidder struct { 129 Prebid *openrtb_ext.ExtImpPrebid `json:"prebid"` 130 131 // Bidder contain the bidder-specific extension. Each bidder should unmarshal this using their 132 // corresponding openrtb_ext.ExtImp{Bidder} struct. 133 // 134 // For example, the Appnexus Bidder should unmarshal this with an openrtb_ext.ExtImpAppnexus object. 135 // 136 // Bidder implementations may safely assume that this JSON has been validated by their 137 // static/bidder-params/{bidder}.json file. 138 Bidder json.RawMessage `json:"bidder"` 139 140 AuctionEnvironment openrtb_ext.AuctionEnvironmentType `json:"ae,omitempty"` 141 } 142 143 func (r *RequestData) SetBasicAuth(username string, password string) { 144 r.Headers.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(username+":"+password))) 145 } 146 147 type ExtraRequestInfo struct { 148 PbsEntryPoint metrics.RequestType 149 GlobalPrivacyControlHeader string 150 CurrencyConversions currency.Conversions 151 } 152 153 func NewExtraRequestInfo(c currency.Conversions) ExtraRequestInfo { 154 return ExtraRequestInfo{ 155 CurrencyConversions: c, 156 } 157 } 158 159 // ConvertCurrency converts a given amount from one currency to another, or returns: 160 // - Error if the `from` or `to` arguments are malformed or unknown ISO-4217 codes. 161 // - ConversionNotFoundError if the conversion mapping is unknown to Prebid Server 162 // and not provided in the bid request. 163 func (r ExtraRequestInfo) ConvertCurrency(value float64, from, to string) (float64, error) { 164 if rate, err := r.CurrencyConversions.GetRate(from, to); err == nil { 165 return value * rate, nil 166 } else { 167 return 0, err 168 } 169 } 170 171 type Builder func(openrtb_ext.BidderName, config.Adapter, config.Server) (Bidder, error)