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