github.com/prebid/prebid-server@v0.275.0/adapters/onetag/onetag.go (about) 1 package onetag 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 adapter struct { 18 endpointTemplate *template.Template 19 } 20 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 endpointTemplate: template, 29 } 30 31 return bidder, nil 32 } 33 34 func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { 35 pubID := "" 36 for idx, imp := range request.Imp { 37 onetagExt, err := getImpressionExt(imp) 38 if err != nil { 39 return nil, []error{err} 40 } 41 if onetagExt.PubId != "" { 42 if pubID == "" { 43 pubID = onetagExt.PubId 44 } else if pubID != onetagExt.PubId { 45 return nil, []error{&errortypes.BadInput{ 46 Message: "There must be only one publisher ID", 47 }} 48 } 49 } else { 50 return nil, []error{&errortypes.BadInput{ 51 Message: "The publisher ID must not be empty", 52 }} 53 } 54 request.Imp[idx].Ext = onetagExt.Ext 55 } 56 57 url, err := a.buildEndpointURL(pubID) 58 if err != nil { 59 return nil, []error{err} 60 } 61 62 requestJSON, err := json.Marshal(request) 63 if err != nil { 64 return nil, []error{err} 65 } 66 67 requestData := &adapters.RequestData{ 68 Method: "POST", 69 Uri: url, 70 Body: requestJSON, 71 } 72 73 return []*adapters.RequestData{requestData}, nil 74 } 75 76 func getImpressionExt(imp openrtb2.Imp) (*openrtb_ext.ExtImpOnetag, error) { 77 var bidderExt adapters.ExtImpBidder 78 if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil { 79 return nil, &errortypes.BadInput{ 80 Message: "Bidder extension not provided or can't be unmarshalled", 81 } 82 } 83 84 var onetagExt openrtb_ext.ExtImpOnetag 85 if err := json.Unmarshal(bidderExt.Bidder, &onetagExt); err != nil { 86 return nil, &errortypes.BadInput{ 87 Message: "Error while unmarshaling bidder extension", 88 } 89 } 90 91 return &onetagExt, nil 92 } 93 94 func (a *adapter) buildEndpointURL(pubID string) (string, error) { 95 endpointParams := macros.EndpointTemplateParams{PublisherID: pubID} 96 return macros.ResolveMacros(a.endpointTemplate, endpointParams) 97 } 98 99 func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) { 100 if responseData.StatusCode == http.StatusNoContent { 101 return nil, nil 102 } 103 104 if responseData.StatusCode != http.StatusOK { 105 err := &errortypes.BadServerResponse{ 106 Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info.", responseData.StatusCode), 107 } 108 return nil, []error{err} 109 } 110 111 var response openrtb2.BidResponse 112 if err := json.Unmarshal(responseData.Body, &response); err != nil { 113 return nil, []error{err} 114 } 115 116 bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp)) 117 bidResponse.Currency = response.Cur 118 for _, seatBid := range response.SeatBid { 119 for _, bid := range seatBid.Bid { 120 bidMediaType, err := getMediaTypeForBid(request.Imp, bid) 121 if err != nil { 122 return nil, []error{err} 123 } 124 b := &adapters.TypedBid{ 125 Bid: &bid, 126 BidType: bidMediaType, 127 } 128 bidResponse.Bids = append(bidResponse.Bids, b) 129 } 130 } 131 return bidResponse, nil 132 } 133 134 func getMediaTypeForBid(impressions []openrtb2.Imp, bid openrtb2.Bid) (openrtb_ext.BidType, error) { 135 for _, impression := range impressions { 136 if impression.ID == bid.ImpID { 137 if impression.Banner != nil { 138 return openrtb_ext.BidTypeBanner, nil 139 } 140 if impression.Video != nil { 141 return openrtb_ext.BidTypeVideo, nil 142 } 143 if impression.Native != nil { 144 return openrtb_ext.BidTypeNative, nil 145 } 146 } 147 } 148 149 return "", &errortypes.BadServerResponse{ 150 Message: fmt.Sprintf("The impression with ID %s is not present into the request", bid.ImpID), 151 } 152 }