github.com/prebid/prebid-server/v2@v2.18.0/adapters/smrtconnect/smrtconnect.go (about) 1 package smrtconnect 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "text/template" 7 8 "github.com/prebid/openrtb/v20/openrtb2" 9 "github.com/prebid/prebid-server/v2/adapters" 10 "github.com/prebid/prebid-server/v2/config" 11 "github.com/prebid/prebid-server/v2/errortypes" 12 "github.com/prebid/prebid-server/v2/macros" 13 "github.com/prebid/prebid-server/v2/openrtb_ext" 14 ) 15 16 type adapter struct { 17 endpoint *template.Template 18 } 19 20 // Builder builds a new instance of the Smrtconnect adapter for the given bidder with the given config. 21 func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { 22 template, err := template.New("endpointTemplate").Parse(config.Endpoint) 23 if err != nil { 24 return nil, fmt.Errorf("unable to parse endpoint url template: %v", err) 25 } 26 27 bidder := &adapter{ 28 endpoint: template, 29 } 30 return bidder, nil 31 } 32 33 func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { 34 var requests []*adapters.RequestData 35 36 requestCopy := *request 37 for _, imp := range request.Imp { 38 smrtconnectExt, err := getImpressionExt(&imp) 39 if err != nil { 40 return nil, []error{err} 41 } 42 43 url, err := a.buildEndpointURL(smrtconnectExt) 44 if err != nil { 45 return nil, []error{err} 46 } 47 48 requestCopy.Imp = []openrtb2.Imp{imp} 49 requestJSON, err := json.Marshal(requestCopy) 50 if err != nil { 51 return nil, []error{err} 52 } 53 54 requestData := &adapters.RequestData{ 55 Method: "POST", 56 Uri: url, 57 Body: requestJSON, 58 ImpIDs: openrtb_ext.GetImpIDs(requestCopy.Imp), 59 } 60 requests = append(requests, requestData) 61 } 62 return requests, nil 63 } 64 65 func getImpressionExt(imp *openrtb2.Imp) (*openrtb_ext.ExtSmrtconnect, error) { 66 var bidderExt adapters.ExtImpBidder 67 if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil { 68 return nil, &errortypes.BadInput{ 69 Message: "ext.bidder not provided", 70 } 71 } 72 var smrtconnectExt openrtb_ext.ExtSmrtconnect 73 if err := json.Unmarshal(bidderExt.Bidder, &smrtconnectExt); err != nil { 74 return nil, &errortypes.BadInput{ 75 Message: "ext.bidder not provided", 76 } 77 } 78 imp.Ext = nil 79 return &smrtconnectExt, nil 80 } 81 82 func (a *adapter) buildEndpointURL(params *openrtb_ext.ExtSmrtconnect) (string, error) { 83 endpointParams := macros.EndpointTemplateParams{SupplyId: params.SupplyId} 84 return macros.ResolveMacros(a.endpoint, endpointParams) 85 } 86 87 func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) { 88 if adapters.IsResponseStatusCodeNoContent(responseData) { 89 return nil, nil 90 } 91 92 if err := adapters.CheckResponseStatusCodeForErrors(responseData); err != nil { 93 return nil, []error{err} 94 } 95 96 var response openrtb2.BidResponse 97 if err := json.Unmarshal(responseData.Body, &response); err != nil { 98 return nil, []error{&errortypes.BadServerResponse{ 99 Message: "Bad Server Response", 100 }} 101 } 102 103 if len(response.SeatBid) == 0 { 104 return nil, []error{&errortypes.BadServerResponse{ 105 Message: "Empty SeatBid array", 106 }} 107 } 108 109 var bidErrs []error 110 bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp)) 111 bidResponse.Currency = response.Cur 112 for _, seatBid := range response.SeatBid { 113 for i := range seatBid.Bid { 114 bidType, err := getBidType(seatBid.Bid[i]) 115 if err != nil { 116 // could not determinate media type, append an error and continue with the next bid. 117 bidErrs = append(bidErrs, err) 118 continue 119 } 120 bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ 121 Bid: &seatBid.Bid[i], 122 BidType: bidType, 123 }) 124 } 125 } 126 return bidResponse, bidErrs 127 } 128 129 func getBidType(bid openrtb2.Bid) (openrtb_ext.BidType, error) { 130 // determinate media type by bid response field mtype 131 switch bid.MType { 132 case openrtb2.MarkupBanner: 133 return openrtb_ext.BidTypeBanner, nil 134 case openrtb2.MarkupVideo: 135 return openrtb_ext.BidTypeVideo, nil 136 case openrtb2.MarkupAudio: 137 return openrtb_ext.BidTypeAudio, nil 138 case openrtb2.MarkupNative: 139 return openrtb_ext.BidTypeNative, nil 140 } 141 142 return "", &errortypes.BadInput{ 143 Message: fmt.Sprintf("Could not define media type for impression: %s", bid.ImpID), 144 } 145 }