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

Add LockerDome bid adapter #1026

Merged
merged 5 commits into from
Oct 1, 2019
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 137 additions & 0 deletions adapters/lockerdome/lockerdome.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package lockerdome

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"
)

const unexpectedStatusCodeMessage = "Unexpected status code: %d. Run with request.debug = 1 for more info"

// Implements Bidder interface.
type LockerDomeAdapter struct {
endpoint string
}

// MakeRequests makes the HTTP requests which should be made to fetch bids [from the bidder, in this case, LockerDome]
func (adapter *LockerDomeAdapter) MakeRequests(openRTBRequest *openrtb.BidRequest, extraReqInfo *adapters.ExtraRequestInfo) (requestsToBidder []*adapters.RequestData, errs []error) {

guscarreon marked this conversation as resolved.
Show resolved Hide resolved
numberOfImps := len(openRTBRequest.Imp)

if openRTBRequest.Imp == nil || numberOfImps == 0 { // lockerdometest/supplemental/empty_imps.json
err := &errortypes.BadInput{
Message: "No valid impressions in the bid request.",
}
errs = append(errs, err)
return nil, errs
}

for i := 0; i < numberOfImps; i++ {
// LockerDome currently only supports banner impressions, and requires data in the ext field.
if openRTBRequest.Imp[i].Banner == nil { // lockerdometest/supplemental/unsupported_imp_type.json
err := &errortypes.BadInput{
Message: "LockerDome does not currently support non-banner types.",
}
errs = append(errs, err)
return nil, errs
}
var bidderExt adapters.ExtImpBidder
err := json.Unmarshal(openRTBRequest.Imp[i].Ext, &bidderExt)
if err != nil { // lockerdometest/supplemental/no_ext.json
err = &errortypes.BadInput{
Message: "ext was not provided.",
}
errs = append(errs, err)
return nil, errs
}
var lockerdomeExt openrtb_ext.ExtImpLockerDome
err = json.Unmarshal(bidderExt.Bidder, &lockerdomeExt)
if err != nil { // lockerdometest/supplemental/no_adUnitId_param.json
err = &errortypes.BadInput{
Message: "ext.bidder.adUnitId was not provided.",
}
errs = append(errs, err)
return nil, errs
}
if lockerdomeExt.AdUnitId == "" { // lockerdometest/supplemental/empty_adUnitId_param.json
err := &errortypes.BadInput{
Message: "ext.bidder.adUnitId is empty.",
}
errs = append(errs, err)
return nil, errs
}
}
guscarreon marked this conversation as resolved.
Show resolved Hide resolved

openRTBRequestJSON, err := json.Marshal(openRTBRequest)
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")

requestToBidder := &adapters.RequestData{
Method: "POST",
Uri: adapter.endpoint,
Body: openRTBRequestJSON,
Headers: headers,
}

requestsToBidder = append(requestsToBidder, requestToBidder)

return requestsToBidder, nil

}

// MakeBids unpacks the server's response into Bids.
func (adapter *LockerDomeAdapter) 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(unexpectedStatusCodeMessage, bidderRawResponse.StatusCode),
}}
}

if bidderRawResponse.StatusCode != http.StatusOK {
return nil, []error{&errortypes.BadServerResponse{
Message: fmt.Sprintf(unexpectedStatusCodeMessage, bidderRawResponse.StatusCode),
}}
}

var openRTBBidderResponse openrtb.BidResponse
if err := json.Unmarshal(bidderRawResponse.Body, &openRTBBidderResponse); err != nil {
return nil, []error{
fmt.Errorf("Error unmarshaling LockerDome bid response - %s", err.Error()),
}
}

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

bidderResponse = adapters.NewBidderResponseWithBidsCapacity(len(openRTBBidderResponse.SeatBid[0].Bid))

for _, seatBid := range openRTBBidderResponse.SeatBid {
for i := range seatBid.Bid {
typedBid := adapters.TypedBid{Bid: &seatBid.Bid[i], BidType: openrtb_ext.BidTypeBanner}
bidderResponse.Bids = append(bidderResponse.Bids, &typedBid)
}
}
return bidderResponse, nil
}

func NewLockerDomeBidder(endpoint string) *LockerDomeAdapter {
return &LockerDomeAdapter{endpoint: endpoint}
}
10 changes: 10 additions & 0 deletions adapters/lockerdome/lockerdome_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package lockerdome

import (
"github.com/prebid/prebid-server/adapters/adapterstest"
"testing"
)

