github.com/prebid/prebid-server@v0.275.0/adapters/nanointeractive/nanointeractive.go (about) 1 package nanointeractive 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 8 "github.com/prebid/openrtb/v19/openrtb2" 9 "github.com/prebid/prebid-server/adapters" 10 "github.com/prebid/prebid-server/config" 11 "github.com/prebid/prebid-server/errortypes" 12 "github.com/prebid/prebid-server/openrtb_ext" 13 ) 14 15 type NanoInteractiveAdapter struct { 16 endpoint string 17 } 18 19 func (a *NanoInteractiveAdapter) MakeRequests(bidRequest *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { 20 21 var errs []error 22 var validImps []openrtb2.Imp 23 24 var adapterRequests []*adapters.RequestData 25 var referer string = "" 26 27 for i := 0; i < len(bidRequest.Imp); i++ { 28 29 ref, err := checkImp(&bidRequest.Imp[i]) 30 31 // If the parsing is failed, remove imp and add the error. 32 if err != nil { 33 errs = append(errs, err) 34 continue 35 } 36 if referer == "" && ref != "" { 37 referer = ref 38 } 39 validImps = append(validImps, bidRequest.Imp[i]) 40 } 41 42 if len(validImps) == 0 { 43 errs = append(errs, fmt.Errorf("no impressions in the bid request")) 44 return nil, errs 45 } 46 47 // set referer origin 48 if referer != "" { 49 if bidRequest.Site == nil { 50 bidRequest.Site = &openrtb2.Site{} 51 } 52 bidRequest.Site.Ref = referer 53 } 54 55 bidRequest.Imp = validImps 56 57 reqJSON, err := json.Marshal(bidRequest) 58 if err != nil { 59 errs = append(errs, err) 60 return nil, errs 61 } 62 63 headers := http.Header{} 64 headers.Add("Content-Type", "application/json;charset=utf-8") 65 headers.Add("Accept", "application/json") 66 headers.Add("x-openrtb-version", "2.5") 67 if bidRequest.Device != nil { 68 headers.Add("User-Agent", bidRequest.Device.UA) 69 headers.Add("X-Forwarded-For", bidRequest.Device.IP) 70 } 71 if bidRequest.Site != nil { 72 headers.Add("Referer", bidRequest.Site.Page) 73 } 74 75 // set user's cookie 76 if bidRequest.User != nil && bidRequest.User.BuyerUID != "" { 77 headers.Add("Cookie", "Nano="+bidRequest.User.BuyerUID) 78 } 79 80 adapterRequests = append(adapterRequests, &adapters.RequestData{ 81 Method: "POST", 82 Uri: a.endpoint, 83 Body: reqJSON, 84 Headers: headers, 85 }) 86 87 return adapterRequests, errs 88 } 89 90 func (a *NanoInteractiveAdapter) MakeBids( 91 internalRequest *openrtb2.BidRequest, 92 externalRequest *adapters.RequestData, 93 response *adapters.ResponseData) (*adapters.BidderResponse, []error) { 94 95 if response.StatusCode == http.StatusNoContent { 96 return nil, nil 97 } else if response.StatusCode == http.StatusBadRequest { 98 return nil, []error{&errortypes.BadInput{ 99 Message: "Invalid request.", 100 }} 101 } else if response.StatusCode != http.StatusOK { 102 return nil, []error{&errortypes.BadServerResponse{ 103 Message: fmt.Sprintf("unexpected HTTP status %d.", response.StatusCode), 104 }} 105 } 106 107 var openRtbBidResponse openrtb2.BidResponse 108 109 if err := json.Unmarshal(response.Body, &openRtbBidResponse); err != nil { 110 return nil, []error{&errortypes.BadServerResponse{ 111 Message: fmt.Sprintf("bad server body response"), 112 }} 113 } 114 115 bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(openRtbBidResponse.SeatBid[0].Bid)) 116 bidResponse.Currency = openRtbBidResponse.Cur 117 118 sb := openRtbBidResponse.SeatBid[0] 119 for i := 0; i < len(sb.Bid); i++ { 120 if !(sb.Bid[i].Price > 0) { 121 continue 122 } 123 bid := sb.Bid[i] 124 bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ 125 Bid: &bid, 126 BidType: openrtb_ext.BidTypeBanner, 127 }) 128 } 129 return bidResponse, nil 130 } 131 132 func checkImp(imp *openrtb2.Imp) (string, error) { 133 // We support only banner impression 134 if imp.Banner == nil { 135 return "", fmt.Errorf("invalid MediaType. NanoInteractive only supports Banner type. ImpID=%s", imp.ID) 136 } 137 138 var bidderExt adapters.ExtImpBidder 139 if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil { 140 return "", fmt.Errorf("ext not provided; ImpID=%s", imp.ID) 141 } 142 143 var nanoExt openrtb_ext.ExtImpNanoInteractive 144 if err := json.Unmarshal(bidderExt.Bidder, &nanoExt); err != nil { 145 return "", fmt.Errorf("ext.bidder not provided; ImpID=%s", imp.ID) 146 } 147 if nanoExt.Pid == "" { 148 return "", fmt.Errorf("pid is empty; ImpID=%s", imp.ID) 149 } 150 151 if nanoExt.Ref != "" { 152 return string(nanoExt.Ref), nil 153 } 154 155 return "", nil 156 } 157 158 // Builder builds a new instance of the NanoInteractive adapter for the given bidder with the given config. 159 func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { 160 bidder := &NanoInteractiveAdapter{ 161 endpoint: config.Endpoint, 162 } 163 return bidder, nil 164 }