github.com/prebid/prebid-server@v0.275.0/adapters/kubient/kubient.go (about) 1 package kubient 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 8 "github.com/prebid/openrtb/v19/openrtb2" 9 "github.com/prebid/prebid-server/config" 10 "github.com/prebid/prebid-server/openrtb_ext" 11 12 "github.com/prebid/prebid-server/adapters" 13 "github.com/prebid/prebid-server/errortypes" 14 ) 15 16 // Builder builds a new instance of the Kubient adapter for the given bidder with the given config. 17 func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { 18 bidder := &KubientAdapter{ 19 endpoint: config.Endpoint, 20 } 21 return bidder, nil 22 } 23 24 // Implements Bidder interface. 25 type KubientAdapter struct { 26 endpoint string 27 } 28 29 // MakeRequests prepares the HTTP requests which should be made to fetch bids. 30 func (adapter *KubientAdapter) MakeRequests( 31 openRTBRequest *openrtb2.BidRequest, 32 reqInfo *adapters.ExtraRequestInfo, 33 ) ([]*adapters.RequestData, []error) { 34 if len(openRTBRequest.Imp) == 0 { 35 return nil, []error{&errortypes.BadInput{ 36 Message: "No impression in the bid request", 37 }} 38 } 39 errs := make([]error, 0, len(openRTBRequest.Imp)) 40 hasErrors := false 41 for _, impObj := range openRTBRequest.Imp { 42 err := checkImpExt(impObj) 43 if err != nil { 44 errs = append(errs, err) 45 hasErrors = true 46 } 47 } 48 if hasErrors { 49 return nil, errs 50 } 51 openRTBRequestJSON, err := json.Marshal(openRTBRequest) 52 if err != nil { 53 errs = append(errs, err) 54 return nil, errs 55 } 56 57 headers := http.Header{} 58 headers.Add("Content-Type", "application/json;charset=utf-8") 59 requestsToBidder := []*adapters.RequestData{{ 60 Method: "POST", 61 Uri: adapter.endpoint, 62 Body: openRTBRequestJSON, 63 Headers: headers, 64 }} 65 return requestsToBidder, errs 66 } 67 68 func checkImpExt(impObj openrtb2.Imp) error { 69 var bidderExt adapters.ExtImpBidder 70 if err := json.Unmarshal(impObj.Ext, &bidderExt); err != nil { 71 return &errortypes.BadInput{ 72 Message: "ext.bidder not provided", 73 } 74 } 75 var kubientExt openrtb_ext.ExtImpKubient 76 if err := json.Unmarshal(bidderExt.Bidder, &kubientExt); err != nil { 77 return &errortypes.BadInput{ 78 Message: "ext.bidder.zoneid is not provided", 79 } 80 } 81 if kubientExt.ZoneID == "" { 82 return &errortypes.BadInput{ 83 Message: "zoneid is empty", 84 } 85 } 86 return nil 87 } 88 89 // MakeBids makes the bids 90 func (adapter *KubientAdapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { 91 var errs []error 92 93 if response.StatusCode == http.StatusNoContent { 94 return nil, nil 95 } 96 97 if response.StatusCode == http.StatusBadRequest { 98 return nil, []error{&errortypes.BadInput{ 99 Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode), 100 }} 101 } 102 103 if response.StatusCode != http.StatusOK { 104 return nil, []error{&errortypes.BadServerResponse{ 105 Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode), 106 }} 107 } 108 109 var bidResp openrtb2.BidResponse 110 111 if err := json.Unmarshal(response.Body, &bidResp); err != nil { 112 return nil, []error{err} 113 } 114 115 bidResponse := adapters.NewBidderResponseWithBidsCapacity(5) 116 117 for _, sb := range bidResp.SeatBid { 118 for i := range sb.Bid { 119 bidType, err := getMediaTypeForImp(sb.Bid[i].ImpID, internalRequest.Imp) 120 if err != nil { 121 errs = append(errs, err) 122 } else { 123 b := &adapters.TypedBid{ 124 Bid: &sb.Bid[i], 125 BidType: bidType, 126 } 127 bidResponse.Bids = append(bidResponse.Bids, b) 128 } 129 } 130 } 131 return bidResponse, errs 132 } 133 134 func getMediaTypeForImp(impID string, imps []openrtb2.Imp) (openrtb_ext.BidType, error) { 135 mediaType := openrtb_ext.BidTypeBanner 136 for _, imp := range imps { 137 if imp.ID == impID { 138 if imp.Banner == nil && imp.Video != nil { 139 mediaType = openrtb_ext.BidTypeVideo 140 } 141 return mediaType, nil 142 } 143 } 144 145 // This shouldnt happen. Lets handle it just incase by returning an error. 146 return "", &errortypes.BadInput{ 147 Message: fmt.Sprintf("Failed to find impression \"%s\" ", impID), 148 } 149 }