github.com/prebid/prebid-server@v0.275.0/adapters/unruly/unruly.go (about) 1 package unruly 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 adapter struct { 16 endPoint string 17 } 18 19 // Builder builds a new instance of the Unruly adapter for the given bidder with the given config. 20 func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { 21 bidder := &adapter{ 22 endPoint: config.Endpoint, 23 } 24 return bidder, nil 25 } 26 27 func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { 28 errs := make([]error, 0, len(request.Imp)) 29 30 request, errs = a.preProcess(request, errs) 31 if request != nil { 32 reqJSON, err := json.Marshal(request) 33 if err != nil { 34 errs = append(errs, err) 35 return nil, errs 36 } 37 if a.endPoint != "" { 38 headers := http.Header{} 39 headers.Add("Content-Type", "application/json;charset=utf-8") 40 headers.Add("Accept", "application/json") 41 return []*adapters.RequestData{{ 42 Method: "POST", 43 Uri: a.endPoint, 44 Body: reqJSON, 45 Headers: headers, 46 }}, errs 47 } 48 } 49 return nil, errs 50 } 51 52 func (a *adapter) preProcess(req *openrtb2.BidRequest, errors []error) (*openrtb2.BidRequest, []error) { 53 numRequests := len(req.Imp) 54 for i := 0; i < numRequests; i++ { 55 imp := req.Imp[i] 56 var bidderExt adapters.ExtImpBidder 57 if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil { 58 err = &errortypes.BadInput{ 59 Message: fmt.Sprintf("ext data not provided in imp id=%s. Abort all Request", imp.ID), 60 } 61 errors = append(errors, err) 62 return nil, errors 63 } 64 var unrulyExt openrtb_ext.ExtImpUnruly 65 if err := json.Unmarshal(bidderExt.Bidder, &unrulyExt); err != nil { 66 err = &errortypes.BadInput{ 67 Message: fmt.Sprintf("siteid not provided in imp id=%s. Abort all Request", imp.ID), 68 } 69 errors = append(errors, err) 70 return nil, errors 71 } 72 unrulyExtCopy, err := json.Marshal(&unrulyExt) 73 if err != nil { 74 errors = append(errors, err) 75 return nil, errors 76 } 77 bidderExtCopy := struct { 78 Bidder json.RawMessage `json:"bidder,omitempty"` 79 }{unrulyExtCopy} 80 impExtCopy, err := json.Marshal(&bidderExtCopy) 81 if err != nil { 82 errors = append(errors, err) 83 return nil, errors 84 } 85 imp.Ext = impExtCopy 86 req.Imp[i] = imp 87 } 88 89 return req, errors 90 } 91 92 func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { 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 var bidResp openrtb2.BidResponse 109 if err := json.Unmarshal(response.Body, &bidResp); err != nil { 110 return nil, []error{&errortypes.BadServerResponse{ 111 Message: fmt.Sprintf("bad server response: %d. ", err), 112 }} 113 } 114 115 bidResponse := adapters.NewBidderResponseWithBidsCapacity(5) 116 117 var errs []error 118 for _, sb := range bidResp.SeatBid { 119 for i := range sb.Bid { 120 var bidType, err = getMediaTypeForImp(sb.Bid[i].ImpID, internalRequest.Imp) 121 if err != nil { 122 errs = append(errs, err...) 123 } else { 124 bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ 125 Bid: &sb.Bid[i], 126 BidType: bidType, 127 }) 128 } 129 } 130 } 131 132 return bidResponse, errs 133 } 134 135 func getMediaTypeForImp(impId string, imps []openrtb2.Imp) (openrtb_ext.BidType, []error) { 136 var errs []error 137 var noMatchingImps []string 138 mediaType := openrtb_ext.BidTypeBanner 139 for _, imp := range imps { 140 if imp.ID == impId { 141 if imp.Banner != nil { 142 mediaType = openrtb_ext.BidTypeBanner 143 } else if imp.Video != nil { 144 mediaType = openrtb_ext.BidTypeVideo 145 } else { 146 errs = append(errs, fmt.Errorf("bid responses mediaType didn't match supported mediaTypes")) 147 } 148 return mediaType, errs 149 } else { 150 noMatchingImps = append(noMatchingImps, imp.ID) 151 } 152 } 153 154 errs = append(errs, fmt.Errorf("Bid response imp ID %s not found in bid request containing imps %v\n", impId, noMatchingImps)) 155 156 return mediaType, errs 157 }