-
Notifications
You must be signed in to change notification settings - Fork 744
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New Adapter: Zentotem #3866
New Adapter: Zentotem #3866
Changes from 8 commits
9aef1ae
6fdcc11
3edd765
9ec095a
a7d9462
36a4b0f
9c6b5e3
b3caeaa
e4bd6d3
153ebf5
f075a67
6f3f47c
6be7244
e8509e6
d161712
a556e2d
59a5b07
54f8759
bd85ba4
84a8162
536f118
b5cb591
8d7117d
4ea0e33
2e2b49f
e825553
f7caea5
8237f7f
ec6a45d
6a011ed
b920cca
e0a21d0
6cbedf0
7613ff5
c02ee8c
ffdd75f
3e24be7
640b97c
3c4527e
905b3a5
93368cc
11b6546
4462fce
8b1b96e
c42fe53
53f51a6
6c154e0
f27bcef
8689e0d
d54c3ed
64584f6
87d4412
9bb9b3d
c37951a
5fcbbbf
cbe9876
b56923c
8134328
451bc44
bcf6491
18f6798
03a4abd
a23380f
ddf897c
1419761
db2a872
df58baf
3907f1a
5b11f59
6e150f3
a788661
3403544
106f6e4
181d523
24ba83b
63af8af
573c59e
f8ee4ed
4bee7d9
5cb43d2
b6bc533
39567ab
93e3969
bd22820
2b0b9b1
7a2144a
d4290d3
764f48a
dc73050
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package zentotem | ||
|
||
import ( | ||
"encoding/json" | ||
"github.com/prebid/prebid-server/v2/openrtb_ext" | ||
"testing" | ||
) | ||
|
||
//Zentotem doesn't currently require any custom fields. This file is included for conformity only | ||
//We do include an unused, non-required custom param in static/bidder-params/zentotem.json, but only to hinder the prebid server from crashing by looking for at least 1 custom param | ||
|
||
// This file actually intends to test static/bidder-params/zentotem.json | ||
// | ||
// These also validate the format of the external API: request.imp[i].ext.prebid.bidder.zentotem | ||
// TestValidParams makes sure that the Zentotem schema accepts all imp.ext fields which we intend to support. | ||
func TestValidParams(t *testing.T) { | ||
validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") | ||
if err != nil { | ||
t.Fatalf("Failed to fetch the json-schemas. %v", err) | ||
} | ||
|
||
for _, validParam := range validParams { | ||
if err := validator.Validate(openrtb_ext.BidderZentotem, json.RawMessage(validParam)); err != nil { | ||
t.Errorf("Schema rejected Zentotem params: %s", validParam) | ||
} | ||
} | ||
} | ||
|
||
// TestInvalidParams makes sure that the Zentotem schema rejects all the imp.ext fields we don't support. | ||
func TestInvalidParams(t *testing.T) { | ||
validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") | ||
if err != nil { | ||
t.Fatalf("Failed to fetch the json-schemas. %v", err) | ||
} | ||
|
||
for _, invalidParam := range invalidParams { | ||
if err := validator.Validate(openrtb_ext.BidderZentotem, json.RawMessage(invalidParam)); err == nil { | ||
t.Errorf("Schema allowed unexpected params: %s", invalidParam) | ||
} | ||
} | ||
} | ||
|
||
var validParams = []string{} | ||
|
||
var invalidParams = []string{} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
package zentotem | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"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" | ||
"net/http" | ||
) | ||
|
||
type adapter struct { | ||
endpoint string | ||
} | ||
|
||
// Builder builds a new instance of the {bidder} 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 := &adapter{ | ||
endpoint: config.Endpoint, | ||
} | ||
return bidder, nil | ||
} | ||
|
||
func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { | ||
if request == nil { | ||
return nil, []error{&errortypes.BadInput{Message: "empty request"}} | ||
} | ||
if len(request.Imp) == 0 { | ||
return nil, []error{&errortypes.BadInput{Message: "empty request.Imp"}} | ||
} | ||
|
||
requests := make([]*adapters.RequestData, 0, len(request.Imp)) | ||
var errors []error | ||
|
||
requestCopy := *request | ||
for _, imp := range request.Imp { | ||
requestCopy.Imp = []openrtb2.Imp{imp} | ||
|
||
requestJSON, err := json.Marshal(request) | ||
if err != nil { | ||
errors = append(errors, err) | ||
continue | ||
} | ||
|
||
requestData := &adapters.RequestData{ | ||
Method: "POST", | ||
Uri: a.endpoint, | ||
Body: requestJSON, | ||
ImpIDs: []string{imp.ID}, | ||
} | ||
requests = append(requests, requestData) | ||
} | ||
return requests, errors | ||
} | ||
|
||
func getMediaTypeForBid(bid openrtb2.Bid) (openrtb_ext.BidType, error) { | ||
if bid.Ext != nil { | ||
var bidExt openrtb_ext.ExtBid | ||
err := json.Unmarshal(bid.Ext, &bidExt) | ||
if err == nil && bidExt.Prebid != nil { | ||
return openrtb_ext.ParseBidType(string(bidExt.Prebid.Type)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider this as a suggestion. Prebid server expects the media type to be explicitly set in the adapter response. Therefore, recommends implementing a pattern where the adapter server sets the MType field in the response to accurately determine the media type for the impression. |
||
} | ||
} | ||
|
||
return "", &errortypes.BadServerResponse{ | ||
Message: fmt.Sprintf("Failed to parse impression \"%s\" mediatype", bid.ImpID), | ||
} | ||
} | ||
|
||
func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) { | ||
if responseData.StatusCode == http.StatusNoContent { | ||
return nil, nil | ||
} | ||
|
||
if responseData.StatusCode == http.StatusBadRequest { | ||
err := &errortypes.BadInput{ | ||
Message: "Unexpected status code: 400. Bad request from publisher. Run with request.debug = 1 for more info.", | ||
} | ||
return nil, []error{err} | ||
} | ||
|
||
if responseData.StatusCode != http.StatusOK { | ||
err := &errortypes.BadServerResponse{ | ||
Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info.", responseData.StatusCode), | ||
} | ||
return nil, []error{err} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please reuse -
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
|
||
var response openrtb2.BidResponse | ||
if err := json.Unmarshal(responseData.Body, &response); err != nil { | ||
return nil, []error{err} | ||
} | ||
|
||
bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp)) | ||
bidResponse.Currency = response.Cur | ||
var errors []error | ||
for _, seatBid := range response.SeatBid { | ||
for i, bid := range seatBid.Bid { | ||
bidType, err := getMediaTypeForBid(bid) | ||
if err != nil { | ||
errors = append(errors, err) | ||
continue | ||
} | ||
bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ | ||
Bid: &seatBid.Bid[i], | ||
BidType: bidType, | ||
}) | ||
} | ||
} | ||
return bidResponse, nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package zentotem | ||
|
||
import ( | ||
"github.com/prebid/prebid-server/v2/adapters/adapterstest" | ||
"github.com/prebid/prebid-server/v2/config" | ||
"github.com/prebid/prebid-server/v2/openrtb_ext" | ||
"testing" | ||
) | ||
|
||
func TestJsonSamples(t *testing.T) { | ||
bidder, buildErr := Builder(openrtb_ext.BidderZentotem, config.Adapter{ | ||
Endpoint: "https://rtb.zentotem.net/bid?sspuid=cqlnvfk00bhs0b6rci6g"}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}) | ||
|
||
if buildErr != nil { | ||
t.Fatalf("Builder returned unexpected error %v", buildErr) | ||
} | ||
|
||
adapterstest.RunJSONBidderTest(t, "zentotemtest", bidder) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
{ | ||
"mockBidRequest": { | ||
"id": "058e84c8-3684-4725-be57-6a211fb8abc3", | ||
"at": 2, | ||
"bcat": [ "IAB8-18", "IAB8-5", "IAB9-9" ], | ||
"cur": [ | ||
"RUB" | ||
], | ||
"tmax": 250, | ||
"imp": [ | ||
{ | ||
"id": "test-imp-id", | ||
"bidfloor": 10, | ||
"bidfloorcur": "RUB", | ||
"tagid": "65f0c2a2feb788d7", | ||
"displaymanager": "Fyber", | ||
"displaymanagerver": "10.1.1", | ||
"banner": { | ||
"api": [ | ||
4,5 | ||
], | ||
"mimes": [ | ||
"application/javascript", | ||
"text/html", | ||
"text/javascript", | ||
"image/png", | ||
"image/jpeg", | ||
"image/gif" | ||
] | ||
}, | ||
"instl": 1 | ||
} | ||
], | ||
"app": { | ||
"privacypolicy": 1, | ||
"paid": 0, | ||
"id": "1757830", | ||
"name": "some-app-name", | ||
"bundle": "some-app-bundle", | ||
"storeurl": "some-store-url", | ||
"cat": [ | ||
|
||
"IAB1-1" | ||
], | ||
"publisher": { | ||
"id": "gambling" | ||
} | ||
}, | ||
"device": { | ||
"dnt": 0, | ||
"devicetype": 4, | ||
"h": 980, | ||
"w": 350, | ||
"connectiontype": 2, | ||
"ua": "Mozilla/5.0 (Linux; Android 10; YAL-L21 Build/HUAWEIYAL-L21; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/113.0.5672.131 Mobile Safari/537.36", | ||
"ip": "95.104.196.182", | ||
"make": "Huawei", | ||
"model": "YAL-L21", | ||
"os": "Android", | ||
"osv": "10.0", | ||
"ifa": "6cecfc3c-de97-4861-ba6c-41a9dc94b391", | ||
"geo": { | ||
"country": "RUS" | ||
} | ||
}, | ||
"user": { | ||
"id": "6cecfc3c-de97-4861-ba6c-41a9dc94b391" | ||
} | ||
}, | ||
"httpCalls": [ | ||
{ | ||
"expectedRequest": { | ||
"uri": "https://rtb.zentotem.net/bid?sspuid=cqlnvfk00bhs0b6rci6g", | ||
"body": { | ||
"id": "058e84c8-3684-4725-be57-6a211fb8abc3", | ||
"at": 2, | ||
"bcat": [ "IAB8-18", "IAB8-5", "IAB9-9" ], | ||
"cur": [ | ||
"RUB" | ||
], | ||
"tmax": 250, | ||
"imp": [ | ||
{ | ||
"id": "test-imp-id", | ||
"bidfloor": 10, | ||
"bidfloorcur": "RUB", | ||
"tagid": "65f0c2a2feb788d7", | ||
"displaymanager": "Fyber", | ||
"displaymanagerver": "10.1.1", | ||
"banner": { | ||
"api": [ | ||
4,5 | ||
], | ||
"mimes": [ | ||
"application/javascript", | ||
"text/html", | ||
"text/javascript", | ||
"image/png", | ||
"image/jpeg", | ||
"image/gif" | ||
] | ||
}, | ||
"instl": 1 | ||
} | ||
], | ||
"app": { | ||
"privacypolicy": 1, | ||
"paid": 0, | ||
"id": "1757830", | ||
"name": "some-app-name", | ||
"bundle": "some-app-bundle", | ||
"storeurl": "some-store-url", | ||
"cat": [ | ||
|
||
"IAB1-1" | ||
], | ||
"publisher": { | ||
"id": "gambling" | ||
} | ||
}, | ||
"device": { | ||
"dnt": 0, | ||
"devicetype": 4, | ||
"h": 980, | ||
"w": 350, | ||
"connectiontype": 2, | ||
"ua": "Mozilla/5.0 (Linux; Android 10; YAL-L21 Build/HUAWEIYAL-L21; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/113.0.5672.131 Mobile Safari/537.36", | ||
"ip": "95.104.196.182", | ||
"make": "Huawei", | ||
"model": "YAL-L21", | ||
"os": "Android", | ||
"osv": "10.0", | ||
"ifa": "6cecfc3c-de97-4861-ba6c-41a9dc94b391", | ||
"geo": { | ||
"country": "RUS" | ||
} | ||
}, | ||
"user": { | ||
"id": "6cecfc3c-de97-4861-ba6c-41a9dc94b391" | ||
} | ||
}, | ||
"impIDs":["test-imp-id"] | ||
}, | ||
"mockResponse": { | ||
"status": 200, | ||
"body": { | ||
"id": "test-request-id", | ||
"seatbid": [ | ||
{ | ||
"bid": [ | ||
{ | ||
"id": "36", | ||
"impid": "1", | ||
"price": 150, | ||
"nurl": "some-test-nurl", | ||
"burl": "some-test-burl", | ||
"adm": "some-test-adm", | ||
"adid": "36", | ||
"adomain": [ | ||
"app.apple.com" | ||
], | ||
"crid": "36" | ||
} | ||
], | ||
"seat": "boldwin" | ||
} | ||
], | ||
"cur": "USD" | ||
} | ||
} | ||
} | ||
], | ||
"expectedBidResponses": [ | ||
{ | ||
"bid": [ | ||
{ | ||
"id": "36", | ||
"impid": "1", | ||
"price": 150, | ||
"nurl": "some-test-nurl", | ||
"burl": "some-test-burl", | ||
"adm": "some-test-adm", | ||
"adid": "36", | ||
"adomain": [ | ||
"app.apple.com" | ||
], | ||
"crid": "36" | ||
} | ||
] | ||
} | ||
] | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to perform these checks. These are covered by the core predid server code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed