github.com/prebid/prebid-server/v2@v2.18.0/adapters/algorix/algorix.go (about) 1 package algorix 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 "net/url" 8 "text/template" 9 10 "github.com/prebid/openrtb/v20/openrtb2" 11 "github.com/prebid/prebid-server/v2/adapters" 12 "github.com/prebid/prebid-server/v2/config" 13 "github.com/prebid/prebid-server/v2/errortypes" 14 "github.com/prebid/prebid-server/v2/macros" 15 "github.com/prebid/prebid-server/v2/openrtb_ext" 16 ) 17 18 type adapter struct { 19 EndpointTemplate *template.Template 20 } 21 22 type algorixVideoExt struct { 23 Rewarded int `json:"rewarded"` 24 } 25 26 type algorixResponseBidExt struct { 27 MediaType string `json:"mediaType"` 28 } 29 30 // Builder builds a new instance of the AlgoriX adapter for the given bidder with the given config. 31 func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { 32 endpoint, err := template.New("endpointTemplate").Parse(config.Endpoint) 33 if err != nil { 34 return nil, fmt.Errorf("unable to parse endpoint url template: %v", err) 35 } 36 bidder := &adapter{ 37 EndpointTemplate: endpoint, 38 } 39 return bidder, nil 40 } 41 42 func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { 43 var adapterRequests []*adapters.RequestData 44 var errs []error 45 46 adapterRequest, err := a.makeRequest(request) 47 if err == nil { 48 adapterRequests = append(adapterRequests, adapterRequest) 49 } else { 50 errs = append(errs, err) 51 } 52 return adapterRequests, errs 53 } 54 55 func (a *adapter) makeRequest(request *openrtb2.BidRequest) (*adapters.RequestData, error) { 56 algorixExt, err := getImpAlgoriXExt(&request.Imp[0]) 57 58 if err != nil { 59 return nil, &errortypes.BadInput{Message: "Invalid ExtImpAlgoriX value"} 60 } 61 62 endPoint, err := a.getEndPoint(algorixExt) 63 if err != nil { 64 return nil, err 65 } 66 67 preProcess(request) 68 reqBody, err := json.Marshal(request) 69 if err != nil { 70 return nil, err 71 } 72 73 headers := http.Header{} 74 headers.Add("Content-Type", "application/json;charset=utf-8") 75 headers.Add("Accept", "application/json") 76 headers.Add("x-openrtb-version", "2.5") 77 78 return &adapters.RequestData{ 79 Method: "POST", 80 Uri: endPoint, 81 Body: reqBody, 82 Headers: headers, 83 ImpIDs: openrtb_ext.GetImpIDs(request.Imp), 84 }, nil 85 } 86 87 // get ImpAlgoriXExt From First Imp. Only check and get first Imp.Ext.Bidder to ExtImpAlgorix 88 func getImpAlgoriXExt(imp *openrtb2.Imp) (*openrtb_ext.ExtImpAlgorix, error) { 89 var extImpAlgoriX openrtb_ext.ExtImpAlgorix 90 var extBidder adapters.ExtImpBidder 91 err := json.Unmarshal(imp.Ext, &extBidder) 92 if err != nil { 93 return nil, err 94 } 95 err = json.Unmarshal(extBidder.Bidder, &extImpAlgoriX) 96 if err != nil { 97 return nil, err 98 } 99 return &extImpAlgoriX, nil 100 } 101 102 func getRegionInfo(region string) string { 103 switch region { 104 case "APAC": 105 return "apac.xyz" 106 case "USE": 107 return "use.xyz" 108 case "EUC": 109 return "euc.xyz" 110 default: 111 return "xyz" 112 } 113 } 114 115 func (a *adapter) getEndPoint(ext *openrtb_ext.ExtImpAlgorix) (string, error) { 116 endPointParams := macros.EndpointTemplateParams{ 117 SourceId: url.PathEscape(ext.Sid), 118 AccountID: url.PathEscape(ext.Token), 119 Host: url.PathEscape(getRegionInfo(ext.Region)), 120 } 121 return macros.ResolveMacros(a.EndpointTemplate, endPointParams) 122 } 123 124 func preProcess(request *openrtb2.BidRequest) { 125 for i := range request.Imp { 126 if request.Imp[i].Banner != nil { 127 banner := *request.Imp[i].Banner 128 if (banner.W == nil || banner.H == nil || *banner.W == 0 || *banner.H == 0) && len(banner.Format) > 0 { 129 firstFormat := banner.Format[0] 130 banner.W = &firstFormat.W 131 banner.H = &firstFormat.H 132 request.Imp[i].Banner = &banner 133 } 134 } 135 if request.Imp[i].Video != nil { 136 var impExt adapters.ExtImpBidder 137 err := json.Unmarshal(request.Imp[i].Ext, &impExt) 138 if err != nil { 139 continue 140 } 141 if impExt.Prebid != nil && impExt.Prebid.IsRewardedInventory != nil && *impExt.Prebid.IsRewardedInventory == 1 { 142 videoCopy := *request.Imp[i].Video 143 videoExt := algorixVideoExt{Rewarded: 1} 144 videoCopy.Ext, err = json.Marshal(&videoExt) 145 request.Imp[i].Video = &videoCopy 146 } 147 } 148 } 149 } 150 151 func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { 152 if response.StatusCode == http.StatusNoContent { 153 return nil, nil 154 } 155 156 if response.StatusCode == http.StatusBadRequest { 157 return nil, []error{&errortypes.BadInput{ 158 Message: fmt.Sprintf("Unexpected status code: %d.", response.StatusCode), 159 }} 160 } 161 162 if response.StatusCode != http.StatusOK { 163 return nil, []error{&errortypes.BadServerResponse{ 164 Message: fmt.Sprintf("Unexpected status code: %d.", response.StatusCode), 165 }} 166 } 167 168 var bidResp openrtb2.BidResponse 169 if err := json.Unmarshal(response.Body, &bidResp); err != nil { 170 return nil, []error{err} 171 } 172 173 bidResponse := adapters.NewBidderResponseWithBidsCapacity(1) 174 var errs []error 175 176 for _, seatBid := range bidResp.SeatBid { 177 for idx := range seatBid.Bid { 178 mediaType, err := getBidType(seatBid.Bid[idx], internalRequest.Imp) 179 if err != nil { 180 errs = append(errs, err) 181 } else { 182 bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ 183 Bid: &seatBid.Bid[idx], 184 BidType: mediaType, 185 }) 186 } 187 } 188 } 189 190 return bidResponse, errs 191 } 192 193 func getBidType(bid openrtb2.Bid, imps []openrtb2.Imp) (openrtb_ext.BidType, error) { 194 var bidExt algorixResponseBidExt 195 err := json.Unmarshal(bid.Ext, &bidExt) 196 if err == nil { 197 switch bidExt.MediaType { 198 case "banner": 199 return openrtb_ext.BidTypeBanner, nil 200 case "native": 201 return openrtb_ext.BidTypeNative, nil 202 case "video": 203 return openrtb_ext.BidTypeVideo, nil 204 } 205 } 206 var mediaType openrtb_ext.BidType 207 var typeCnt = 0 208 for _, imp := range imps { 209 if imp.ID == bid.ImpID { 210 if imp.Banner != nil { 211 typeCnt += 1 212 mediaType = openrtb_ext.BidTypeBanner 213 } 214 if imp.Native != nil { 215 typeCnt += 1 216 mediaType = openrtb_ext.BidTypeNative 217 } 218 if imp.Video != nil { 219 typeCnt += 1 220 mediaType = openrtb_ext.BidTypeVideo 221 } 222 } 223 } 224 if typeCnt == 1 { 225 return mediaType, nil 226 } 227 return mediaType, fmt.Errorf("unable to fetch mediaType in multi-format: %s", bid.ImpID) 228 }