Skip to content
This repository has been archived by the owner on Dec 22, 2022. It is now read-only.

Commit

Permalink
Yieldone s2s Bid Adapter (prebid#1242)
Browse files Browse the repository at this point in the history
* Added new Yieldone Bid s2s Adapter

* Update endpoint for yieldone bid adapter

* Fixes after review for Yieldone Bid s2s Adapter

* Fix typeo in Yieldone s2s Bid Adapter
  • Loading branch information
hbanalytics authored Apr 22, 2020
1 parent 5c581b7 commit ba075cb
Show file tree
Hide file tree
Showing 20 changed files with 721 additions and 0 deletions.
48 changes: 48 additions & 0 deletions adapters/yieldone/params_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package yieldone

import (
"encoding/json"
"github.com/prebid/prebid-server/openrtb_ext"
"testing"
)

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.BidderYieldone, json.RawMessage(validParam)); err != nil {
t.Errorf("Schema rejected Yieldone params: %s", validParam)
}
}
}

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.BidderYieldone, json.RawMessage(invalidParam)); err == nil {
t.Errorf("Schema allowed unexpected params: %s", invalidParam)
}
}
}

var validParams = []string{
`{"placementId": "123"}`,
}

var invalidParams = []string{
`null`,
`nil`,
``,
`[]`,
`true`,
`2`,
`{"invalid_param": "123"}`,
`{"placementId": 123}`,
}
12 changes: 12 additions & 0 deletions adapters/yieldone/usersync.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package yieldone

import (
"text/template"

"github.com/prebid/prebid-server/adapters"
"github.com/prebid/prebid-server/usersync"
)

func NewYieldoneSyncer(temp *template.Template) usersync.Usersyncer {
return adapters.NewSyncer("yieldone", 0, temp, adapters.SyncTypeRedirect)
}
30 changes: 30 additions & 0 deletions adapters/yieldone/usersync_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package yieldone

import (
"testing"
"text/template"

"github.com/prebid/prebid-server/privacy"
"github.com/prebid/prebid-server/privacy/gdpr"
"github.com/stretchr/testify/assert"
)

func TestYieldoneSyncer(t *testing.T) {
syncURL := "//not_localhost/synclocalhost%2Fsetuid%3Fbidder%3Dyieldone%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID"
syncURLTemplate := template.Must(
template.New("sync-template").Parse(syncURL),
)

syncer := NewYieldoneSyncer(syncURLTemplate)
syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{
GDPR: gdpr.Policy{
Signal: "0",
},
})

assert.NoError(t, err)
assert.Equal(t, "//not_localhost/synclocalhost%2Fsetuid%3Fbidder%3Dyieldone%26gdpr%3D0%26gdpr_consent%3D%26uid%3D%24UID", syncInfo.URL)
assert.Equal(t, "redirect", syncInfo.Type)
assert.EqualValues(t, 0, syncer.GDPRVendorID())
assert.Equal(t, false, syncInfo.SupportCORS)
}
144 changes: 144 additions & 0 deletions adapters/yieldone/yieldone.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package yieldone

import (
"encoding/json"
"fmt"
"net/http"

"github.com/mxmCherry/openrtb"
"github.com/prebid/prebid-server/adapters"
"github.com/prebid/prebid-server/errortypes"
"github.com/prebid/prebid-server/openrtb_ext"
)

type YieldoneAdapter struct {
endpoint string
}

// MakeRequests makes the HTTP requests which should be made to fetch bids.
func (a *YieldoneAdapter) MakeRequests(request *openrtb.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
var errors = make([]error, 0)

var validImps []openrtb.Imp
for i := 0; i < len(request.Imp); i++ {
if err := preprocess(&request.Imp[i]); err == nil {
validImps = append(validImps, request.Imp[i])
} else {
errors = append(errors, err)
}
}

request.Imp = validImps

reqJSON, err := json.Marshal(request)
if err != nil {
errors = append(errors, err)
return nil, errors
}

headers := http.Header{}
headers.Add("Content-Type", "application/json;charset=utf-8")

return []*adapters.RequestData{{
Method: "POST",
Uri: a.endpoint,
Body: reqJSON,
Headers: headers,
}}, errors
}

