github.com/prebid/prebid-server@v0.275.0/adapters/ownadx/ownadx.go (about) 1 package ownadx 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "github.com/prebid/openrtb/v19/openrtb2" 7 "github.com/prebid/prebid-server/adapters" 8 "github.com/prebid/prebid-server/config" 9 "github.com/prebid/prebid-server/errortypes" 10 "github.com/prebid/prebid-server/macros" 11 "github.com/prebid/prebid-server/openrtb_ext" 12 "net/http" 13 "text/template" 14 ) 15 16 type adapter struct { 17 endpoint *template.Template 18 } 19 type bidExt struct { 20 MediaType string `json:"mediaType"` 21 } 22 23 func (adapter *adapter) getRequestData(bidRequest *openrtb2.BidRequest, impExt *openrtb_ext.ExtImpOwnAdx, imps []openrtb2.Imp) (*adapters.RequestData, error) { 24 pbidRequest := createBidRequest(bidRequest, imps) 25 reqJSON, err := json.Marshal(pbidRequest) 26 if err != nil { 27 return nil, &errortypes.BadInput{ 28 Message: "Prebid bidder request not valid or can't be marshalled. Err: " + err.Error(), 29 } 30 } 31 url, err := adapter.buildEndpointURL(impExt) 32 if err != nil { 33 return nil, &errortypes.BadInput{ 34 Message: "Error while creating endpoint. Err: " + err.Error(), 35 } 36 } 37 38 headers := http.Header{} 39 headers.Add("Content-Type", "application/json;charset=utf-8") 40 headers.Add("Accept", "application/json") 41 headers.Add("x-openrtb-version", "2.5") 42 43 return &adapters.RequestData{ 44 Method: "POST", 45 Uri: url, 46 Body: reqJSON, 47 Headers: headers}, nil 48 49 } 50 func createBidRequest(rtbBidRequest *openrtb2.BidRequest, imps []openrtb2.Imp) *openrtb2.BidRequest { 51 bidRequest := *rtbBidRequest 52 bidRequest.Imp = imps 53 return &bidRequest 54 } 55 func (adapter *adapter) buildEndpointURL(params *openrtb_ext.ExtImpOwnAdx) (string, error) { 56 endpointParams := macros.EndpointTemplateParams{ 57 ZoneID: params.SspId, 58 AccountID: params.SeatId, 59 SourceId: params.TokenId, 60 } 61 return macros.ResolveMacros(adapter.endpoint, endpointParams) 62 } 63 64 func getImpressionExt(imp *openrtb2.Imp) (*openrtb_ext.ExtImpOwnAdx, error) { 65 var bidderExt adapters.ExtImpBidder 66 if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil { 67 return nil, &errortypes.BadInput{ 68 Message: "Bidder extension not valid or can't be unmarshalled", 69 } 70 } 71 72 var ownAdxExt openrtb_ext.ExtImpOwnAdx 73 if err := json.Unmarshal(bidderExt.Bidder, &ownAdxExt); err != nil { 74 return nil, &errortypes.BadInput{ 75 Message: "Error while unmarshaling bidder extension", 76 } 77 } 78 79 return &ownAdxExt, nil 80 } 81 82 func (adapter *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { 83 84 errs := make([]error, 0, len(request.Imp)) 85 if len(request.Imp) == 0 { 86 errs = append(errs, &errortypes.BadInput{ 87 Message: "No impression in the bid request"}, 88 ) 89 return nil, errs 90 } 91 extImps, errors := groupImpsByExt(request.Imp) 92 if len(errors) != 0 { 93 errs = append(errs, errors...) 94 } 95 if len(extImps) == 0 { 96 return nil, errs 97 } 98 reqDetail := make([]*adapters.RequestData, 0, len(extImps)) 99 for k, imps := range extImps { 100 bidRequest, err := adapter.getRequestData(request, &k, imps) 101 if err != nil { 102 errs = append(errs, err) 103 } else { 104 reqDetail = append(reqDetail, bidRequest) 105 } 106 } 107 return reqDetail, errs 108 } 109 func groupImpsByExt(imps []openrtb2.Imp) (map[openrtb_ext.ExtImpOwnAdx][]openrtb2.Imp, []error) { 110 respExt := make(map[openrtb_ext.ExtImpOwnAdx][]openrtb2.Imp) 111 errors := make([]error, 0, len(imps)) 112 for _, imp := range imps { 113 ownAdxExt, err := getImpressionExt(&(imp)) 114 if err != nil { 115 errors = append(errors, err) 116 continue 117 } 118 119 respExt[*ownAdxExt] = append(respExt[*ownAdxExt], imp) 120 } 121 return respExt, errors 122 } 123 124 func (adapter *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { 125 if response.StatusCode == http.StatusNoContent { 126 return nil, nil 127 } 128 if response.StatusCode == http.StatusBadRequest { 129 return nil, []error{ 130 &errortypes.BadServerResponse{ 131 Message: fmt.Sprintf("Bad request: %d", response.StatusCode), 132 }, 133 } 134 } 135 if response.StatusCode != http.StatusOK { 136 return nil, []error{ 137 &errortypes.BadServerResponse{ 138 Message: fmt.Sprintf("Unexpected status code: %d. Run with request.test = 1 for more info.", response.StatusCode), 139 }, 140 } 141 } 142 var bidResp openrtb2.BidResponse 143 if err := json.Unmarshal(response.Body, &bidResp); err != nil { 144 return nil, []error{ 145 &errortypes.BadServerResponse{ 146 Message: fmt.Sprintf("Bad server response "), 147 }, 148 } 149 } 150 if len(bidResp.SeatBid) == 0 { 151 return nil, []error{ 152 &errortypes.BadServerResponse{ 153 Message: fmt.Sprintf("Array SeatBid cannot be empty "), 154 }, 155 } 156 } 157 158 seatBid := bidResp.SeatBid[0] 159 bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(bidResp.SeatBid[0].Bid)) 160 if len(seatBid.Bid) == 0 { 161 return nil, []error{ 162 &errortypes.BadServerResponse{ 163 Message: fmt.Sprintf("Bid cannot be empty "), 164 }, 165 } 166 } 167 for i := 0; i < len(seatBid.Bid); i++ { 168 var bidType openrtb_ext.BidType 169 bid := seatBid.Bid[i] 170 171 bidType, err := getMediaType(bid) 172 if err != nil { 173 return nil, []error{&errortypes.BadServerResponse{ 174 Message: "Bid type is invalid", 175 }} 176 } 177 bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ 178 Bid: &bid, 179 BidType: bidType, 180 }) 181 } 182 183 return bidResponse, nil 184 } 185 186 // Builder builds a new instance of the OwnAdx adapter for the given bidder with the given config 187 func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { 188 template, err := template.New("endpointTemplate").Parse(config.Endpoint) 189 if err != nil { 190 return nil, fmt.Errorf("unable to parse endpoint url template: %v", err) 191 } 192 193 bidder := &adapter{ 194 endpoint: template, 195 } 196 197 return bidder, nil 198 } 199 200 func getMediaType(bid openrtb2.Bid) (openrtb_ext.BidType, error) { 201 switch bid.MType { 202 case openrtb2.MarkupBanner: 203 return openrtb_ext.BidTypeBanner, nil 204 case openrtb2.MarkupVideo: 205 return openrtb_ext.BidTypeVideo, nil 206 case openrtb2.MarkupAudio: 207 return openrtb_ext.BidTypeAudio, nil 208 case openrtb2.MarkupNative: 209 return openrtb_ext.BidTypeNative, nil 210 default: 211 return "", fmt.Errorf("invalid BidType: %d", bid.MType) 212 } 213 }