Skip to content

Commit 3bf447b

Browse files
screencore-ioafront-io
and
afront-io
authored
New adapter: Screencore (prebid#2969)
Co-authored-by: afront-io <[email protected]>
1 parent a3c1a74 commit 3bf447b

24 files changed

+2032
-0
lines changed

adapters/screencore/params_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package screencore
2+
3+
import (
4+
"encoding/json"
5+
"testing"
6+
7+
"github.com/prebid/prebid-server/openrtb_ext"
8+
)
9+
10+
var validParams = []string{
11+
`{ "accountId": "hash", "placementId": "hash"}`,
12+
}
13+
14+
func TestValidParams(t *testing.T) {
15+
validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
16+
if err != nil {
17+
t.Fatalf("Failed to fetch the json-schemas. %v", err)
18+
}
19+
20+
for _, validParam := range validParams {
21+
if err := validator.Validate(openrtb_ext.BidderScreencore, json.RawMessage(validParam)); err != nil {
22+
t.Errorf("Schema rejected Screencore params: %s", validParam)
23+
}
24+
}
25+
}
26+
27+
var invalidParams = []string{
28+
``,
29+
`null`,
30+
`true`,
31+
`5`,
32+
`5.2`,
33+
`[]`,
34+
`{}`,
35+
`{"adCode": "string", "seatCode": 5, "originalPublisherid": "string"}`,
36+
`{ "placementId": "", "accountId": "" }`,
37+
}
38+
39+
func TestInvalidParams(t *testing.T) {
40+
validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
41+
if err != nil {
42+
t.Fatalf("Failed to fetch the json-schemas. %v", err)
43+
}
44+
45+
for _, invalidParam := range invalidParams {
46+
if err := validator.Validate(openrtb_ext.BidderScreencore, json.RawMessage(invalidParam)); err == nil {
47+
t.Errorf("Schema allowed unexpected params: %s", invalidParam)
48+
}
49+
}
50+
}

adapters/screencore/screencore.go

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
package screencore
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"net/http"
7+
"text/template"
8+
9+
"github.com/prebid/openrtb/v19/openrtb2"
10+
"github.com/prebid/prebid-server/adapters"
11+
"github.com/prebid/prebid-server/config"
12+
"github.com/prebid/prebid-server/errortypes"
13+
"github.com/prebid/prebid-server/macros"
14+
"github.com/prebid/prebid-server/openrtb_ext"
15+
)
16+
17+
type adapter struct {
18+
endpoint *template.Template
19+
}
20+
21+
func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) {
22+
template, err := template.New("endpointTemplate").Parse(config.Endpoint)
23+
if err != nil {
24+
return nil, fmt.Errorf("unable to parse endpoint url template: %v", err)
25+
}
26+
27+
bidder := &adapter{
28+
endpoint: template,
29+
}
30+
return bidder, nil
31+
}
32+
33+
func getHeaders(request *openrtb2.BidRequest) http.Header {
34+
headers := http.Header{}
35+
headers.Add("Content-Type", "application/json;charset=utf-8")
36+
headers.Add("Accept", "application/json")
37+
headers.Add("X-Openrtb-Version", "2.5")
38+
39+
if request.Device != nil {
40+
if len(request.Device.UA) > 0 {
41+
headers.Add("User-Agent", request.Device.UA)
42+
}
43+
44+
if len(request.Device.IPv6) > 0 {
45+
headers.Add("X-Forwarded-For", request.Device.IPv6)
46+
}
47+
48+
if len(request.Device.IP) > 0 {
49+
headers.Add("X-Forwarded-For", request.Device.IP)
50+
}
51+
}
52+
53+
return headers
54+
}
55+
56+
func (a *adapter) MakeRequests(openRTBRequest *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) (requestsToBidder []*adapters.RequestData, errs []error) {
57+
if len(openRTBRequest.Imp) == 0 {
58+
return nil, []error{&errortypes.BadInput{
59+
Message: "Empty Imp array in BidRequest",
60+
}}
61+
}
62+
63+
screencoreExt, err := getImpressionExt(&openRTBRequest.Imp[0])
64+
if err != nil {
65+
return nil, []error{err}
66+
}
67+
68+
openRTBRequest.Imp[0].Ext = nil
69+
70+
url, err := a.buildEndpointURL(screencoreExt)
71+
if err != nil {
72+
return nil, []error{err}
73+
}
74+
75+
reqJSON, err := json.Marshal(openRTBRequest)
76+
if err != nil {
77+
return nil, []error{err}
78+
}
79+
80+
return []*adapters.RequestData{{
81+
Method: http.MethodPost,
82+
Body: reqJSON,
83+
Uri: url,
84+
Headers: getHeaders(openRTBRequest),
85+
}}, nil
86+
}
87+
88+
func getImpressionExt(imp *openrtb2.Imp) (*openrtb_ext.ExtScreencore, error) {
89+
var bidderExt adapters.ExtImpBidder
90+
if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil {
91+
return nil, &errortypes.BadInput{
92+
Message: "Error parsing screencoreExt - " + err.Error(),
93+
}
94+
}
95+
var screencoreExt openrtb_ext.ExtScreencore
96+
if err := json.Unmarshal(bidderExt.Bidder, &screencoreExt); err != nil {
97+
return nil, &errortypes.BadInput{
98+
Message: "Error parsing bidderExt - " + err.Error(),
99+
}
100+
}
101+
102+
return &screencoreExt, nil
103+
}
104+
105+
func (a *adapter) buildEndpointURL(params *openrtb_ext.ExtScreencore) (string, error) {
106+
endpointParams := macros.EndpointTemplateParams{AccountID: params.AccountID, SourceId: params.PlacementID}
107+
return macros.ResolveMacros(a.endpoint, endpointParams)
108+
}
109+
110+
func checkResponseStatusCodes(response *adapters.ResponseData) error {
111+
if response.StatusCode == http.StatusServiceUnavailable {
112+
return &errortypes.BadServerResponse{
113+
Message: fmt.Sprintf("Something went wrong Status Code: [ %d ] ", response.StatusCode),
114+
}
115+
}
116+
117+
return adapters.CheckResponseStatusCodeForErrors(response)
118+
}
119+
120+
func (a *adapter) MakeBids(openRTBRequest *openrtb2.BidRequest, requestToBidder *adapters.RequestData, bidderRawResponse *adapters.ResponseData) (bidderResponse *adapters.BidderResponse, errs []error) {
121+
if adapters.IsResponseStatusCodeNoContent(bidderRawResponse) {
122+
return nil, nil
123+
}
124+
125+
httpStatusError := checkResponseStatusCodes(bidderRawResponse)
126+
if httpStatusError != nil {
127+
return nil, []error{httpStatusError}
128+
}
129+
130+
responseBody := bidderRawResponse.Body
131+
var bidResp openrtb2.BidResponse
132+
if err := json.Unmarshal(responseBody, &bidResp); err != nil {
133+
return nil, []error{&errortypes.BadServerResponse{
134+
Message: "Bad Server Response",
135+
}}
136+
}
137+
138+
if len(bidResp.SeatBid) == 0 {
139+
return nil, []error{&errortypes.BadServerResponse{
140+
Message: "Empty SeatBid array",
141+
}}
142+
}
143+
144+
bidResponse := adapters.NewBidderResponseWithBidsCapacity(5)
145+
var bidsArray []*adapters.TypedBid
146+
147+
for _, sb := range bidResp.SeatBid {
148+
for idx, bid := range sb.Bid {
149+
bidType, err := getMediaTypeForImp(bid)
150+
if err != nil {
151+
return nil, []error{err}
152+
}
153+
154+
bidsArray = append(bidsArray, &adapters.TypedBid{
155+
Bid: &sb.Bid[idx],
156+
BidType: bidType,
157+
})
158+
}
159+
}
160+
161+
bidResponse.Bids = bidsArray
162+
return bidResponse, nil
163+
}
164+
165+
func getMediaTypeForImp(bid openrtb2.Bid) (openrtb_ext.BidType, error) {
166+
switch bid.MType {
167+
case openrtb2.MarkupBanner:
168+
return openrtb_ext.BidTypeBanner, nil
169+
case openrtb2.MarkupVideo:
170+
return openrtb_ext.BidTypeVideo, nil
171+
case openrtb2.MarkupNative:
172+
return openrtb_ext.BidTypeNative, nil
173+
default:
174+
return "", fmt.Errorf("unsupported MType %d", bid.MType)
175+
}
176+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package screencore
2+
3+
import (
4+
"testing"
5+
6+
"github.com/prebid/prebid-server/adapters/adapterstest"
7+
"github.com/prebid/prebid-server/config"
8+
"github.com/prebid/prebid-server/openrtb_ext"
9+
)
10+
11+
func TestJsonSamples(t *testing.T) {
12+
bidder, buildErr := Builder(openrtb_ext.BidderScreencore, config.Adapter{
13+
Endpoint: "http://h1.screencore.io/?kp={{.AccountID}}&kn={{.SourceId}}"}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"})
14+
15+
if buildErr != nil {
16+
t.Fatalf("Builder returned unexpected error %v", buildErr)
17+
}
18+
19+
adapterstest.RunJSONBidderTest(t, "screencoretest", bidder)
20+
}

0 commit comments

Comments
 (0)