func TestJsonSamples(t *testing.T) {
adapterstest.RunJSONBidderTest(t, "lockerdometest", NewLockerDomeBidder("https://lockerdome.com/ladbid/prebidserver/openrtb2"))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
{
"mockBidRequest": {
"id": "test-request-id",
"imp": [
{
"id": "test-imp-id",
"banner": {
"format": [
{
"w": 300,
"h": 250
}
]
},
"ext": {
"bidder": {
"adUnitId": "LD9434769725128806"
}
}
},
{
"id": "test-imp-id-2",
"banner": {
"format": [
{
"w": 300,
"h": 250
}
]
},
"ext": {
"bidder": {
"adUnitId": "LD9360401292656742"
}
}
}
]
},

"httpCalls": [
{
"expectedRequest": {
"uri": "https://lockerdome.com/ladbid/prebidserver/openrtb2",
"body": {
"id": "test-request-id",
"imp": [
{
"id": "test-imp-id",
"banner": {
"format": [
{
"w": 300,
"h": 250
}
]
},
"ext": {
"bidder": {
"adUnitId": "LD9434769725128806"
}
}
},
{
"id": "test-imp-id-2",
"banner": {
"format": [
{
"w": 300,
"h": 250
}
]
},
"ext": {
"bidder": {
"adUnitId": "LD9360401292656742"
}
}
}
]
}
},
"mockResponse": {
"status": 200,
"body": {
"id": "test-request-id",
"seatbid": [
{
"seat": "lockerdome",
"bid": [
{
"id": "729c0d99-3b45-4225-9ad5-64aef2b46df3",
"impid": "test-imp-id",
"price": 0.23,
"adm": "<html>test ad markup #1</html>",
"crid": "LD12134555163033624",
"h": 250,
"w": 300
},
{
"id": "9euij6w8-sj89-6397-6er4-5we9t1a67wkj",
"impid": "test-imp-id-2",
"price": 0.5,
"adm": "<html>test ad markup #2</html>",
"crid": "LD12258417590730764",
"h": 250,
"w": 300
}
]
}
]
}
}
}
],

"expectedBidResponses": [
{
"bids": [
{
"bid": {
"id": "729c0d99-3b45-4225-9ad5-64aef2b46df3",
"impid": "test-imp-id",
"price": 0.23,
"adm": "<html>test ad markup #1</html>",
"crid": "LD12134555163033624",
"w": 300,
"h": 250
},
"type": "banner"
},
{
"bid": {
"id": "9euij6w8-sj89-6397-6er4-5we9t1a67wkj",
"impid": "test-imp-id-2",
"price": 0.5,
"adm": "<html>test ad markup #2</html>",
"crid": "LD12258417590730764",
"w": 300,
"h": 250
},
"type": "banner"
}
]
}
]
}
93 changes: 93 additions & 0 deletions adapters/lockerdome/lockerdometest/exemplary/simple-banner.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
{
margsliu marked this conversation as resolved.
Show resolved Hide resolved
"mockBidRequest": {
"id": "test-request-id",
"imp": [
{
"id": "test-imp-id",
"banner": {
"format": [
{
"w": 300,
"h": 250
}
]
},
"ext": {
"bidder": {
"adUnitId": "LD9434769725128806"
}
}
}
]
},

"httpCalls": [
{
"expectedRequest": {
"uri": "https://lockerdome.com/ladbid/prebidserver/openrtb2",
"body": {
"id": "test-request-id",
"imp": [
{
"id": "test-imp-id",
"banner": {
"format": [
{
"w": 300,
"h": 250
}
]
},
"ext": {
"bidder": {
"adUnitId": "LD9434769725128806"
}
}
}
]
}
},
"mockResponse": {
"status": 200,
"body": {
"id": "test-request-id",
"seatbid": [
{
"seat": "lockerdome",
"bid": [
{
"id": "729c0d99-3b45-4225-9ad5-64aef2b46df3",
"impid": "test-imp-id",
"price": 0.60,
"adm": "<html>test ad markup</html>",
"crid": "LD12134555163033624",
"h": 250,
"w": 300
}
]
}
]
}
}
}
],

"expectedBidResponses": [
{
"bids": [
{
"bid": {
"id": "729c0d99-3b45-4225-9ad5-64aef2b46df3",
"impid": "test-imp-id",
"price": 0.60,
"adm": "<html>test ad markup</html>",
"crid": "LD12134555163033624",
"w": 300,
"h": 250
},
"type": "banner"
}
]
}
]
}
3 changes: 3 additions & 0 deletions adapters/lockerdome/lockerdometest/params/race/banner.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"adUnitId": "LD9434769725128805"
}
Loading