Skip to content
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ vendor
prebid-server
build
debug
__debug_bin

# config files
pbs.*
Expand Down
95 changes: 47 additions & 48 deletions adapters/beachfront/beachfront.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"errors"
"fmt"
"net/http"
"reflect"
"strconv"
"strings"

Expand All @@ -24,12 +23,13 @@ const defaultVideoEndpoint = "https://reachms.bfmio.com/bid.json?exchange_id"
const nurlVideoEndpointSuffix = "&prebidserver"

const beachfrontAdapterName = "BF_PREBID_S2S"
const beachfrontAdapterVersion = "0.9.1"
const beachfrontAdapterVersion = "0.9.2"

const minBidFloor = 0.01

const DefaultVideoWidth = 300
const DefaultVideoHeight = 250
const defaultVideoWidth = 300
const defaultVideoHeight = 250
const fakeIP = "255.255.255.255"

type BeachfrontAdapter struct {
bannerEndpoint string
Expand Down Expand Up @@ -249,16 +249,12 @@ func getAppId(ext openrtb_ext.ExtImpBeachfront, media openrtb_ext.BidType) (stri
var appid string
var error error

if fmt.Sprintf("%s", reflect.TypeOf(ext.AppId)) == "string" &&
ext.AppId != "" {

if ext.AppId != "" {
appid = ext.AppId
} else if fmt.Sprintf("%s", reflect.TypeOf(ext.AppIds)) == "openrtb_ext.ExtImpBeachfrontAppIds" {
if media == openrtb_ext.BidTypeVideo && ext.AppIds.Video != "" {
appid = ext.AppIds.Video
} else if media == openrtb_ext.BidTypeBanner && ext.AppIds.Banner != "" {
appid = ext.AppIds.Banner
}
} else if media == openrtb_ext.BidTypeVideo && ext.AppIds.Video != "" {
appid = ext.AppIds.Video
} else if media == openrtb_ext.BidTypeBanner && ext.AppIds.Banner != "" {
appid = ext.AppIds.Banner
} else {
error = errors.New("unable to determine the appId(s) from the supplied extension")
}
Expand Down Expand Up @@ -317,7 +313,7 @@ func getBannerRequest(request *openrtb.BidRequest) (beachfrontBannerRequest, []e
}

if request.Device != nil {
bfr.IP = getIP(request.Device.IP)
bfr.IP = request.Device.IP
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just checking, you don't need to set the ip to fakeIP if it's a banner request?

Copy link
Contributor Author

@muncha muncha Feb 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is correct. It's just the video requests that need it.

bfr.DeviceModel = request.Device.Model
bfr.DeviceOs = request.Device.OS
if request.Device.DNT != nil {
Expand Down Expand Up @@ -399,6 +395,7 @@ func getVideoRequests(request *openrtb.BidRequest) ([]beachfrontVideoRequest, []
}

appid, err := getAppId(beachfrontExt, openrtb_ext.BidTypeVideo)
bfReqs[i].AppId = appid

if err != nil {
// Failed to get an appid, so this request is junk.
Expand All @@ -407,20 +404,25 @@ func getVideoRequests(request *openrtb.BidRequest) ([]beachfrontVideoRequest, []
continue
}

bfReqs[i].AppId = appid
bfReqs[i].Request = *request
var secure int8

if bfReqs[i].Request.Device == nil {
bfReqs[i].Request.Device = &openrtb.Device{}
}

if beachfrontExt.VideoResponseType != "" {
bfReqs[i].VideoResponseType = beachfrontExt.VideoResponseType
if beachfrontExt.VideoResponseType == "nurl" {
bfReqs[i].VideoResponseType = "nurl"
} else {
bfReqs[i].VideoResponseType = "adm"
}

bfReqs[i].Request = *request
var secure int8
if bfReqs[i].Request.Device.IP == "" {
bfReqs[i].Request.Device.IP = fakeIP
}
}

if bfReqs[i].Request.Site != nil && bfReqs[i].Request.Site.Domain == "" && bfReqs[i].Request.Site.Page != "" {
bfReqs[i].Request.Site.Domain = getDomain(bfReqs[i].Request.Site.Page)

secure = isSecure(bfReqs[i].Request.Site.Page)
}

Expand All @@ -433,7 +435,6 @@ func getVideoRequests(request *openrtb.BidRequest) ([]beachfrontVideoRequest, []
fmt.Sprintf("%s.%s", chunks[len(chunks)-(len(chunks)-1)], chunks[0])
}
}

}

if bfReqs[i].Request.Device != nil && bfReqs[i].Request.Device.DeviceType == 0 {
Expand All @@ -454,8 +455,8 @@ func getVideoRequests(request *openrtb.BidRequest) ([]beachfrontVideoRequest, []
}

if imp.Video.H == 0 && imp.Video.W == 0 {
imp.Video.W = DefaultVideoWidth
imp.Video.H = DefaultVideoHeight
imp.Video.W = defaultVideoWidth
imp.Video.H = defaultVideoHeight
}

if len(bfReqs[i].Request.Cur) == 0 {
Expand All @@ -467,9 +468,6 @@ func getVideoRequests(request *openrtb.BidRequest) ([]beachfrontVideoRequest, []
bfReqs[i].Request.Imp = make([]openrtb.Imp, 1, 1)
bfReqs[i].Request.Imp[0] = imp

if bfReqs[i].Request.Device != nil && bfReqs[i].Request.Device.IP != "" {
bfReqs[i].Request.Device.IP = getIP(bfReqs[i].Request.Device.IP)
}
}

// Strip out any failed requests
Expand All @@ -484,15 +482,24 @@ func getVideoRequests(request *openrtb.BidRequest) ([]beachfrontVideoRequest, []

func (a *BeachfrontAdapter) MakeBids(internalRequest *openrtb.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
var bids []openrtb.Bid
var errs []error

// The case of response status == 200 and response body length == 2 below covers the case of the banner endpoint returning
// an empty JSON array ('[]'), which is functionally no content.
if response.StatusCode == http.StatusNoContent || (response.StatusCode == http.StatusOK && len(response.Body) <= 2) {
return nil, nil
return nil, []error{&errortypes.BadInput{
Message: fmt.Sprintf("no content or truncated content received from server. status code %d from %s. Run with request.debug = 1 for more info", response.StatusCode, externalRequest.Uri),
}}
}

if response.StatusCode >= http.StatusInternalServerError {
return nil, []error{&errortypes.BadInput{
Message: fmt.Sprintf("server error status code %d from %s. Run with request.debug = 1 for more info", response.StatusCode, externalRequest.Uri),
}}
}

if response.StatusCode == http.StatusBadRequest {
if response.StatusCode >= http.StatusBadRequest {
return nil, []error{&errortypes.BadInput{
Message: fmt.Sprintf("bad request status code %d from %s. Run with request.debug = 1 for more info", response.StatusCode, externalRequest.Uri),
Message: fmt.Sprintf("request error status code %d from %s. Run with request.debug = 1 for more info", response.StatusCode, externalRequest.Uri),
}}
}

Expand All @@ -501,6 +508,7 @@ func (a *BeachfrontAdapter) MakeBids(internalRequest *openrtb.BidRequest, extern
}

var xtrnal openrtb.BidRequest
var errs = make([]error, 0)

// For video, which uses RTB for the external request, this will unmarshal as expected. For banner, it will
// only get the User struct and everything else will be nil
Expand Down Expand Up @@ -550,18 +558,15 @@ func (a *BeachfrontAdapter) getBidType(externalRequest *adapters.RequestData) op

func postprocess(response *adapters.ResponseData, xtrnal openrtb.BidRequest, uri string, id string) ([]openrtb.Bid, []error) {
var beachfrontResp []beachfrontResponseSlot
var errs = make([]error, 0)

var openrtbResp openrtb.BidResponse

// try it as a video
if err := json.Unmarshal(response.Body, &openrtbResp); err != nil {
errs = append(errs, err)
if err := json.Unmarshal(response.Body, &openrtbResp); err != nil || len(openrtbResp.SeatBid) == 0 {

// try it as a banner
if err := json.Unmarshal(response.Body, &beachfrontResp); err != nil {
errs = append(errs, err)
return nil, errs
return nil, []error{&errortypes.BadServerResponse{
Message: fmt.Sprint("server response failed to unmarshal as valid rtb. Run with request.debug = 1 for more info"),
}}
} else {
return postprocessBanner(beachfrontResp, id)
}
Expand Down Expand Up @@ -669,18 +674,12 @@ func isSecure(page string) int8 {

}

func getIP(ip string) string {
// This will only effect testing. The backend will return "" for localhost IPs,
// and seems not to know what IPv6 is, so just setting it to one that is not likely to
// be used.
if ip == "" || ip == "::1" || ip == "127.0.0.1" {
return "192.168.255.255"
func removeVideoElement(slice []beachfrontVideoRequest, s int) []beachfrontVideoRequest {
if len(slice) >= s+1 {
return append(slice[:s], slice[s+1:]...)
}
return ip
}

func removeVideoElement(slice []beachfrontVideoRequest, s int) []beachfrontVideoRequest {
return append(slice[:s], slice[s+1:]...)
return []beachfrontVideoRequest{}
}

// Builder builds a new instance of the Beachfront adapter for the given bidder with the given config.
Expand Down
123 changes: 123 additions & 0 deletions adapters/beachfront/beachfronttest/exemplary/adm-video.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
{
"mockBidRequest": {
"id": "adm-video",
"imp": [
{
"id": "video1",
"ext": {
"bidder": {
"bidfloor": 3.01,
"appId": "videoAppId1"
}
},
"video": {
"mimes": [
"video/mp4"
],
"context": "instream",
"w": 300,
"h": 250
}
}
],
"site": {
"page": "https://some.domain.us/some/page.html"
},
"device":{
"ip":"192.168.168.168"
}
},

"httpCalls": [
{
"expectedRequest": {
"uri": "https://qa.beachrtb.com/bid.json?exchange_id=videoAppId1",
"body": {
"id": "adm-video",
"imp": [
{
"video": {
"w": 300,
"h": 250,
"mimes": [
"video/mp4"
]
},
"bidfloor": 3.01,
"id": "video1",
"secure": 1
}
],
"site": {
"page": "https://some.domain.us/some/page.html",
"domain": "some.domain.us"
},
"cur": [
"USD"
],
"device":{
"devicetype": 2,
"ip":"192.168.168.168"
}
}
},
"mockResponse": {
"status": 200,
"body": {
"id": "adm-video",
"seatBid": [
{
"bid": [
{
"id": "5fd7c8a6ff2f1f0d42ee6427",
"impid": "video1",
"price": 20,
"adm": "<VAST version=\"2.0\"><Ad><Wrapper>http://example.com/vast.xml</Wrapper></Ad></VAST>",
"adid": "1088",
"adomain": [
"beachfront.io"
],
"cid": "277",
"crid": "532",
"w": 300,
"h": 250,
"ext": {
"duration": 30
}
}
],
"seat": "bfio-s-1"
}
]
}
}
}
],

"expectedBidResponses": [
{
"bids": [
{
"bid": {
"id": "video1AdmVideo",
"impid": "video1",
"price": 20,
"adm": "<VAST version=\"2.0\"><Ad><Wrapper>http://example.com/vast.xml</Wrapper></Ad></VAST>",
"adid": "1088",
"adomain": [
"beachfront.io"
],
"cid": "277",
"crid": "532",
"w": 300,
"h": 250,
"ext": {
"duration": 30
}
},
"type": "video"
}
]
}
]
}
2 changes: 1 addition & 1 deletion adapters/beachfront/beachfronttest/exemplary/banner.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
"dnt": 0,
"ua": "",
"adapterName": "BF_PREBID_S2S",
"adapterVersion": "0.9.1",
"adapterVersion": "0.9.2",
"user": {}
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@
],
"site": {
"page": "https://some.domain.us/some/page.html"
},
"device":{
"ip":"255.255.255.255"
}
},

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
],
"site": {
"page": "https://some.domain.us/some/page.html"
},
"device":{
"ip":"255.255.255.255"
}
},

Expand Down Expand Up @@ -64,11 +67,11 @@
"deviceModel": "",
"isMobile": 0,
"ua": "",
"ip": "",
"ip": "255.255.255.255",
"dnt": 0,
"user": {},
"adapterName": "BF_PREBID_S2S",
"adapterVersion": "0.9.1",
"adapterVersion": "0.9.2",
"requestId": "banner-and-video"
}
},
Expand Down Expand Up @@ -109,6 +112,10 @@
"domain": "some.domain.us",
"page": "https://some.domain.us/some/page.html"
},
"device": {
"devicetype": 2,
"ip": "255.255.255.255"
},
"cur": [
"USD"
]
Expand Down
Loading