// MakeBids unpacks the server's response into Bids.
func (a *YieldoneAdapter) MakeBids(internalRequest *openrtb.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
if response.StatusCode == http.StatusNoContent {
return nil, nil
}

if response.StatusCode == http.StatusBadRequest {
return nil, []error{&errortypes.BadInput{
Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode),
}}
}

if response.StatusCode != http.StatusOK {
return nil, []error{&errortypes.BadServerResponse{
Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode),
}}
}

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

bidResponse := adapters.NewBidderResponseWithBidsCapacity(1)

for _, sb := range bidResp.SeatBid {
for i := range sb.Bid {
bidType, err := getMediaTypeForImp(sb.Bid[i].ImpID, internalRequest.Imp)
if err != nil {
return nil, []error{err}
}

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

}

// NewYieldoneBidder configure bidder endpoint
func NewYieldoneBidder(endpoint string) *YieldoneAdapter {
return &YieldoneAdapter{
endpoint: endpoint,
}
}

func preprocess(imp *openrtb.Imp) error {

var ext adapters.ExtImpBidder
if err := json.Unmarshal(imp.Ext, &ext); err != nil {
return err
}
var impressionExt openrtb_ext.ExtImpYieldone
if err := json.Unmarshal(ext.Bidder, &impressionExt); err != nil {
return err
}

if imp.Banner != nil {
bannerCopy := *imp.Banner
if bannerCopy.W == nil && bannerCopy.H == nil && len(bannerCopy.Format) > 0 {
firstFormat := bannerCopy.Format[0]
bannerCopy.W = &(firstFormat.W)
bannerCopy.H = &(firstFormat.H)
}
imp.Banner = &bannerCopy
}

return nil
}

func getMediaTypeForImp(impID string, imps []openrtb.Imp) (openrtb_ext.BidType, error) {
for _, imp := range imps {
if imp.ID == impID {
if imp.Banner != nil {
return openrtb_ext.BidTypeBanner, nil
}

if imp.Video != nil {
return openrtb_ext.BidTypeVideo, nil
}

return "", &errortypes.BadServerResponse{
Message: fmt.Sprintf("Unknown impression type for ID: \"%s\"", impID),
}
}
}

// This shouldnt happen. Lets handle it just incase by returning an error.
return "", &errortypes.BadServerResponse{
Message: fmt.Sprintf("Failed to find impression for ID: \"%s\"", impID),
}
}
11 changes: 11 additions & 0 deletions adapters/yieldone/yieldone_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package yieldone

import (
"testing"

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

func TestJsonSamples(t *testing.T) {
adapterstest.RunJSONBidderTest(t, "yieldonetest", NewYieldoneBidder("http://localhost/prebid"))
}
89 changes: 89 additions & 0 deletions adapters/yieldone/yieldonetest/exemplary/simple-banner.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
{
"mockBidRequest": {
"id": "test-request-id",
"site": {
"page": "https://good.site/url"
},
"imp": [{
"id": "test-imp-id",
"banner": {
"format": [{
"w": 300,
"h": 250
}]
},
"ext": {
"bidder": {
"placementId": "36891"
}
}
}]
},

"httpCalls": [{
"expectedRequest": {
"uri": "http://localhost/prebid",
"body": {
"id": "test-request-id",
"site": {
"page": "https://good.site/url"
},
"imp": [{
"id": "test-imp-id",
"banner": {
"format": [{
"w": 300,
"h": 250
}],
"w": 300,
"h": 250
},
"ext": {
"bidder": {
"placementId": "36891"
}
}
}]
}
},
"mockResponse": {
"status": 200,
"body": {
"id": "test-request-id",
"seatbid": [{
"seat": "yieldone",
"bid": [{
"id": "randomid",
"impid": "test-imp-id",
"price": 0.500000,
"adid": "12345678",
"adm": "some-test-ad",
"cid": "987",
"crid": "12345678",
"h": 250,
"w": 300
}]
}],
"cur": "JPY"
}
}
}],

"expectedBidResponses": [{
"currency": "JPY",
"bids": [{
"bid": {
"id": "randomid",
"impid": "test-imp-id",
"price": 0.5,
"adm": "some-test-ad",
"adid": "12345678",
"cid": "987",
"crid": "12345678",
"w": 300,
"h": 250
},
"type": "banner"
}]
}]
}
Loading

0 comments on commit ba075cb

Please sign in to comment.