github.com/prebid/prebid-server/v2@v2.18.0/adapters/vidoomy/vidoomy.go (about) 1 package vidoomy 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 8 "github.com/prebid/openrtb/v20/openrtb2" 9 10 "github.com/prebid/prebid-server/v2/adapters" 11 "github.com/prebid/prebid-server/v2/config" 12 "github.com/prebid/prebid-server/v2/errortypes" 13 "github.com/prebid/prebid-server/v2/openrtb_ext" 14 "github.com/prebid/prebid-server/v2/util/ptrutil" 15 ) 16 17 type adapter struct { 18 endpoint string 19 } 20 21 func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { 22 var errors []error 23 24 reqs := make([]*adapters.RequestData, 0, len(request.Imp)) 25 26 header := getHeaders(request) 27 for _, imp := range request.Imp { 28 29 // Split up multi-impression requests into multiple requests so that 30 // each split request is only associated to a single impression 31 reqCopy := *request 32 reqCopy.Imp = []openrtb2.Imp{imp} 33 34 if err := changeRequestForBidService(&reqCopy); err != nil { 35 errors = append(errors, err) 36 continue 37 } 38 39 reqJSON, err := json.Marshal(&reqCopy) 40 if err != nil { 41 errors = append(errors, err) 42 continue 43 } 44 45 reqs = append(reqs, &adapters.RequestData{ 46 Method: "POST", 47 Uri: a.endpoint, 48 Body: reqJSON, 49 Headers: header, 50 ImpIDs: openrtb_ext.GetImpIDs(reqCopy.Imp), 51 }) 52 } 53 54 return reqs, errors 55 } 56 57 func getHeaders(request *openrtb2.BidRequest) http.Header { 58 headers := http.Header{} 59 60 headers.Add("Content-Type", "application/json;charset=utf-8") 61 headers.Add("Accept", "application/json") 62 headers.Add("x-openrtb-version", "2.5") 63 64 if request.Device == nil { 65 return headers 66 } 67 68 if request.Device.UA != "" { 69 headers.Set("User-Agent", request.Device.UA) 70 } 71 72 if len(request.Device.IPv6) > 0 { 73 headers.Add("X-Forwarded-For", request.Device.IPv6) 74 } 75 76 if len(request.Device.IP) > 0 { 77 headers.Add("X-Forwarded-For", request.Device.IP) 78 } 79 80 return headers 81 } 82 83 func changeRequestForBidService(request *openrtb2.BidRequest) error { 84 if request.Imp[0].Banner == nil { 85 return nil 86 } 87 88 banner := *request.Imp[0].Banner 89 request.Imp[0].Banner = &banner 90 91 if banner.W != nil && banner.H != nil { 92 if *banner.W == 0 || *banner.H == 0 { 93 return fmt.Errorf("invalid sizes provided for Banner %d x %d", *banner.W, *banner.H) 94 } 95 return nil 96 } 97 98 if len(banner.Format) == 0 { 99 return fmt.Errorf("no sizes provided for Banner %v", banner.Format) 100 } 101 102 banner.W = ptrutil.ToPtr(banner.Format[0].W) 103 banner.H = ptrutil.ToPtr(banner.Format[0].H) 104 105 return nil 106 } 107 108 func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { 109 if response.StatusCode == http.StatusNoContent { 110 return nil, nil 111 } 112 113 if response.StatusCode != http.StatusOK { 114 return nil, []error{&errortypes.BadServerResponse{ 115 Message: fmt.Sprintf("Unexpected status code: %d.", response.StatusCode), 116 }} 117 } 118 119 var bidResp openrtb2.BidResponse 120 if err := json.Unmarshal(response.Body, &bidResp); err != nil { 121 return nil, []error{&errortypes.BadServerResponse{ 122 Message: fmt.Sprintf("Bad server response: %d.", err), 123 }} 124 } 125 126 bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(internalRequest.Imp)) 127 128 for _, sb := range bidResp.SeatBid { 129 for _, bid := range sb.Bid { 130 bid := bid 131 exists, mediaType := getImpInfo(bid.ImpID, internalRequest.Imp) 132 if !exists { 133 return nil, []error{&errortypes.BadServerResponse{ 134 Message: fmt.Sprintf("Unknown ad unit code '%s'", bid.ImpID), 135 }} 136 } 137 138 if openrtb_ext.BidTypeBanner != mediaType && 139 openrtb_ext.BidTypeVideo != mediaType { 140 //only banner and video are supported, anything else is ignored 141 continue 142 } 143 144 bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ 145 Bid: &bid, 146 BidType: mediaType, 147 }) 148 } 149 } 150 151 return bidResponse, nil 152 } 153 154 func getImpInfo(impId string, imps []openrtb2.Imp) (bool, openrtb_ext.BidType) { 155 var mediaType openrtb_ext.BidType 156 for _, imp := range imps { 157 if imp.ID == impId { 158 159 if imp.Video != nil { 160 mediaType = openrtb_ext.BidTypeVideo 161 } else if imp.Banner != nil { 162 mediaType = openrtb_ext.BidTypeBanner 163 } 164 165 return true, mediaType 166 } 167 } 168 return false, mediaType 169 } 170 171 // Builder builds a new instance of the Vidoomy adapter for the given bidder with the given config. 172 func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { 173 bidder := &adapter{ 174 endpoint: config.Endpoint, 175 } 176 return bidder, nil 177 }