github.com/prebid/prebid-server/v2@v2.18.0/adapters/cpmstar/cpmstar.go (about) 1 package cpmstar 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 8 "github.com/prebid/openrtb/v20/openrtb2" 9 "github.com/prebid/prebid-server/v2/adapters" 10 "github.com/prebid/prebid-server/v2/config" 11 "github.com/prebid/prebid-server/v2/errortypes" 12 "github.com/prebid/prebid-server/v2/openrtb_ext" 13 ) 14 15 type Adapter struct { 16 endpoint string 17 } 18 19 func (a *Adapter) MakeRequests(request *openrtb2.BidRequest, unused *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { 20 var errs []error 21 var adapterRequests []*adapters.RequestData 22 23 if err := preprocess(request); err != nil { 24 errs = append(errs, err) 25 return nil, errs 26 } 27 28 adapterReq, err := a.makeRequest(request) 29 if err != nil { 30 errs = append(errs, err) 31 return nil, errs 32 } 33 34 adapterRequests = append(adapterRequests, adapterReq) 35 36 return adapterRequests, errs 37 } 38 39 func (a *Adapter) makeRequest(request *openrtb2.BidRequest) (*adapters.RequestData, error) { 40 var err error 41 42 jsonBody, err := json.Marshal(request) 43 if err != nil { 44 return nil, err 45 } 46 47 headers := http.Header{} 48 headers.Add("Content-Type", "application/json;charset=utf-8") 49 50 return &adapters.RequestData{ 51 Method: "POST", 52 Uri: a.endpoint, 53 Body: jsonBody, 54 Headers: headers, 55 ImpIDs: openrtb_ext.GetImpIDs(request.Imp), 56 }, nil 57 } 58 59 func preprocess(request *openrtb2.BidRequest) error { 60 if len(request.Imp) == 0 { 61 return &errortypes.BadInput{ 62 Message: "No Imps in Bid Request", 63 } 64 } 65 for i := 0; i < len(request.Imp); i++ { 66 var imp = &request.Imp[i] 67 var bidderExt adapters.ExtImpBidder 68 69 if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil { 70 return &errortypes.BadInput{ 71 Message: err.Error(), 72 } 73 } 74 75 if err := validateImp(imp); err != nil { 76 return err 77 } 78 79 var extImp openrtb_ext.ExtImpCpmstar 80 if err := json.Unmarshal(bidderExt.Bidder, &extImp); err != nil { 81 return &errortypes.BadInput{ 82 Message: err.Error(), 83 } 84 } 85 86 imp.Ext = bidderExt.Bidder 87 } 88 89 return nil 90 } 91 92 func validateImp(imp *openrtb2.Imp) error { 93 if imp.Banner == nil && imp.Video == nil { 94 return &errortypes.BadInput{ 95 Message: "Only Banner and Video bid-types are supported at this time", 96 } 97 } 98 return nil 99 } 100 101 // MakeBids based on cpmstar server response 102 func (a *Adapter) MakeBids(bidRequest *openrtb2.BidRequest, unused *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) { 103 if responseData.StatusCode == http.StatusNoContent { 104 return nil, nil 105 } 106 107 if responseData.StatusCode != http.StatusOK { 108 return nil, []error{&errortypes.BadServerResponse{ 109 Message: fmt.Sprintf("Unexpected HTTP status code: %d. Run with request.debug = 1 for more info", responseData.StatusCode), 110 }} 111 } 112 113 var bidResponse openrtb2.BidResponse 114 115 if err := json.Unmarshal(responseData.Body, &bidResponse); err != nil { 116 return nil, []error{&errortypes.BadServerResponse{ 117 Message: err.Error(), 118 }} 119 } 120 121 if len(bidResponse.SeatBid) == 0 { 122 return nil, nil 123 } 124 125 rv := adapters.NewBidderResponseWithBidsCapacity(len(bidResponse.SeatBid[0].Bid)) 126 var errors []error 127 128 for _, seatbid := range bidResponse.SeatBid { 129 for i := range seatbid.Bid { 130 foundMatchingBid := false 131 bidType := openrtb_ext.BidTypeBanner 132 for _, imp := range bidRequest.Imp { 133 if imp.ID == seatbid.Bid[i].ImpID { 134 foundMatchingBid = true 135 if imp.Banner != nil { 136 bidType = openrtb_ext.BidTypeBanner 137 } else if imp.Video != nil { 138 bidType = openrtb_ext.BidTypeVideo 139 } 140 break 141 } 142 } 143 144 if foundMatchingBid { 145 rv.Bids = append(rv.Bids, &adapters.TypedBid{ 146 Bid: &seatbid.Bid[i], 147 BidType: bidType, 148 }) 149 } else { 150 errors = append(errors, &errortypes.BadServerResponse{ 151 Message: fmt.Sprintf("bid id='%s' could not find valid impid='%s'", seatbid.Bid[i].ID, seatbid.Bid[i].ImpID), 152 }) 153 } 154 } 155 } 156 return rv, errors 157 } 158 159 // Builder builds a new instance of the Cpmstar adapter for the given bidder with the given config. 160 func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { 161 bidder := &Adapter{ 162 endpoint: config.Endpoint, 163 } 164 return bidder, nil 165 }