github.com/prebid/prebid-server/v2@v2.18.0/adapters/avocet/avocet.go (about) 1 package avocet 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 8 "github.com/prebid/openrtb/v20/adcom1" 9 "github.com/prebid/openrtb/v20/openrtb2" 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 ) 15 16 // AvocetAdapter implements a adapters.Bidder compatible with the Avocet advertising platform. 17 type AvocetAdapter struct { 18 // Endpoint is a http endpoint to use when making requests to the Avocet advertising platform. 19 Endpoint string 20 } 21 22 func (a *AvocetAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { 23 if len(request.Imp) == 0 { 24 return nil, nil 25 } 26 27 headers := http.Header{} 28 headers.Add("Content-Type", "application/json;charset=utf-8") 29 headers.Add("Accept", "application/json") 30 body, err := json.Marshal(request) 31 if err != nil { 32 return nil, []error{&errortypes.FailedToRequestBids{ 33 Message: err.Error(), 34 }} 35 } 36 reqData := &adapters.RequestData{ 37 Method: http.MethodPost, 38 Uri: a.Endpoint, 39 Body: body, 40 Headers: headers, 41 ImpIDs: openrtb_ext.GetImpIDs(request.Imp), 42 } 43 return []*adapters.RequestData{reqData}, nil 44 } 45 46 type avocetBidExt struct { 47 Avocet avocetBidExtension `json:"avocet"` 48 } 49 50 type avocetBidExtension struct { 51 Duration int `json:"duration"` 52 DealPriority int `json:"deal_priority"` 53 } 54 55 func (a *AvocetAdapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { 56 57 if response.StatusCode == http.StatusNoContent { 58 return nil, nil 59 } 60 61 if response.StatusCode != http.StatusOK { 62 var errStr string 63 if len(response.Body) > 0 { 64 errStr = string(response.Body) 65 } else { 66 errStr = "no response body" 67 } 68 return nil, []error{&errortypes.BadServerResponse{ 69 Message: fmt.Sprintf("received status code: %v error: %s", response.StatusCode, errStr), 70 }} 71 } 72 73 var br openrtb2.BidResponse 74 err := json.Unmarshal(response.Body, &br) 75 if err != nil { 76 return nil, []error{&errortypes.BadServerResponse{ 77 Message: err.Error(), 78 }} 79 } 80 var errs []error 81 82 bidResponse := adapters.NewBidderResponseWithBidsCapacity(5) 83 for i := range br.SeatBid { 84 for j := range br.SeatBid[i].Bid { 85 var ext avocetBidExt 86 if len(br.SeatBid[i].Bid[j].Ext) > 0 { 87 err := json.Unmarshal(br.SeatBid[i].Bid[j].Ext, &ext) 88 if err != nil { 89 errs = append(errs, err) 90 continue 91 } 92 } 93 tbid := &adapters.TypedBid{ 94 Bid: &br.SeatBid[i].Bid[j], 95 DealPriority: ext.Avocet.DealPriority, 96 } 97 tbid.BidType = getBidType(br.SeatBid[i].Bid[j], ext) 98 if tbid.BidType == openrtb_ext.BidTypeVideo { 99 tbid.BidVideo = &openrtb_ext.ExtBidPrebidVideo{ 100 Duration: ext.Avocet.Duration, 101 } 102 } 103 bidResponse.Bids = append(bidResponse.Bids, tbid) 104 } 105 } 106 if len(errs) > 0 { 107 return nil, errs 108 } 109 return bidResponse, nil 110 } 111 112 // getBidType returns the openrtb_ext.BidType for the provided bid. 113 func getBidType(bid openrtb2.Bid, ext avocetBidExt) openrtb_ext.BidType { 114 if ext.Avocet.Duration != 0 { 115 return openrtb_ext.BidTypeVideo 116 } 117 switch bid.API { 118 case adcom1.APIVPAID10, adcom1.APIVPAID20: 119 return openrtb_ext.BidTypeVideo 120 default: 121 return openrtb_ext.BidTypeBanner 122 } 123 } 124 125 // Builder builds a new instance of the Avocet adapter for the given bidder with the given config. 126 func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { 127 bidder := &AvocetAdapter{ 128 Endpoint: config.Endpoint, 129 } 130 return bidder, nil 131 }