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

OpenWeb Adapter Refactor #1

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
202 changes: 73 additions & 129 deletions adapters/openweb/openweb.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ package openweb

import (
"encoding/json"
"errors"
"fmt"
"net/http"
"strconv"
"strings"

"github.com/prebid/openrtb/v20/openrtb2"

"github.com/prebid/prebid-server/v2/adapters"
"github.com/prebid/prebid-server/v2/config"
"github.com/prebid/prebid-server/v2/errortypes"
Expand All @@ -16,175 +20,115 @@ type adapter struct {
endpoint string
}

type openwebImpExt struct {
OpenWeb openrtb_ext.ExtImpOpenWeb `json:"openweb"`
}

func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
totalImps := len(request.Imp)
errors := make([]error, 0, totalImps)
sourceIdToImpIds := make(map[int][]int)
var sourceIds []int

for i := 0; i < totalImps; i++ {

sourceId, err := validateImpression(&request.Imp[i])

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

if _, ok := sourceIdToImpIds[sourceId]; !ok {
sourceIdToImpIds[sourceId] = make([]int, 0, totalImps-i)
sourceIds = append(sourceIds, sourceId)
}

sourceIdToImpIds[sourceId] = append(sourceIdToImpIds[sourceId], i)

func (a *adapter) MakeRequests(request *openrtb2.BidRequest, _ *adapters.ExtraRequestInfo) (requestsToBidder []*adapters.RequestData, errs []error) {
org, err := checkExtAndExtractOrg(request)
if err != nil {
errs = append(errs, fmt.Errorf("checkExtAndExtractOrg: %w", err))
return nil, errs
}

totalReqs := len(sourceIdToImpIds)
if totalReqs == 0 {
return nil, errors
requestJSON, err := json.Marshal(request)
if err != nil {
errs = append(errs, fmt.Errorf("marshal bidRequest: %w", err))
return nil, errs
}

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

reqs := make([]*adapters.RequestData, 0, totalReqs)
return append(requestsToBidder, &adapters.RequestData{
Method: http.MethodPost,
Uri: a.endpoint + "?publisher_id=" + org,
Body: requestJSON,
Headers: headers,
ImpIDs: openrtb_ext.GetImpIDs(request.Imp),
}), nil
}

imps := request.Imp
reqCopy := *request
reqCopy.Imp = make([]openrtb2.Imp, totalImps)
for _, sourceId := range sourceIds {
impIds := sourceIdToImpIds[sourceId]
reqCopy.Imp = reqCopy.Imp[:0]
// checkExtAndExtractOrg checks the presence of required parameters and extracts the Org ID string.
func checkExtAndExtractOrg(request *openrtb2.BidRequest) (string, error) {
var err error
for _, imp := range request.Imp {
var bidderExt adapters.ExtImpBidder
if err = json.Unmarshal(imp.Ext, &bidderExt); err != nil {
return "", fmt.Errorf("unmarshal bidderExt: %w", err)
}

for i := 0; i < len(impIds); i++ {
reqCopy.Imp = append(reqCopy.Imp, imps[impIds[i]])
var impExt openrtb_ext.ExtImpOpenWeb
if err = json.Unmarshal(bidderExt.Bidder, &impExt); err != nil {
return "", fmt.Errorf("unmarshal ExtImpOpenWeb: %w", err)
}

body, err := json.Marshal(reqCopy)
if err != nil {
errors = append(errors, fmt.Errorf("error while encoding bidRequest, err: %s", err))
return nil, errors
if impExt.PlacementID == "" {
return "", errors.New("no placement id supplied")
}

reqs = append(reqs, &adapters.RequestData{
Method: "POST",
Uri: a.endpoint + fmt.Sprintf("?aid=%d", sourceId),
Body: body,
Headers: headers,
ImpIDs: openrtb_ext.GetImpIDs(reqCopy.Imp),
})
}
if impExt.Org != "" {
return strings.TrimSpace(impExt.Org), nil
}

return reqs, errors
if impExt.Aid != 0 {
return strconv.Itoa(impExt.Aid), nil
}
}

return "", errors.New("no org or aid supplied")
}

func (a *adapter) MakeBids(bidReq *openrtb2.BidRequest, unused *adapters.RequestData, httpRes *adapters.ResponseData) (*adapters.BidderResponse, []error) {

if httpRes.StatusCode == http.StatusNoContent {
func (a *adapter) MakeBids(request *openrtb2.BidRequest, _ *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) {
if adapters.IsResponseStatusCodeNoContent(responseData) {
return nil, nil
}

if httpRes.StatusCode != http.StatusOK {
return nil, []error{&errortypes.BadServerResponse{
Message: fmt.Sprintf("Remote server error: %s", httpRes.Body),
}}
}
var bidResp openrtb2.BidResponse
if err := json.Unmarshal(httpRes.Body, &bidResp); err != nil {
return nil, []error{&errortypes.BadServerResponse{
Message: fmt.Sprintf("error while decoding response, err: %s", err),
}}
if err := adapters.CheckResponseStatusCodeForErrors(responseData); err != nil {
return nil, []error{err}
}

bidResponse := adapters.NewBidderResponse()
var errors []error
var response openrtb2.BidResponse
if err := json.Unmarshal(responseData.Body, &response); err != nil {
return nil, []error{err}
}

for _, sb := range bidResp.SeatBid {
for i := 0; i < len(sb.Bid); i++ {
bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp))
if response.Cur != "" {
bidResponse.Currency = response.Cur
}

bid := sb.Bid[i]
var errs []error

mediaType, impOK := getBidType(bidReq.Imp, bid.ImpID)
if !impOK {
errors = append(errors, &errortypes.BadServerResponse{
Message: fmt.Sprintf("ignoring bid id=%s, request doesn't contain any impression with id=%s", bid.ID, bid.ImpID),
})
for _, seatBid := range response.SeatBid {
for i, bid := range seatBid.Bid {
bidType, err := getMediaTypeForBid(bid)
if err != nil {
errs = append(errs, err)
continue
}

bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
Bid: &bid,
BidType: mediaType,
Bid: &seatBid.Bid[i],
BidType: bidType,
})
}
}

return bidResponse, errors
return bidResponse, errs
}

func getBidType(imps []openrtb2.Imp, impId string) (mediaType openrtb_ext.BidType, ok bool) {
mediaType = openrtb_ext.BidTypeBanner
for _, imp := range imps {
if imp.ID == impId {
ok = true

if imp.Video != nil {
mediaType = openrtb_ext.BidTypeVideo
}

break
}
}

return
}

func validateImpression(imp *openrtb2.Imp) (int, error) {
var bidderExt adapters.ExtImpBidder

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

impExt := openrtb_ext.ExtImpOpenWeb{}
err := json.Unmarshal(bidderExt.Bidder, &impExt)
if err != nil {
return 0, &errortypes.BadInput{
Message: fmt.Sprintf("ignoring imp id=%s, error while decoding impExt, err: %s", imp.ID, err),
func getMediaTypeForBid(bid openrtb2.Bid) (openrtb_ext.BidType, error) {
switch bid.MType {
case openrtb2.MarkupBanner:
return openrtb_ext.BidTypeBanner, nil
case openrtb2.MarkupVideo:
return openrtb_ext.BidTypeVideo, nil
default:
return "", &errortypes.BadServerResponse{
Message: fmt.Sprintf("unsupported MType %d", bid.MType),
}
}

var impExtBuffer []byte

impExtBuffer, err = json.Marshal(&openwebImpExt{
OpenWeb: impExt,
})
if err != nil {
return 0, &errortypes.BadInput{
Message: fmt.Sprintf("ignoring imp id=%s, error while encoding impExt, err: %s", imp.ID, err),
}
}

if impExt.BidFloor > 0 {
imp.BidFloor = impExt.BidFloor
}

imp.Ext = impExtBuffer

return impExt.SourceID, nil
}

// Builder builds a new instance of the OpenWeb adapter for the given bidder with the given config.
func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) {
func Builder(_ openrtb_ext.BidderName, config config.Adapter, _ config.Server) (adapters.Bidder, error) {
bidder := &adapter{
endpoint: config.Endpoint,
}
Expand Down
2 changes: 1 addition & 1 deletion adapters/openweb/openweb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (

func TestJsonSamples(t *testing.T) {
bidder, buildErr := Builder(openrtb_ext.BidderOpenWeb, config.Adapter{
Endpoint: "http://ghb.spotim.market/pbs/ortb"}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"})
Endpoint: "https://pbs.openwebmp.com/pbs"}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"})

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