Skip to content

Commit

Permalink
SilverMob adapter (prebid#1561)
Browse files Browse the repository at this point in the history
* SilverMob adapter

* Fixes andchanges according to notes in PR

* Remaining fixes:
multibids, expectedMakeRequestsErrors

* removed log

* removed log

* Multi-bid test

* Removed unnesesary block

Co-authored-by: Anton Nikityuk <[email protected]>
  • Loading branch information
2 people authored and shunj-nb committed Nov 8, 2022
1 parent eab694f commit 7637d70
Show file tree
Hide file tree
Showing 24 changed files with 1,732 additions and 0 deletions.
56 changes: 56 additions & 0 deletions adapters/silvermob/params_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package silvermob

import (
"encoding/json"
"testing"

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

// TestValidParams makes sure that the silvermob 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.BidderSilverMob, json.RawMessage(validParam)); err != nil {
t.Errorf("Schema rejected silvermob params: %s", validParam)
}
}
}

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

var validParams = []string{
`{"zoneid": "16", "host": "us"}`,
`{"zoneid": "16", "host": "eu"}`,
}

var invalidParams = []string{
``,
`null`,
`true`,
`5`,
`4.2`,
`[]`,
`{}`,
`{"ZoneID": "asd", "Host": "123"}`,
`{}`,
`{"ZoneID": "asd"}`,
`{"Host": "111"}`,
`{"zoneid": 16, "host": 111}`,
}
188 changes: 188 additions & 0 deletions adapters/silvermob/silvermob.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
package silvermob

import (
"encoding/json"
"fmt"
"github.com/golang/glog"
"net/http"
"text/template"

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

type SilverMobAdapter struct {
endpoint template.Template
}

func NewSilverMobBidder(endpointTemplate string) *SilverMobAdapter {
template, err := template.New("endpointTemplate").Parse(endpointTemplate)
if err != nil {
glog.Fatal("Unable to parse endpoint url template")
return nil
}
return &SilverMobAdapter{endpoint: *template}
}

func GetHeaders(request *openrtb.BidRequest) *http.Header {
headers := http.Header{}
headers.Add("Content-Type", "application/json;charset=utf-8")
headers.Add("Accept", "application/json")
headers.Add("X-Openrtb-Version", "2.5")

if request.Device != nil {
if len(request.Device.UA) > 0 {
headers.Add("User-Agent", request.Device.UA)
}

if len(request.Device.IPv6) > 0 {
headers.Add("X-Forwarded-For", request.Device.IPv6)
}

if len(request.Device.IP) > 0 {
headers.Add("X-Forwarded-For", request.Device.IP)
}
}

return &headers
}

func (a *SilverMobAdapter) MakeRequests(
openRTBRequest *openrtb.BidRequest,
reqInfo *adapters.ExtraRequestInfo,
) (
[]*adapters.RequestData,
[]error,
) {
requestCopy := *openRTBRequest
impCount := len(openRTBRequest.Imp)
requestData := make([]*adapters.RequestData, 0, impCount)
errs := []error{}

var err error

for _, imp := range openRTBRequest.Imp {
var silvermobExt *openrtb_ext.ExtSilverMob

silvermobExt, err = a.getImpressionExt(&imp)

if err != nil {
errs = append(errs, err)
continue
}

url, err := a.buildEndpointURL(silvermobExt)
if err != nil {
errs = append(errs, err)
continue
}

requestCopy.Imp = []openrtb.Imp{imp}
reqJSON, err := json.Marshal(requestCopy)
if err != nil {
errs = append(errs, err)
continue
}

reqData := &adapters.RequestData{
Method: http.MethodPost,
Body: reqJSON,
Uri: url,
Headers: *GetHeaders(&requestCopy),
}

requestData = append(requestData, reqData)
}

return requestData, errs
}

func (a *SilverMobAdapter) getImpressionExt(imp *openrtb.Imp) (*openrtb_ext.ExtSilverMob, error) {
var bidderExt adapters.ExtImpBidder
if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil {
return nil, &errortypes.BadInput{
Message: fmt.Sprintf("error unmarshaling imp.ext: %s", err.Error()),
}
}
var silvermobExt openrtb_ext.ExtSilverMob
if err := json.Unmarshal(bidderExt.Bidder, &silvermobExt); err != nil {
return nil, &errortypes.BadInput{
Message: fmt.Sprintf("error unmarshaling imp.ext.bidder: %s", err.Error()),
}
}
return &silvermobExt, nil
}

func (a *SilverMobAdapter) buildEndpointURL(params *openrtb_ext.ExtSilverMob) (string, error) {
endpointParams := macros.EndpointTemplateParams{ZoneID: params.ZoneID, Host: params.Host}
return macros.ResolveMacros(a.endpoint, endpointParams)
}

func (a *SilverMobAdapter) MakeBids(
openRTBRequest *openrtb.BidRequest,
requestToBidder *adapters.RequestData,
bidderRawResponse *adapters.ResponseData,
) (
bidderResponse *adapters.BidderResponse,
errs []error,
) {

if bidderRawResponse.StatusCode == http.StatusNoContent {
return nil, nil
}

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

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

responseBody := bidderRawResponse.Body
var bidResp openrtb.BidResponse
if err := json.Unmarshal(responseBody, &bidResp); err != nil {
return nil, []error{&errortypes.BadServerResponse{
Message: fmt.Sprintf("Error unmarshaling server Response: %s", err),
}}
}

if len(bidResp.SeatBid) == 0 {
return nil, []error{&errortypes.BadServerResponse{
Message: "Empty SeatBid array",
}}
}

bidResponse := adapters.NewBidderResponseWithBidsCapacity(1)

for _, sb := range bidResp.SeatBid {
for _, bid := range sb.Bid {
bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
Bid: &bid,
BidType: getMediaTypeForImp(bid.ImpID, openRTBRequest.Imp),
})
}
}

return bidResponse, nil
}

func getMediaTypeForImp(impId string, imps []openrtb.Imp) openrtb_ext.BidType {
mediaType := openrtb_ext.BidTypeBanner
for _, imp := range imps {
if imp.ID == impId {
if imp.Video != nil {
mediaType = openrtb_ext.BidTypeVideo
} else if imp.Native != nil {
mediaType = openrtb_ext.BidTypeNative
}
return mediaType
}
}
return mediaType
}
11 changes: 11 additions & 0 deletions adapters/silvermob/silvermob_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package silvermob

import (
"testing"

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

func TestJsonSamples(t *testing.T) {
adapterstest.RunJSONBidderTest(t, "silvermobtest", NewSilverMobBidder("http://{{.Host}}.example.com/api/dsp/bid/{{.ZoneID}}"))
}
Loading

0 comments on commit 7637d70

Please sign in to comment.