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: apacdex and Remove Adapter: valueimpression #2097

Merged
merged 10 commits into from
Dec 20, 2021
181 changes: 181 additions & 0 deletions adapters/apacdex/apacdex.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
package apacdex

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

"github.com/mxmCherry/openrtb/v15/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"
)

type apacdexAdapter struct {
thuyhq marked this conversation as resolved.
Show resolved Hide resolved
endpoint string
}

// Builder builds a new instance of the Apacdex adapter for the given bidder with the given config.
func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters.Bidder, error) {
bidder := &apacdexAdapter{
endpoint: config.Endpoint,
}
return bidder, nil
}

func (a *apacdexAdapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *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 *apacdexAdapter) makeRequest(request *openrtb2.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")
headers.Add("Accept", "application/json")
headers.Add("x-openrtb-version", "2.5")

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

func preprocess(request *openrtb2.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.ExtImpApacdex
if err := json.Unmarshal(bidderExt.Bidder, &extImp); err != nil {
return &errortypes.BadInput{
Message: err.Error(),
}
}

imp.Ext = bidderExt.Bidder
}

return nil
}

func (a *apacdexAdapter) 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}
}

var response openrtb2.BidResponse

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

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

bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp))
bidResponse.Currency = response.Cur
var errors []error

for _, seatbid := range response.SeatBid {
for _, bid := range seatbid.Bid {
imp, err := getImpressionForBid(request.Imp, bid.ImpID)
if err != nil {
errors = append(errors, &errortypes.BadServerResponse{
thuyhq marked this conversation as resolved.
Show resolved Hide resolved
Message: fmt.Sprintf("bid id='%s' could not find valid impid='%s'", bid.ID, bid.ImpID),
})
continue
}

bidType := openrtb_ext.BidTypeBanner
thuyhq marked this conversation as resolved.
Show resolved Hide resolved
if imp.Banner != nil {
bidType = openrtb_ext.BidTypeBanner
} else if imp.Video != nil {
bidType = openrtb_ext.BidTypeVideo
} else if imp.Audio != nil {
bidType = openrtb_ext.BidTypeAudio
} else if imp.Native != nil {
bidType = openrtb_ext.BidTypeNative
} else {
errors = append(errors, &errortypes.BadServerResponse{
Message: fmt.Sprintf("Unknown bidType for bid id='%s'", bid.ID),
})
continue
}

bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
Bid: &bid,
BidType: bidType,
})
}
}
return bidResponse, errors
}

func getImpressionForBid(imps []openrtb2.Imp, impID string) (openrtb2.Imp, error) {
result := openrtb2.Imp{}
found := false
for _, imp := range imps {
if imp.ID == impID {
result = imp
found = true
break
}
}
if found {
return result, nil
}
return result, fmt.Errorf("not found impression matched with ImpID=%s", impID)
}
thuyhq marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package valueimpression
package apacdex

import (
"testing"
Expand All @@ -9,12 +9,12 @@ import (
)

func TestJsonSamples(t *testing.T) {
bidder, buildErr := Builder(openrtb_ext.BidderValueImpression, config.Adapter{
bidder, buildErr := Builder(openrtb_ext.BidderApacdex, config.Adapter{
Endpoint: "//host"})

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

adapterstest.RunJSONBidderTest(t, "valueimpressiontest", bidder)
adapterstest.RunJSONBidderTest(t, "apacdextest", bidder)
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
"id": "test-request-id",
"seatbid": [
{
"seat": "valueimpression",
"seat": "apacdex",
"bid": [
{
"id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
"id": "test-request-id",
"seatbid": [
{
"seat": "valueimpression",
"seat": "apacdex",
"bid": [
{
"id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
Expand Down Expand Up @@ -95,4 +95,3 @@
}
]
}

Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@

"expectedMakeBidsErrors": [
{
"value": "Bad server response: HTTP status 500",
"value": "Unexpected status code: 500. Run with request.debug = 1 for more info.",
"comparison": "literal"
}
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

"expectedMakeRequestsErrors": [
{
"value": "json: cannot unmarshal number into Go struct field ExtImpValueImpression.siteId of type string",
"value": "json: cannot unmarshal number into Go struct field ExtImpApacdex.siteId of type string",
"comparison": "literal"
}
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
"bid": [
{
"id": "test-bid-id",
"impid": "BOGUS-IMPID",
"impid": "another-imp-id",
"price": 3.5,
"w": 900,
"h": 250
Expand All @@ -68,7 +68,7 @@
],
"expectedMakeBidsErrors": [
{
"value": "bid id='test-bid-id' could not find valid impid='BOGUS-IMPID'",
"value": "bid id='test-bid-id' could not find valid impid='another-imp-id'",
"comparison": "regex"
}
]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package valueimpression
package apacdex

import (
"encoding/json"
Expand All @@ -7,9 +7,9 @@ import (
"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.
// This file actually intends to test static/bidder-params/apacdex.json
// These also validate the format of the external API: request.imp[i].ext.apacdex
// TestValidParams makes sure that the Apacdex schema accepts all imp.ext fields which we intend to support.

func TestValidParams(t *testing.T) {
validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
Expand All @@ -18,35 +18,39 @@ func TestValidParams(t *testing.T) {
}

for _, validParam := range validParams {
if err := validator.Validate(openrtb_ext.BidderValueImpression, json.RawMessage(validParam)); err != nil {
t.Errorf("Schema rejected ValueImpression params: %s", validParam)
if err := validator.Validate(openrtb_ext.BidderApacdex, json.RawMessage(validParam)); err != nil {
t.Errorf("Schema rejected Apacdex params: %s", validParam)
}
}
}

// TestInvalidParams makes sure that the ValueImpression schema rejects all the imp.ext fields we don't support.
// TestInvalidParams makes sure that the Apacdex 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 {
if err := validator.Validate(openrtb_ext.BidderApacdex, json.RawMessage(invalidParam)); err == nil {
t.Errorf("Schema allowed unexpected params: %s", invalidParam)
}
}
}

var validParams = []string{
`{"siteId": "123"}`,
`{"siteId": "123", "floorPrice": 0.05}`,
`{"placementId": "123123"}`,
`{"placementId": "123123", "floorPrice": 0.05}`,
}

var invalidParams = []string{
`{}`,
`null`,
`true`,
`154`,
`{"siteId": 123}`, // siteId should be string
`{"siteId": 123}`,
`{"invalid_param": "123"}`,
`{"siteId": "123", "placementId": "123123"}`,
}
Loading