github.com/prebid/prebid-server/v2@v2.18.0/adapters/ucfunnel/ucfunnel.go (about) 1 package ucfunnel 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 "net/url" 8 9 "github.com/prebid/openrtb/v20/openrtb2" 10 "github.com/prebid/prebid-server/v2/adapters" 11 "github.com/prebid/prebid-server/v2/config" 12 "github.com/prebid/prebid-server/v2/errortypes" 13 "github.com/prebid/prebid-server/v2/openrtb_ext" 14 ) 15 16 type UcfunnelAdapter struct { 17 URI string 18 } 19 20 // Builder builds a new instance of the Ucfunnel adapter for the given bidder with the given config. 21 func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { 22 bidder := &UcfunnelAdapter{ 23 URI: config.Endpoint, 24 } 25 return bidder, nil 26 } 27 28 func (a *UcfunnelAdapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { 29 if response.StatusCode == http.StatusNoContent { 30 return nil, nil 31 } 32 33 if response.StatusCode == http.StatusBadRequest { 34 return nil, []error{&errortypes.BadInput{ 35 Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode), 36 }} 37 } 38 39 if response.StatusCode != http.StatusOK { 40 return nil, []error{&errortypes.BadServerResponse{ 41 Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode), 42 }} 43 } 44 45 var errs []error 46 var bidResp openrtb2.BidResponse 47 if err := json.Unmarshal(response.Body, &bidResp); err != nil { 48 return nil, []error{err} 49 } 50 51 var bidReq openrtb2.BidRequest 52 if err := json.Unmarshal(externalRequest.Body, &bidReq); err != nil { 53 return nil, []error{err} 54 } 55 56 bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(bidResp.SeatBid[0].Bid)) 57 for _, sb := range bidResp.SeatBid { 58 for i := range sb.Bid { 59 bidType := getBidType(bidReq, sb.Bid[i].ImpID) 60 if (bidType == openrtb_ext.BidTypeBanner) || (bidType == openrtb_ext.BidTypeVideo) { 61 b := &adapters.TypedBid{ 62 Bid: &sb.Bid[i], 63 BidType: bidType, 64 } 65 bidResponse.Bids = append(bidResponse.Bids, b) 66 } 67 } 68 } 69 return bidResponse, errs 70 } 71 72 func (a *UcfunnelAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { 73 errs := make([]error, 0, len(request.Imp)) 74 75 // If all the requests were malformed, don't bother making a server call with no impressions. 76 if len(request.Imp) == 0 { 77 return nil, []error{&errortypes.BadInput{ 78 Message: fmt.Sprintf("No impression in the bid request\n"), 79 }} 80 } 81 82 partnerId, partnerErr := getPartnerId(request) 83 if partnerErr != nil { 84 return nil, partnerErr 85 } 86 87 reqJSON, err := json.Marshal(request) 88 if err != nil { 89 return nil, []error{err} 90 } 91 92 headers := http.Header{} 93 headers.Add("Content-Type", "application/json") 94 95 uri := a.URI + "/" + url.PathEscape(partnerId) + "/request" 96 return []*adapters.RequestData{{ 97 Method: "POST", 98 Uri: uri, 99 Body: reqJSON, 100 Headers: headers, 101 ImpIDs: openrtb_ext.GetImpIDs(request.Imp), 102 }}, errs 103 } 104 105 func getPartnerId(request *openrtb2.BidRequest) (string, []error) { 106 var ext ExtBidderUcfunnel 107 var errs = []error{} 108 err := json.Unmarshal(request.Imp[0].Ext, &ext) 109 if err != nil { 110 errs = append(errs, err) 111 return "", errs 112 } 113 errs = checkBidderParameter(ext) 114 if errs != nil { 115 return "", errs 116 } 117 return ext.Bidder.PartnerId, nil 118 } 119 120 func checkBidderParameter(ext ExtBidderUcfunnel) []error { 121 var errs = []error{} 122 if len(ext.Bidder.PartnerId) == 0 || len(ext.Bidder.AdUnitId) == 0 { 123 errs = append(errs, fmt.Errorf("No PartnerId or AdUnitId in the bid request\n")) 124 return errs 125 } 126 return nil 127 } 128 129 func getBidType(bidReq openrtb2.BidRequest, impid string) openrtb_ext.BidType { 130 for i := range bidReq.Imp { 131 if bidReq.Imp[i].ID == impid { 132 if bidReq.Imp[i].Banner != nil { 133 return openrtb_ext.BidTypeBanner 134 } else if bidReq.Imp[i].Video != nil { 135 return openrtb_ext.BidTypeVideo 136 } else if bidReq.Imp[i].Audio != nil { 137 return openrtb_ext.BidTypeAudio 138 } else if bidReq.Imp[i].Native != nil { 139 return openrtb_ext.BidTypeNative 140 } 141 } 142 } 143 return openrtb_ext.BidTypeNative 144 } 145 146 type ExtBidderUcfunnel struct { 147 Bidder openrtb_ext.ExtImpUcfunnel `json:"bidder"` 148 }