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