Skip to content
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: pwbid #2657

Merged
merged 11 commits into from
Apr 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions adapters/pwbid/params_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package pwbid

import (
"encoding/json"
"testing"

"github.com/prebid/prebid-server/openrtb_ext"
)

func TestValidParams(t *testing.T) {
validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
if err != nil {
t.Fatalf("Failed to fetch the json schema. %v", err)
}

for _, p := range validParams {
if err := validator.Validate(openrtb_ext.BidderPWBid, json.RawMessage(p)); err != nil {
t.Errorf("Schema rejected valid params: %s", p)
}
}
}

func TestInvalidParams(t *testing.T) {
validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
if err != nil {
t.Fatalf("Failed to fetch the json schema. %v", err)
}

for _, p := range invalidParams {
if err := validator.Validate(openrtb_ext.BidderPWBid, json.RawMessage(p)); err == nil {
t.Errorf("Schema allowed invalid params: %s", p)
}
}
}

var validParams = []string{
Sonali-More-Xandr marked this conversation as resolved.
Show resolved Hide resolved
`{"siteId":"39f43a","bidFloor":0.10,"isTest":false}`,
`{"siteId":"39f43a","bidFloor":0.10,"isTest":true}`,
`{"siteId":"39f43a","bidFloor":0.10}`,
`{"siteId":"39f43a"}`,
}

var invalidParams = []string{
`{"siteId":42,"bidFloor":"asdf","isTest":123}`,
`{"siteId":}`,
`{"bidFloor":}`,
`{"bidFloor":0.10}`,
`null`,
}
97 changes: 97 additions & 0 deletions adapters/pwbid/pwbid.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package pwbid

import (
"encoding/json"
"fmt"

"github.com/prebid/openrtb/v17/openrtb2"
"github.com/prebid/prebid-server/adapters"
"github.com/prebid/prebid-server/config"
"github.com/prebid/prebid-server/errortypes"
"github.com/prebid/prebid-server/openrtb_ext"
"github.com/prebid/prebid-server/util/httputil"
)

type adapter struct {
endpoint string
}

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) {
requestJSON, err := json.Marshal(request)
if err != nil {
return nil, []error{err}
}

requestData := &adapters.RequestData{
Method: "POST",
Uri: a.endpoint,
Body: requestJSON,
}

return []*adapters.RequestData{requestData}, nil
}

func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) {
var errors []error

if httputil.IsResponseStatusCodeNoContent(responseData) {
return nil, nil
}

if err := httputil.CheckResponseStatusCodeForErrors(responseData); err != nil {
return nil, []error{err}
}

var response openrtb2.BidResponse
if err := json.Unmarshal(responseData.Body, &response); err != nil {
return nil, []error{err}
}

bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp))

for _, seatBid := range response.SeatBid {
for i, bid := range seatBid.Bid {
bidType, typeErr := getMediaTypeForBid(request.Imp, bid)
if typeErr != nil {
errors = append(errors, typeErr)
continue
}

b := &adapters.TypedBid{
Bid: &seatBid.Bid[i],
BidType: bidType,
}
bidResponse.Bids = append(bidResponse.Bids, b)
}
}

return bidResponse, errors
}

