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

Commit

Permalink
Add ValueImpression Adapter (prebid#1204)
Browse files Browse the repository at this point in the history
  • Loading branch information
thuyhq authored Mar 16, 2020
1 parent f7d91f9 commit c3c56af
Show file tree
Hide file tree
Showing 24 changed files with 994 additions and 0 deletions.
52 changes: 52 additions & 0 deletions adapters/valueimpression/params_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package valueimpression

import (
"encoding/json"
"testing"

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

// This file actually intends to test static/bidder-params/valueimpression.json
// These also validate the format of the external API: request.imp[i].ext.valueimpression
// TestValidParams makes sure that the ValueImpression 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.BidderValueImpression, json.RawMessage(validParam)); err != nil {
t.Errorf("Schema rejected ValueImpression params: %s", validParam)
}
}
}

// TestInvalidParams makes sure that the ValueImpression 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.BidderValueImpression, json.RawMessage(invalidParam)); err == nil {
t.Errorf("Schema allowed unexpected params: %s", invalidParam)
}
}
}

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

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

import (
"text/template"

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

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

import (
"testing"
"text/template"

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

func TestValueImpressionSyncer(t *testing.T) {
syncURL := "https://rtb.valueimpression.com/usersync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&redirectUri=http%3A%2F%2Flocalhost:8000%2Fsetuid%3Fbidder%3Dvalueimpression%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID"
syncURLTemplate := template.Must(
template.New("sync-template").Parse(syncURL),
)

syncer := NewValueImpressionSyncer(syncURLTemplate)
syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{
GDPR: gdpr.Policy{
Signal: "1",
Consent: "BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA",
},
CCPA: ccpa.Policy{
Value: "1NYN",
},
})

assert.NoError(t, err)
assert.Equal(t, "https://rtb.valueimpression.com/usersync?gdpr=1&gdpr_consent=BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA&redirectUri=http%3A%2F%2Flocalhost:8000%2Fsetuid%3Fbidder%3Dvalueimpression%26gdpr%3D1%26gdpr_consent%3DBOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA%26uid%3D%24UID", syncInfo.URL)
assert.Equal(t, "redirect", syncInfo.Type)
assert.EqualValues(t, 0, syncer.GDPRVendorID())
assert.False(t, syncInfo.SupportCORS)
}
154 changes: 154 additions & 0 deletions adapters/valueimpression/valueimpression.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
package valueimpression

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 ValueImpressionAdapter struct {
endpoint string
}

func (a *ValueImpressionAdapter) MakeRequests(request *openrtb.BidRequest, unused *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
var errs []error
var adapterRequests []*adapters.RequestData

if err := preprocess(request); err != nil {
errs = append(errs, err)
return nil, errs
}

adapterReq, err := a.makeRequest(request)
if err != nil {
errs = append(errs, err)
return nil, errs
}

adapterRequests = append(adapterRequests, adapterReq)

return adapterRequests, errs
}

func (a *ValueImpressionAdapter) makeRequest(request *openrtb.BidRequest) (*adapters.RequestData, error) {
var err error

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

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

return &adapters.RequestData{
Method: "POST",
Uri: a.endpoint,
Body: jsonBody,
Headers: headers,
}, nil
}

func preprocess(request *openrtb.BidRequest) error {
if len(request.Imp) == 0 {
return &errortypes.BadInput{
Message: "No Imps in Bid Request",
}
}
for i := 0; i < len(request.Imp); i++ {
var imp = &request.Imp[i]
var bidderExt adapters.ExtImpBidder

if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil {
return &errortypes.BadInput{
Message: err.Error(),
}
}

var extImp openrtb_ext.ExtImpValueImpression
if err := json.Unmarshal(bidderExt.Bidder, &extImp); err != nil {
return &errortypes.BadInput{
Message: err.Error(),
}
}

imp.Ext = bidderExt.Bidder
}

return nil
}

// MakeBids based on valueimpression server response
func (a *ValueImpressionAdapter) MakeBids(bidRequest *openrtb.BidRequest, unused *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) {
if responseData.StatusCode == http.StatusNoContent {
return nil, nil
}

if responseData.StatusCode == http.StatusBadRequest {
return nil, []error{&errortypes.BadInput{
Message: fmt.Sprintf("Bad user input: HTTP status %d", responseData.StatusCode),
}}
}

if responseData.StatusCode != http.StatusOK {
return nil, []error{&errortypes.BadServerResponse{
Message: fmt.Sprintf("Bad server response: HTTP status %d", responseData.StatusCode),
}}
}

var bidResponse openrtb.BidResponse

if err := json.Unmarshal(responseData.Body, &bidResponse); err != nil {
return nil, []error{&errortypes.BadServerResponse{
Message: err.Error(),
}}
}

if len(bidResponse.SeatBid) == 0 {
return nil, nil
}

rv := adapters.NewBidderResponseWithBidsCapacity(len(bidResponse.SeatBid[0].Bid))
var errors []error

for _, seatbid := range bidResponse.SeatBid {
for _, bid := range seatbid.Bid {
foundMatchingBid := false
bidType := openrtb_ext.BidTypeBanner
for _, imp := range bidRequest.Imp {
if imp.ID == bid.ImpID {
foundMatchingBid = true
if imp.Banner != nil {
bidType = openrtb_ext.BidTypeBanner
} else if imp.Video != nil {
bidType = openrtb_ext.BidTypeVideo
}
break
}
}

if foundMatchingBid {
rv.Bids = append(rv.Bids, &adapters.TypedBid{
Bid: &bid,
BidType: bidType,
})
} else {
errors = append(errors, &errortypes.BadServerResponse{
Message: fmt.Sprintf("bid id='%s' could not find valid impid='%s'", bid.ID, bid.ImpID),
})
}
}
}
return rv, errors
}

func NewValueImpressionBidder(endpoint string) *ValueImpressionAdapter {
return &ValueImpressionAdapter{
endpoint: endpoint,
}
}
11 changes: 11 additions & 0 deletions adapters/valueimpression/valueimpression_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package valueimpression

import (
"testing"

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

func TestJsonSamples(t *testing.T) {
adapterstest.RunJSONBidderTest(t, "valueimpressiontest", NewValueImpressionBidder("//host"))
}
Loading

0 comments on commit c3c56af

Please sign in to comment.