github.com/prebid/prebid-server/v2@v2.18.0/adapters/pulsepoint/pulsepoint.go (about) 1 package pulsepoint 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 "strconv" 8 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/openrtb_ext" 13 14 "github.com/prebid/openrtb/v20/openrtb2" 15 ) 16 17 type PulsePointAdapter struct { 18 URI string 19 } 20 21 // Builds an instance of PulsePointAdapter 22 func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { 23 bidder := &PulsePointAdapter{ 24 URI: config.Endpoint, 25 } 26 return bidder, nil 27 } 28 29 func (a *PulsePointAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { 30 errs := make([]error, 0, len(request.Imp)) 31 32 var err error 33 pubID := "" 34 imps := make([]openrtb2.Imp, 0, len(request.Imp)) 35 for i := 0; i < len(request.Imp); i++ { 36 imp := request.Imp[i] 37 var bidderExt adapters.ExtImpBidder 38 if err = json.Unmarshal(imp.Ext, &bidderExt); err != nil { 39 errs = append(errs, &errortypes.BadInput{ 40 Message: err.Error(), 41 }) 42 continue 43 } 44 var pulsepointExt openrtb_ext.ExtImpPulsePoint 45 if err = json.Unmarshal(bidderExt.Bidder, &pulsepointExt); err != nil { 46 errs = append(errs, &errortypes.BadInput{ 47 Message: err.Error(), 48 }) 49 continue 50 } 51 // parse pubid and keep it for reference 52 if pubID == "" && pulsepointExt.PubID > 0 { 53 pubID = strconv.Itoa(pulsepointExt.PubID) 54 } 55 // tag id to be sent 56 imp.TagID = strconv.Itoa(pulsepointExt.TagID) 57 imps = append(imps, imp) 58 } 59 60 // verify there are valid impressions 61 if len(imps) == 0 { 62 return nil, errs 63 } 64 65 // add the publisher id from ext to the site.pub.id or app.pub.id 66 if request.Site != nil { 67 site := *request.Site 68 if site.Publisher != nil { 69 publisher := *site.Publisher 70 publisher.ID = pubID 71 site.Publisher = &publisher 72 } else { 73 site.Publisher = &openrtb2.Publisher{ID: pubID} 74 } 75 request.Site = &site 76 } else if request.App != nil { 77 app := *request.App 78 if app.Publisher != nil { 79 publisher := *app.Publisher 80 publisher.ID = pubID 81 app.Publisher = &publisher 82 } else { 83 app.Publisher = &openrtb2.Publisher{ID: pubID} 84 } 85 request.App = &app 86 } 87 88 request.Imp = imps 89 reqJSON, err := json.Marshal(request) 90 if err != nil { 91 errs = append(errs, err) 92 return nil, errs 93 } 94 headers := http.Header{} 95 headers.Add("Content-Type", "application/json;charset=utf-8") 96 headers.Add("Accept", "application/json") 97 return []*adapters.RequestData{{ 98 Method: "POST", 99 Uri: a.URI, 100 Body: reqJSON, 101 Headers: headers, 102 ImpIDs: openrtb_ext.GetImpIDs(request.Imp), 103 }}, errs 104 } 105 106 func (a *PulsePointAdapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { 107 // passback 108 if response.StatusCode == http.StatusNoContent { 109 return nil, nil 110 } 111 // bad requests 112 if response.StatusCode == http.StatusBadRequest { 113 return nil, []error{&errortypes.BadInput{ 114 Message: fmt.Sprintf("Bad user input: HTTP status %d", response.StatusCode), 115 }} 116 } 117 // error 118 if response.StatusCode != http.StatusOK { 119 return nil, []error{&errortypes.BadServerResponse{ 120 Message: fmt.Sprintf("Bad server response: HTTP status %d", response.StatusCode), 121 }} 122 } 123 // parse response 124 var bidResp openrtb2.BidResponse 125 if err := json.Unmarshal(response.Body, &bidResp); err != nil { 126 return nil, []error{err} 127 } 128 129 bidResponse := adapters.NewBidderResponseWithBidsCapacity(5) 130 // map imps by id 131 impsByID := make(map[string]openrtb2.Imp) 132 for i := 0; i < len(internalRequest.Imp); i++ { 133 impsByID[internalRequest.Imp[i].ID] = internalRequest.Imp[i] 134 } 135 136 var errs []error 137 for _, sb := range bidResp.SeatBid { 138 for i := 0; i < len(sb.Bid); i++ { 139 bid := sb.Bid[i] 140 imp := impsByID[bid.ImpID] 141 bidType := getBidType(imp) 142 if &imp != nil && bidType != "" { 143 bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ 144 Bid: &bid, 145 BidType: bidType, 146 }) 147 } 148 } 149 } 150 return bidResponse, errs 151 } 152 153 func getBidType(imp openrtb2.Imp) openrtb_ext.BidType { 154 // derive the bidtype purely from the impression itself 155 if imp.Banner != nil { 156 return openrtb_ext.BidTypeBanner 157 } else if imp.Video != nil { 158 return openrtb_ext.BidTypeVideo 159 } else if imp.Audio != nil { 160 return openrtb_ext.BidTypeAudio 161 } else if imp.Native != nil { 162 return openrtb_ext.BidTypeNative 163 } 164 return "" 165 }