github.com/prebid/prebid-server@v0.275.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/v19/openrtb2" 11 "github.com/prebid/prebid-server/adapters" 12 "github.com/prebid/prebid-server/config" 13 "github.com/prebid/prebid-server/errortypes" 14 "github.com/prebid/prebid-server/macros" 15 "github.com/prebid/prebid-server/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 }, nil 84 } 85 86 // get ImpAlgoriXExt From First Imp. Only check and get first Imp.Ext.Bidder to ExtImpAlgorix 87 func getImpAlgoriXExt(imp *openrtb2.Imp) (*openrtb_ext.ExtImpAlgorix, error) { 88 var extImpAlgoriX openrtb_ext.ExtImpAlgorix 89 var extBidder adapters.ExtImpBidder 90 err := json.Unmarshal(imp.Ext, &extBidder) 91 if err != nil { 92 return nil, err 93 } 94 err = json.Unmarshal(extBidder.Bidder, &extImpAlgoriX) 95 if err != nil { 96 return nil, err 97 } 98 return &extImpAlgoriX, nil 99 } 100 101 func getRegionInfo(region string) string { 102 switch region { 103 case "APAC": 104 return "apac.xyz" 105 case "USE": 106 return "use.xyz" 107 case "EUC": 108 return "euc.xyz" 109 default: 110 return "xyz" 111 } 112 } 113 114 func (a *adapter) getEndPoint(ext *openrtb_ext.ExtImpAlgorix) (string, error) { 115 endPointParams := macros.EndpointTemplateParams{ 116 SourceId: url.PathEscape(ext.Sid), 117 AccountID: url.PathEscape(ext.Token), 118 Host: url.PathEscape(getRegionInfo(ext.Region)), 119 } 120 return macros.ResolveMacros(a.EndpointTemplate, endPointParams) 121 } 122 123 func preProcess(request *openrtb2.BidRequest) { 124 for i := range request.Imp { 125 if request.Imp[i].Banner != nil { 126 banner := *request.Imp[i].Banner 127 if (banner.W == nil || banner.H == nil || *banner.W == 0 || *banner.H == 0) && len(banner.Format) > 0 { 128 firstFormat := banner.Format[0] 129 banner.W = &firstFormat.W 130 banner.H = &firstFormat.H 131 request.Imp[i].Banner = &banner 132 } 133 } 134 if request.Imp[i].Video != nil { 135 var impExt adapters.ExtImpBidder 136 err := json.Unmarshal(request.Imp[i].Ext, &impExt) 137 if err != nil { 138 continue 139 } 140 if impExt.Prebid != nil && impExt.Prebid.IsRewardedInventory != nil && *impExt.Prebid.IsRewardedInventory == 1 { 141 videoCopy := *request.Imp[i].Video 142 videoExt := algorixVideoExt{Rewarded: 1} 143 videoCopy.Ext, err = json.Marshal(&videoExt) 144 request.Imp[i].Video = &videoCopy 145 } 146 } 147 } 148 } 149 150 func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { 151 if response.StatusCode == http.StatusNoContent { 152 return nil, nil 153 } 154 155 if response.StatusCode == http.StatusBadRequest { 156 return nil, []error{&errortypes.BadInput{ 157 Message: fmt.Sprintf("Unexpected status code: %d.", response.StatusCode), 158 }} 159 } 160 161 if response.StatusCode != http.StatusOK { 162 return nil, []error{&errortypes.BadServerResponse{ 163 Message: fmt.Sprintf("Unexpected status code: %d.", response.StatusCode), 164 }} 165 } 166 167 var bidResp openrtb2.BidResponse 168 if err := json.Unmarshal(response.Body, &bidResp); err != nil { 169 return nil, []error{err} 170 } 171 172 bidResponse := adapters.NewBidderResponseWithBidsCapacity(1) 173 var errs []error 174 175 for _, seatBid := range bidResp.SeatBid { 176 for idx := range seatBid.Bid { 177 mediaType, err := getBidType(seatBid.Bid[idx], internalRequest.Imp) 178 if err != nil { 179 errs = append(errs, err) 180 } else { 181 bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ 182 Bid: &seatBid.Bid[idx], 183 BidType: mediaType, 184 }) 185 } 186 } 187 } 188 189 return bidResponse, errs 190 } 191 192 func getBidType(bid openrtb2.Bid, imps []openrtb2.Imp) (openrtb_ext.BidType, error) { 193 var bidExt algorixResponseBidExt 194 err := json.Unmarshal(bid.Ext, &bidExt) 195 if err == nil { 196 switch bidExt.MediaType { 197 case "banner": 198 return openrtb_ext.BidTypeBanner, nil 199 case "native": 200 return openrtb_ext.BidTypeNative, nil 201 case "video": 202 return openrtb_ext.BidTypeVideo, nil 203 } 204 } 205 var mediaType openrtb_ext.BidType 206 var typeCnt = 0 207 for _, imp := range imps { 208 if imp.ID == bid.ImpID { 209 if imp.Banner != nil { 210 typeCnt += 1 211 mediaType = openrtb_ext.BidTypeBanner 212 } 213 if imp.Native != nil { 214 typeCnt += 1 215 mediaType = openrtb_ext.BidTypeNative 216 } 217 if imp.Video != nil { 218 typeCnt += 1 219 mediaType = openrtb_ext.BidTypeVideo 220 } 221 } 222 } 223 if typeCnt == 1 { 224 return mediaType, nil 225 } 226 return mediaType, fmt.Errorf("unable to fetch mediaType in multi-format: %s", bid.ImpID) 227 }