github.com/prebid/prebid-server/v2@v2.18.0/adapters/consumable/consumable.go (about) 1 package consumable 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 8 "github.com/prebid/prebid-server/v2/adapters" 9 "github.com/prebid/prebid-server/v2/config" 10 "github.com/prebid/prebid-server/v2/errortypes" 11 "github.com/prebid/prebid-server/v2/openrtb_ext" 12 13 "github.com/prebid/openrtb/v20/openrtb2" 14 ) 15 16 type adapter struct { 17 endpoint string 18 } 19 20 func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { 21 var errs []error 22 headers := http.Header{ 23 "Content-Type": {"application/json"}, 24 "Accept": {"application/json"}, 25 } 26 bodyBytes, err := json.Marshal(request) 27 if err != nil { 28 return nil, []error{err} 29 } 30 31 if request.Site != nil { 32 _, consumableExt, err := extractExtensions(request.Imp[0]) 33 if err != nil { 34 return nil, err 35 } 36 if consumableExt.SiteId == 0 && consumableExt.NetworkId == 0 && consumableExt.UnitId == 0 { 37 return nil, []error{&errortypes.FailedToRequestBids{ 38 Message: "SiteId, NetworkId and UnitId are all required for site requests", 39 }} 40 } 41 requests := []*adapters.RequestData{ 42 { 43 Method: "POST", 44 Uri: "https://e.serverbid.com/sb/rtb", 45 Body: bodyBytes, 46 Headers: headers, 47 ImpIDs: openrtb_ext.GetImpIDs(request.Imp), 48 }, 49 } 50 return requests, errs 51 52 } else { 53 _, consumableExt, err := extractExtensions(request.Imp[0]) 54 if err != nil { 55 return nil, err 56 } 57 58 if consumableExt.PlacementId == "" { 59 return nil, []error{&errortypes.FailedToRequestBids{ 60 Message: "PlacementId is required for non-site requests", 61 }} 62 } 63 requests := []*adapters.RequestData{ 64 { 65 Method: "POST", 66 Uri: "https://e.serverbid.com/rtb/bid?s=" + consumableExt.PlacementId, 67 Body: bodyBytes, 68 Headers: headers, 69 ImpIDs: openrtb_ext.GetImpIDs(request.Imp), 70 }, 71 } 72 return requests, errs 73 } 74 75 } 76 func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) { 77 if adapters.IsResponseStatusCodeNoContent(responseData) { 78 return nil, nil 79 } 80 81 if err := adapters.CheckResponseStatusCodeForErrors(responseData); err != nil { 82 return nil, []error{err} 83 } 84 85 var response openrtb2.BidResponse 86 if err := json.Unmarshal(responseData.Body, &response); err != nil { 87 return nil, []error{err} 88 } 89 90 bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp)) 91 bidResponse.Currency = response.Cur 92 var errors []error 93 for _, seatBid := range response.SeatBid { 94 for i, bid := range seatBid.Bid { 95 bidType, err := getMediaTypeForBid(bid) 96 if err != nil { 97 errors = append(errors, err) 98 continue 99 } 100 var bidVideo *openrtb_ext.ExtBidPrebidVideo 101 if bidType == openrtb_ext.BidTypeVideo { 102 bidVideo = &openrtb_ext.ExtBidPrebidVideo{Duration: int(bid.Dur)} 103 } 104 switch bidType { 105 case openrtb_ext.BidTypeAudio: 106 seatBid.Bid[i].MType = openrtb2.MarkupAudio 107 case openrtb_ext.BidTypeVideo: 108 seatBid.Bid[i].MType = openrtb2.MarkupVideo 109 case openrtb_ext.BidTypeBanner: 110 seatBid.Bid[i].MType = openrtb2.MarkupBanner 111 } 112 bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ 113 Bid: &seatBid.Bid[i], 114 BidType: bidType, 115 BidVideo: bidVideo, 116 }) 117 } 118 } 119 return bidResponse, nil 120 } 121 122 func getMediaTypeForBid(bid openrtb2.Bid) (openrtb_ext.BidType, error) { 123 if bid.MType != 0 { 124 switch bid.MType { 125 case openrtb2.MarkupBanner: 126 return openrtb_ext.BidTypeBanner, nil 127 case openrtb2.MarkupVideo: 128 return openrtb_ext.BidTypeVideo, nil 129 case openrtb2.MarkupAudio: 130 return openrtb_ext.BidTypeAudio, nil 131 } 132 } 133 134 return "", &errortypes.BadServerResponse{ 135 Message: fmt.Sprintf("Failed to parse impression \"%s\" mediatype", bid.ImpID), 136 } 137 } 138 139 // Builder builds a new instance of the Consumable adapter for the given bidder with the given config. 140 func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { 141 bidder := &adapter{ 142 endpoint: config.Endpoint, 143 } 144 return bidder, nil 145 } 146 147 func extractExtensions(impression openrtb2.Imp) (*adapters.ExtImpBidder, *openrtb_ext.ExtImpConsumable, []error) { 148 var bidderExt adapters.ExtImpBidder 149 if err := json.Unmarshal(impression.Ext, &bidderExt); err != nil { 150 return nil, nil, []error{&errortypes.BadInput{ 151 Message: err.Error(), 152 }} 153 } 154 155 var consumableExt openrtb_ext.ExtImpConsumable 156 if err := json.Unmarshal(bidderExt.Bidder, &consumableExt); err != nil { 157 return nil, nil, []error{&errortypes.BadInput{ 158 Message: err.Error(), 159 }} 160 } 161 162 return &bidderExt, &consumableExt, nil 163 }