Skip to content

Commit 3f5ff04

Browse files
BoldwinDevdanielbaud
authored andcommitted
New Adapter: Boldwin Rapid (prebid#4478)
1 parent 7d47722 commit 3f5ff04

File tree

17 files changed

+1647
-1
lines changed

17 files changed

+1647
-1
lines changed
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
package boldwin_rapid
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"text/template"
7+
8+
"net/http"
9+
10+
"github.com/prebid/openrtb/v20/openrtb2"
11+
"github.com/prebid/prebid-server/v3/adapters"
12+
"github.com/prebid/prebid-server/v3/config"
13+
"github.com/prebid/prebid-server/v3/macros"
14+
"github.com/prebid/prebid-server/v3/openrtb_ext"
15+
"github.com/prebid/prebid-server/v3/util/jsonutil"
16+
)
17+
18+
type adapter struct {
19+
endpoint *template.Template
20+
}
21+
22+
func Builder(_ openrtb_ext.BidderName, config config.Adapter, _ config.Server) (adapters.Bidder, error) {
23+
endpointTemplate, err := template.New("endpointTemplate").Parse(config.Endpoint)
24+
if err != nil {
25+
return nil, fmt.Errorf("unable to parse endpoint template: %v", err)
26+
}
27+
28+
bidder := &adapter{
29+
endpoint: endpointTemplate,
30+
}
31+
32+
return bidder, nil
33+
}
34+
35+
func (a *adapter) buildEndpointURL(boldwinExt openrtb_ext.ImpExtBoldwinRapid) (string, error) {
36+
endpointParams := macros.EndpointTemplateParams{
37+
PublisherID: boldwinExt.Pid,
38+
PlacementID: boldwinExt.Tid,
39+
}
40+
41+
return macros.ResolveMacros(a.endpoint, endpointParams)
42+
}
43+
44+
func (a *adapter) MakeRequests(request *openrtb2.BidRequest, _ *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
45+
var adapterRequests []*adapters.RequestData
46+
47+
reqCopy := *request
48+
headers := a.getHeaders(request)
49+
50+
for _, imp := range request.Imp {
51+
// Create a new request with just this impression
52+
reqCopy.Imp = []openrtb2.Imp{imp}
53+
54+
var bidderExt adapters.ExtImpBidder
55+
var boldwinExt openrtb_ext.ImpExtBoldwinRapid
56+
57+
// Use the current impression's Ext
58+
if err := jsonutil.Unmarshal(imp.Ext, &bidderExt); err != nil {
59+
return nil, []error{err}
60+
}
61+
62+
if err := jsonutil.Unmarshal(bidderExt.Bidder, &boldwinExt); err != nil {
63+
return nil, []error{err}
64+
}
65+
66+
endpoint, err := a.buildEndpointURL(boldwinExt)
67+
if err != nil {
68+
return nil, []error{err}
69+
}
70+
71+
adapterReq, err := a.makeRequest(&reqCopy, endpoint, headers)
72+
if err != nil {
73+
return nil, []error{err}
74+
}
75+
76+
if adapterReq != nil {
77+
adapterRequests = append(adapterRequests, adapterReq)
78+
}
79+
}
80+
81+
return adapterRequests, nil
82+
}
83+
84+
func (a *adapter) getHeaders(request *openrtb2.BidRequest) http.Header {
85+
headers := http.Header{}
86+
headers.Add("Content-Type", "application/json;charset=utf-8")
87+
headers.Add("Accept", "application/json")
88+
headers.Add("x-openrtb-version", "2.5")
89+
headers.Add("Host", "rtb.beardfleet.com") // required header for the request
90+
91+
if request.Device != nil {
92+
if request.Device.UA != "" {
93+
headers.Add("User-Agent", request.Device.UA)
94+
}
95+
96+
if len(request.Device.IPv6) > 0 {
97+
headers.Set("X-Forwarded-For", request.Device.IPv6)
98+
}
99+
100+
if len(request.Device.IP) > 0 {
101+
headers.Set("X-Forwarded-For", request.Device.IP)
102+
headers.Add("IP", request.Device.IP)
103+
}
104+
}
105+
106+
return headers
107+
}
108+
109+
func (a *adapter) makeRequest(request *openrtb2.BidRequest, endpoint string, headers http.Header) (*adapters.RequestData, error) {
110+
reqJSON, err := json.Marshal(request)
111+
if err != nil {
112+
return nil, fmt.Errorf("failed to marshal request: %w", err)
113+
}
114+
115+
return &adapters.RequestData{
116+
Method: "POST",
117+
Uri: endpoint,
118+
Body: reqJSON,
119+
Headers: headers,
120+
ImpIDs: openrtb_ext.GetImpIDs(request.Imp),
121+
}, nil
122+
}
123+
124+
func (a *adapter) MakeBids(request *openrtb2.BidRequest, _ *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) {
125+
if adapters.IsResponseStatusCodeNoContent(responseData) {
126+
return nil, nil
127+
}
128+
129+
err := adapters.CheckResponseStatusCodeForErrors(responseData)
130+
if err != nil {
131+
return nil, []error{err}
132+
}
133+
134+
var response openrtb2.BidResponse
135+
if err := jsonutil.Unmarshal(responseData.Body, &response); err != nil {
136+
return nil, []error{err}
137+
}
138+
139+
bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp))
140+
if response.Cur != "" {
141+
bidResponse.Currency = response.Cur
142+
}
143+
144+
for _, seatBid := range response.SeatBid {
145+
for i := range seatBid.Bid {
146+
bidType, err := getBidMediaType(&seatBid.Bid[i])
147+
if err != nil {
148+
return nil, []error{err}
149+
}
150+
151+
b := &adapters.TypedBid{
152+
Bid: &seatBid.Bid[i],
153+
BidType: bidType,
154+
}
155+
bidResponse.Bids = append(bidResponse.Bids, b)
156+
}
157+
}
158+
return bidResponse, nil
159+
}
160+
161+
func getBidMediaType(bid *openrtb2.Bid) (openrtb_ext.BidType, error) {
162+
switch bid.MType {
163+
case openrtb2.MarkupBanner:
164+
return openrtb_ext.BidTypeBanner, nil
165+
case openrtb2.MarkupVideo:
166+
return openrtb_ext.BidTypeVideo, nil
167+
case openrtb2.MarkupNative:
168+
return openrtb_ext.BidTypeNative, nil
169+
default:
170+
return "", fmt.Errorf("Unable to fetch mediaType in multi-format: %s", bid.ImpID)
171+
}
172+
}

0 commit comments

Comments
 (0)