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