github.com/prebid/prebid-server/v2@v2.18.0/adapters/krushmedia/krushmedia.go (about) 1 package krushmedia 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 "strconv" 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 KrushmediaAdapter struct { 19 endpoint *template.Template 20 } 21 22 // Builder builds a new instance of the KrushmediaA adapter for the given bidder with the given config. 23 func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { 24 template, err := template.New("endpointTemplate").Parse(config.Endpoint) 25 if err != nil { 26 return nil, fmt.Errorf("unable to parse endpoint url template: %v", err) 27 } 28 29 bidder := &KrushmediaAdapter{ 30 endpoint: template, 31 } 32 return bidder, nil 33 } 34 35 func getHeaders(request *openrtb2.BidRequest) *http.Header { 36 headers := http.Header{} 37 headers.Add("Content-Type", "application/json;charset=utf-8") 38 headers.Add("Accept", "application/json") 39 headers.Add("X-Openrtb-Version", "2.5") 40 41 if request.Device != nil { 42 if len(request.Device.UA) > 0 { 43 headers.Add("User-Agent", request.Device.UA) 44 } 45 46 if len(request.Device.IP) > 0 { 47 headers.Add("X-Forwarded-For", request.Device.IP) 48 } 49 50 if len(request.Device.Language) > 0 { 51 headers.Add("Accept-Language", request.Device.Language) 52 } 53 54 if request.Device.DNT != nil { 55 headers.Add("Dnt", strconv.Itoa(int(*request.Device.DNT))) 56 } 57 } 58 59 return &headers 60 } 61 62 func (a *KrushmediaAdapter) MakeRequests( 63 openRTBRequest *openrtb2.BidRequest, 64 reqInfo *adapters.ExtraRequestInfo, 65 ) ( 66 requestsToBidder []*adapters.RequestData, 67 errs []error, 68 ) { 69 70 request := *openRTBRequest 71 72 var errors []error 73 var krushmediaExt *openrtb_ext.ExtKrushmedia 74 var err error 75 76 if len(request.Imp) > 0 { 77 krushmediaExt, err = a.getImpressionExt(&(request.Imp[0])) 78 if err != nil { 79 errors = append(errors, err) 80 } 81 request.Imp[0].Ext = nil 82 } else { 83 errors = append(errors, &errortypes.BadInput{ 84 Message: "Missing Imp Object", 85 }) 86 } 87 88 if len(errors) > 0 { 89 return nil, errors 90 } 91 92 url, err := a.buildEndpointURL(krushmediaExt) 93 if err != nil { 94 return nil, []error{err} 95 } 96 97 reqJSON, err := json.Marshal(request) 98 if err != nil { 99 return nil, []error{err} 100 } 101 102 return []*adapters.RequestData{{ 103 Method: http.MethodPost, 104 Body: reqJSON, 105 Uri: url, 106 Headers: *getHeaders(&request), 107 ImpIDs: openrtb_ext.GetImpIDs(request.Imp), 108 }}, nil 109 } 110 111 func (a *KrushmediaAdapter) getImpressionExt(imp *openrtb2.Imp) (*openrtb_ext.ExtKrushmedia, error) { 112 var bidderExt adapters.ExtImpBidder 113 if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil { 114 return nil, &errortypes.BadInput{ 115 Message: "Bidder extension not provided or can't be unmarshalled", 116 } 117 } 118 var krushmediaExt openrtb_ext.ExtKrushmedia 119 if err := json.Unmarshal(bidderExt.Bidder, &krushmediaExt); err != nil { 120 return nil, &errortypes.BadInput{ 121 Message: "Error while unmarshaling bidder extension", 122 } 123 } 124 return &krushmediaExt, nil 125 } 126 127 func (a *KrushmediaAdapter) buildEndpointURL(params *openrtb_ext.ExtKrushmedia) (string, error) { 128 endpointParams := macros.EndpointTemplateParams{AccountID: params.AccountID} 129 return macros.ResolveMacros(a.endpoint, endpointParams) 130 } 131 132 func (a *KrushmediaAdapter) MakeBids( 133 openRTBRequest *openrtb2.BidRequest, 134 requestToBidder *adapters.RequestData, 135 bidderRawResponse *adapters.ResponseData, 136 ) ( 137 bidderResponse *adapters.BidderResponse, 138 errs []error, 139 ) { 140 if bidderRawResponse.StatusCode == http.StatusNoContent { 141 return nil, nil 142 } 143 144 if bidderRawResponse.StatusCode == http.StatusBadRequest { 145 return nil, []error{&errortypes.BadInput{ 146 Message: fmt.Sprintf("Unexpected status code: [ %d ]", bidderRawResponse.StatusCode), 147 }} 148 } 149 150 if bidderRawResponse.StatusCode == http.StatusServiceUnavailable { 151 return nil, nil 152 } 153 154 if bidderRawResponse.StatusCode != http.StatusOK { 155 return nil, []error{&errortypes.BadServerResponse{ 156 Message: fmt.Sprintf("Something went wrong, please contact your Account Manager. Status Code: [ %d ] ", bidderRawResponse.StatusCode), 157 }} 158 } 159 160 responseBody := bidderRawResponse.Body 161 var bidResp openrtb2.BidResponse 162 if err := json.Unmarshal(responseBody, &bidResp); err != nil { 163 return nil, []error{&errortypes.BadServerResponse{ 164 Message: "Bad Server Response", 165 }} 166 } 167 168 bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(bidResp.SeatBid[0].Bid)) 169 sb := bidResp.SeatBid[0] 170 171 for _, bid := range sb.Bid { 172 bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ 173 Bid: &bid, 174 BidType: getMediaTypeForImp(bid.ImpID, openRTBRequest.Imp), 175 }) 176 } 177 return bidResponse, nil 178 } 179 180 func getMediaTypeForImp(impId string, imps []openrtb2.Imp) openrtb_ext.BidType { 181 mediaType := openrtb_ext.BidTypeBanner 182 for _, imp := range imps { 183 if imp.ID == impId { 184 if imp.Video != nil { 185 mediaType = openrtb_ext.BidTypeVideo 186 } else if imp.Native != nil { 187 mediaType = openrtb_ext.BidTypeNative 188 } 189 return mediaType 190 } 191 } 192 return mediaType 193 }