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

Commit

Permalink
SomoAudience adapter: Cleanup of code and adding an optional parameter (
Browse files Browse the repository at this point in the history
prebid#664)

* Prebid server reworking and optional params

* Removed some copy and paste errors
  • Loading branch information
SuprPhatAnon authored and dbemiller committed Sep 21, 2018
1 parent 3c11999 commit 939f355
Show file tree
Hide file tree
Showing 16 changed files with 163 additions and 122 deletions.
3 changes: 3 additions & 0 deletions adapters/somoaudience/params_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,12 @@ func TestInvalidParams(t *testing.T) {

var validParams = []string{
`{"placement_hash":"22a58cfb0c9b656bff713d1236e930e8"}`,
`{"placement_hash":"22a58cfb0c9b656bff713d1236e930e8", "bid_floor": 1.05}`,
}

var invalidParams = []string{
`{"placement_hash": 323423}`,
`{"tag_id":"234234"}`,
`{"placement_hash":"22a58cfb0c9b656bff713d1236e930e8", "bid_floor": "423s"}`,
`{"placement_hash":"22a58cfb0c9b656bff713d1236e930e8", "bid_floor": -1}`,
}
189 changes: 119 additions & 70 deletions adapters/somoaudience/somoaudience.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,81 +4,156 @@ import (
"encoding/json"
"fmt"
"net/http"
"strconv"

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

const config = "hb_pbs_1.0.0"

type SomoaudienceAdapter struct {
endpoint string
}

type somoaudienceReqExt struct {
BidderConfig string `json:"prebid"`
}

func (a *SomoaudienceAdapter) MakeRequests(request *openrtb.BidRequest) ([]*adapters.RequestData, []error) {

totalImps := len(request.Imp)
errors := make([]error, 0, totalImps)
imp2placement := make(map[string][]int)
var errs []error
var bannerImps []openrtb.Imp
var videoImps []openrtb.Imp
var nativeImps []openrtb.Imp

for _, imp := range request.Imp {
if imp.Banner != nil {
bannerImps = append(bannerImps, imp)
} else if imp.Video != nil {
videoImps = append(videoImps, imp)
} else if imp.Native != nil {
nativeImps = append(nativeImps, imp)
} else {
err := &errortypes.BadInput{
Message: fmt.Sprintf("SomoAudience only supports banner and video imps. Ignoring imp id=%s", imp.ID),
}
glog.Warning("SomoAudience CAPABILITY VIOLATION: only supports banner and video imps")
errs = append(errs, err)
}
}
var adapterRequests []*adapters.RequestData
// Make a copy as we don't want to change the original request
reqCopy := *request

reqCopy.Imp = bannerImps
adapterReq, errors := a.makeRequest(&reqCopy)
if adapterReq != nil {
adapterRequests = append(adapterRequests, adapterReq)
}
errs = append(errs, errors...)

// Somoaudience only supports single imp video request
for _, videoImp := range videoImps {
reqCopy.Imp = []openrtb.Imp{videoImp}
adapterReq, errors := a.makeRequest(&reqCopy)
if adapterReq != nil {
adapterRequests = append(adapterRequests, adapterReq)
}
errs = append(errs, errors...)
}

// Somoaudience only supports single imp video request
for _, nativeImp := range nativeImps {
reqCopy.Imp = []openrtb.Imp{nativeImp}
adapterReq, errors := a.makeRequest(&reqCopy)
if adapterReq != nil {
adapterRequests = append(adapterRequests, adapterReq)
}
errs = append(errs, errors...)
}
return adapterRequests, errs

}

for i := 0; i < totalImps; i++ {
func (a *SomoaudienceAdapter) makeRequest(request *openrtb.BidRequest) (*adapters.RequestData, []error) {
var errs []error
var err error
var validImps []openrtb.Imp
reqExt := somoaudienceReqExt{BidderConfig: config}

placementHash, err := validateImpression(&request.Imp[i])
var placementHash string

for _, imp := range request.Imp {
placementHash, err = preprocess(&imp, &reqExt)
if err != nil {
errors = append(errors, err)
errs = append(errs, err)
continue
}
imp.Ext = nil
validImps = append(validImps, imp)
}

if _, ok := imp2placement[placementHash]; !ok {
imp2placement[placementHash] = make([]int, 0, totalImps-i)
}
// If all the imps were malformed, don't bother making a server call with no impressions.
if len(validImps) == 0 {
return nil, errs
}

imp2placement[placementHash] = append(imp2placement[placementHash], i)
request.Imp = validImps

request.Ext, err = json.Marshal(reqExt)
if err != nil {
errs = append(errs, err)
return nil, errs
}

totalReqs := len(imp2placement)
if 0 == totalReqs {
return nil, errors
reqJSON, err := json.Marshal(request)
if err != nil {
errs = append(errs, err)
return nil, errs
}

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

reqs := make([]*adapters.RequestData, 0, totalReqs)

imps := request.Imp
request.Imp = make([]openrtb.Imp, 0, len(imps))

for placementHash, impIds := range imp2placement {
request.Imp = request.Imp[:0]

for i := 0; i < len(impIds); i++ {
request.Imp = append(request.Imp, imps[impIds[i]])
}
if request.Device != nil {
addHeaderIfNonEmpty(headers, "User-Agent", request.Device.UA)
addHeaderIfNonEmpty(headers, "X-Forwarded-For", request.Device.IP)
addHeaderIfNonEmpty(headers, "Accept-Language", request.Device.Language)
addHeaderIfNonEmpty(headers, "DNT", strconv.Itoa(int(request.Device.DNT)))
}
return &adapters.RequestData{
Method: "POST",
Uri: a.endpoint + fmt.Sprintf("?s=%s", placementHash),
Body: reqJSON,
Headers: headers,
}, errs
}

body, err := json.Marshal(request)
if err != nil {
errors = append(errors, fmt.Errorf("error while encoding bidRequest, err: %s", err))
return nil, errors
func preprocess(imp *openrtb.Imp, reqExt *somoaudienceReqExt) (string, error) {
var bidderExt adapters.ExtImpBidder
if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil {
return "", &errortypes.BadInput{
Message: "ignoring imp id=empty-extbid-test, extImpBidder is empty",
}

reqs = append(reqs, &adapters.RequestData{
Method: "POST",
Uri: a.endpoint + fmt.Sprintf("?s=%s", placementHash),
Body: body,
Headers: headers,
})
}

if 0 == len(reqs) {
return nil, errors
var somoExt openrtb_ext.ExtImpSomoaudience
if err := json.Unmarshal(bidderExt.Bidder, &somoExt); err != nil {
return "", &errortypes.BadInput{
Message: "ignoring imp id=empty-extbid-test, error while decoding impExt, err: " + err.Error(),
}
}

return reqs, errors
imp.BidFloor = somoExt.BidFloor
imp.Ext = nil

return somoExt.PlacementHash, nil
}

func (a *SomoaudienceAdapter) MakeBids(bidReq *openrtb.BidRequest, unused *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
Expand Down Expand Up @@ -118,10 +193,10 @@ func (a *SomoaudienceAdapter) MakeBids(bidReq *openrtb.BidRequest, unused *adapt
return bidResponse, nil
}

func getMediaTypeForImp(impId string, imps []openrtb.Imp) openrtb_ext.BidType {
func getMediaTypeForImp(impID string, imps []openrtb.Imp) openrtb_ext.BidType {
mediaType := openrtb_ext.BidTypeBanner
for _, imp := range imps {
if imp.ID == impId {
if imp.ID == impID {
if imp.Banner != nil {
mediaType = openrtb_ext.BidTypeBanner
} else if imp.Video != nil {
Expand All @@ -138,37 +213,11 @@ func getMediaTypeForImp(impId string, imps []openrtb.Imp) openrtb_ext.BidType {
return mediaType
}

func validateImpression(imp *openrtb.Imp) (string, error) {

if imp.Audio != nil {
return "", &errortypes.BadInput{
Message: fmt.Sprintf("ignoring imp id=%s, Somoaudience doesn't support Audio", imp.ID),
}
}

if 0 == len(imp.Ext) {
return "", &errortypes.BadInput{
Message: fmt.Sprintf("ignoring imp id=%s, extImpBidder is empty", imp.ID),
}
}

var bidderExt adapters.ExtImpBidder

if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil {
return "", &errortypes.BadInput{
Message: fmt.Sprintf("ignoring imp id=%s, error while decoding extImpBidder, err: %s", imp.ID, err),
}
//Adding header fields to request header
func addHeaderIfNonEmpty(headers http.Header, headerName string, headerValue string) {
if len(headerValue) > 0 {
headers.Add(headerName, headerValue)
}

impExt := openrtb_ext.ExtImpSomoaudience{}
err := json.Unmarshal(bidderExt.Bidder, &impExt)
if err != nil {
return "", &errortypes.BadInput{
Message: fmt.Sprintf("ignoring imp id=%s, error while decoding impExt, err: %s", imp.ID, err),
}
}

return impExt.PlacementHash, nil
}

func NewSomoaudienceBidder(endpoint string) *SomoaudienceAdapter {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
},
"ext": {
"bidder": {
"placement_hash": "22a58cfb0c9b656bff713d1236e930e8"
"placement_hash": "22a58cfb0c9b656bff713d1236e930e8",
"bid_floor": 1.05
}
}
}
Expand All @@ -36,6 +37,9 @@
"expectedRequest": {
"uri": "http://publisher-east.mobileadtrading.com/rtb/bid?s=22a58cfb0c9b656bff713d1236e930e8",
"body": {
"ext":{
"prebid": "hb_pbs_1.0.0"
},
"id": "test-request-id",
"imp": [
{
Expand All @@ -58,11 +62,7 @@
"w": 1024,
"h": 576
},
"ext": {
"bidder": {
"placement_hash": "22a58cfb0c9b656bff713d1236e930e8"
}
}
"bidfloor": 1.05
}
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,6 @@
"native": {
"request": "{\"ver\":\"1.1\",\"context\":1,\"contextsubtype\":11,\"plcmttype\":4,\"plcmtcnt\":1,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":500}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":1,\"hmin\":1}},{\"id\":3,\"required\":0,\"data\":{\"type\":1,\"len\":200}},{\"id\":4,\"required\":0,\"data\":{\"type\":2,\"len\":15000}},{\"id\":5,\"required\":0,\"data\":{\"type\":6,\"len\":40}},{\"id\":6,\"required\":0,\"data\":{\"type\":500}}]}",
"ver": "1.1"
},
"ext": {
"bidder": {
"placement_hash": "22a58cfb0c9b656bff713d1236e930e8"
}
}
}
],
Expand All @@ -55,6 +50,9 @@
"device": {
"ip": "152.193.6.74"
},
"ext":{
"prebid": "hb_pbs_1.0.0"
},
"user": {
"id": "db089de9-a62e-4861-a881-0ff15e052516",
"buyeruid": "8299345306627569435"
Expand Down
9 changes: 3 additions & 6 deletions adapters/somoaudience/somoaudiencetest/exemplary/no-bid.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@
"uri": "http://publisher-east.mobileadtrading.com/rtb/bid?s=22a58cfb0c9b656bff713d1236e930e8",
"body": {
"id": "test-request-id",
"ext":{
"prebid": "hb_pbs_1.0.0"
},
"imp": [
{
"id": "test-imp-id",
Expand All @@ -78,12 +81,6 @@
"h": 600
}
]
},

"ext": {
"bidder": {
"placement_hash": "22a58cfb0c9b656bff713d1236e930e8"
}
}
}
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
"uri": "http://publisher-east.mobileadtrading.com/rtb/bid?s=22a58cfb0c9b656bff713d1236e930e8",
"body": {
"id": "test-request-id",
"ext":{
"prebid": "hb_pbs_1.0.0"
},
"imp": [
{
"id": "test-imp-id",
Expand All @@ -45,11 +48,6 @@
"h": 600
}
]
},
"ext": {
"bidder": {
"placement_hash": "22a58cfb0c9b656bff713d1236e930e8"
}
}
}
]
Expand All @@ -65,6 +63,6 @@
],

"expectedBidResponses": [

]
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
"uri": "http://publisher-east.mobileadtrading.com/rtb/bid?s=22a58cfb0c9b656bff713d1236e930e8",
"body": {
"id": "test-request-id",
"ext":{
"prebid": "hb_pbs_1.0.0"
},
"imp": [
{
"id": "test-imp-id",
Expand All @@ -45,11 +48,6 @@
"h": 600
}
]
},
"ext": {
"bidder": {
"placement_hash": "22a58cfb0c9b656bff713d1236e930e8"
}
}
}
]
Expand Down
Loading

0 comments on commit 939f355

Please sign in to comment.