func getMediaTypeForBid(impressions []openrtb2.Imp, bid openrtb2.Bid) (openrtb_ext.BidType, error) {
for _, impression := range impressions {
if impression.ID == bid.ImpID {
if impression.Banner != nil {
return openrtb_ext.BidTypeBanner, nil
}
if impression.Native != nil {
return openrtb_ext.BidTypeNative, nil
}
if impression.Video != nil {
return openrtb_ext.BidTypeVideo, nil
}
Comment on lines +82 to +90
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning - If request has multi format bid, this code will by default set the bid type to Banner. Is that the intention here? Preferred way would be bidder server using MType field available in seatBid.Bid to determine media type

	// Attribute:
	//   mtype
	// Type:
	//   integer
	// Description:
	//   Type of the creative markup so that it can properly be
	//   associated with the right sub-object of the BidRequest.Imp.
	//   Values:
	//   1 = Banner
	//   2 = Video
	//   3 = Audio
	//   4 = Native
	MType MarkupType `json:"mtype,omitempty"`

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with you on this, however I have not been able to find a working example of this. Do you know of an adapter that is accepting multi format bids?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The IX adapter uses mtype. There is some overhead currently required which will go away in the near future.

func getMediaTypeForBid(bid openrtb2.Bid, impMediaTypeReq map[string]openrtb_ext.BidType) (openrtb_ext.BidType, error) {

Several other adapters use custom fields in their response, such as AAX.

func getMediaTypeForImp(bid openrtb2.Bid, imps []openrtb2.Imp) (openrtb_ext.BidType, error) {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the examples! @SyntaxNode

Do you have a reference to where this mtype overhead is going to be addressed?

Where we're at now is, let's get this out in the current state, it should be sufficient for our needs and we can update this later. Especially if there's an update in the pipe to make this better.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay. But as fyi, multi-format bid won't be correctly supported by current state

}
}

return "", &errortypes.BadServerResponse{
Message: fmt.Sprintf("The impression with ID %s is not present into the request", bid.ImpID),
}
}
21 changes: 21 additions & 0 deletions adapters/pwbid/pwbid_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package pwbid

import (
"testing"

"github.com/prebid/prebid-server/adapters/adapterstest"
"github.com/prebid/prebid-server/config"
"github.com/prebid/prebid-server/openrtb_ext"
)

func TestJsonSamples(t *testing.T) {
bidder, buildErr := Builder(openrtb_ext.BidderPWBid, config.Adapter{
Endpoint: "https://bid.pubwise.io/prebid"},
config.Server{ExternalUrl: "http://hosturl.com", GvlID: 842, DataCenter: "2"})

if buildErr != nil {
t.Fatalf("Builder returned unexpected error %v", buildErr)
}

adapterstest.RunJSONBidderTest(t, "pwbidtest", bidder)
}
93 changes: 93 additions & 0 deletions adapters/pwbid/pwbidtest/exemplary/banner.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
{
"mockBidRequest": {
"id": "test-request-id-banner",
"imp": [
{
"id": "test-imp-id-banner",
"banner": {
"format": [
{
"w": 728,
"h": 90
}
]
},
"ext": {
"bidder": {
"siteId": "3943fa"
}
}
}
]
},
"httpCalls": [
{
"expectedRequest": {
"uri": "https://bid.pubwise.io/prebid",
"body": {
"id": "test-request-id-banner",
"imp": [
{
"id": "test-imp-id-banner",
"banner": {
"format": [
{
"w": 728,
"h": 90
}
]
},
"ext": {
"bidder": {
"siteId": "3943fa"
}
}
}
]
}
},
"mockResponse": {
"status": 200,
"body": {
"id": "test-request-id-banner",
"seatbid": [
{
"seat": "pwbid",
"bid": [
{
"id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
"impid": "test-imp-id-banner",
"price": 0.500000,
"adm": "some-test-ad-banner",
"crid": "crid_10",
"w": 728,
"h": 90
}
]
}
],
"cur": "USD"
}
}
}
],
"expectedBidResponses": [
{
"currency": "USD",
"bids": [
{
"bid": {
"id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
"impid": "test-imp-id-banner",
"price": 0.5,
"adm": "some-test-ad-banner",
"crid": "crid_10",
"w": 728,
"h": 90
},
"type": "banner"
}
]
}
]
}
81 changes: 81 additions & 0 deletions adapters/pwbid/pwbidtest/exemplary/native.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
{
"mockBidRequest": {
"id": "test-request-id-native",
"imp": [
{
"id": "test-imp-id-native",
"native": {
"request": ""
},
"ext": {
"bidder": {
"siteId": "39f43a"
}
}
}
]
},
"httpCalls": [
{
"expectedRequest": {
"uri": "https://bid.pubwise.io/prebid",
"body": {
"id": "test-request-id-native",
"imp": [
{
"id": "test-imp-id-native",
"native": {
"request": ""
},
"ext": {
"bidder": {
"siteId": "39f43a"
}
}
}
]
}
},
"mockResponse": {
"status": 200,
"body": {
"id": "test-request-id-native",
"seatbid": [
{
"seat": "pwbid",
"bid": [{
"id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
"impid": "test-imp-id-native",
"price": 0.500000,
"adm": "some-test-ad-native",
"crid": "crid_10",
"w": 728,
"h": 90
}]
}
],
"cur": "USD"
}
}
}
],
"expectedBidResponses": [
{
"currency": "USD",
"bids": [
{
"bid": {
"id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
"impid": "test-imp-id-native",
"price": 0.5,
"adm": "some-test-ad-native",
"crid": "crid_10",
"w": 728,
"h": 90
},
"type": "native"
}
]
}
]
}
Loading