-
Notifications
You must be signed in to change notification settings - Fork 749
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'prebid:master' into tradplus
- Loading branch information
Showing
98 changed files
with
4,213 additions
and
337 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package blue | ||
|
||
import ( | ||
"encoding/json" | ||
"testing" | ||
|
||
"github.com/prebid/prebid-server/v3/openrtb_ext" | ||
) | ||
|
||
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.BidderBlue, json.RawMessage(validParam)); err != nil { | ||
t.Errorf("Schema rejected blue params: %s", validParam) | ||
} | ||
} | ||
} | ||
|
||
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.BidderBlue, json.RawMessage(invalidParam)); err == nil { | ||
t.Errorf("Schema allowed unexpected params: %s", invalidParam) | ||
} | ||
} | ||
} | ||
|
||
var validParams = []string{ | ||
`{"publisherId":"1234"}`, | ||
`{"publisherId":"1234", "placementId":"12345"}`, | ||
`{"publisherId":"", "placementId":""}`, | ||
} | ||
|
||
var invalidParams = []string{ | ||
``, | ||
`null`, | ||
`true`, | ||
`5`, | ||
`4.2`, | ||
`[]`, | ||
`{}`, | ||
`{"placementId":"12345"}`, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,236 @@ | ||
package connatix | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
"strings" | ||
|
||
"github.com/buger/jsonparser" | ||
"github.com/prebid/openrtb/v20/openrtb2" | ||
"github.com/prebid/prebid-server/v3/adapters" | ||
"github.com/prebid/prebid-server/v3/config" | ||
"github.com/prebid/prebid-server/v3/errortypes" | ||
"github.com/prebid/prebid-server/v3/openrtb_ext" | ||
"github.com/prebid/prebid-server/v3/util/jsonutil" | ||
) | ||
|
||
const ( | ||
maxImpsPerReq = 1 | ||
) | ||
|
||
// Builder builds a new instance of the Connatix adapter for the given bidder with the given config. | ||
func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { | ||
bidder := &adapter{ | ||
endpoint: config.Endpoint, | ||
} | ||
return bidder, nil | ||
} | ||
|
||
func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { | ||
if request.Device == nil || (request.Device.IP == "" && request.Device.IPv6 == "") { | ||
return nil, []error{&errortypes.BadInput{ | ||
Message: "Device IP is required", | ||
}} | ||
} | ||
|
||
// connatix adapter expects imp.displaymanagerver to be populated in openrtb2 request | ||
// but some SDKs will put it in imp.ext.prebid instead | ||
displayManagerVer := buildDisplayManagerVer(request) | ||
|
||
var errs []error | ||
|
||
validImps := []openrtb2.Imp{} | ||
|
||
for i := range request.Imp { | ||
impExtIncoming, err := validateAndBuildImpExt(&request.Imp[i]) | ||
if err != nil { | ||
errs = append(errs, err) | ||
continue | ||
} | ||
|
||
if err := buildRequestImp(&request.Imp[i], impExtIncoming, displayManagerVer, reqInfo); err != nil { | ||
errs = append(errs, err) | ||
continue | ||
} | ||
|
||
validImps = append(validImps, request.Imp[i]) | ||
} | ||
|
||
// Divide imps to several requests | ||
requests, errors := splitRequests(validImps, request, a.endpoint) | ||
return requests, append(errs, errors...) | ||
} | ||
|
||
func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { | ||
if adapters.IsResponseStatusCodeNoContent(response) { | ||
return nil, nil | ||
} | ||
|
||
if err := adapters.CheckResponseStatusCodeForErrors(response); err != nil { | ||
return nil, []error{err} | ||
} | ||
|
||
var connatixResponse openrtb2.BidResponse | ||
if err := jsonutil.Unmarshal(response.Body, &connatixResponse); err != nil { | ||
return nil, []error{err} | ||
} | ||
|
||
var errs []error | ||
bidderResponse := adapters.NewBidderResponseWithBidsCapacity(1) | ||
for _, sb := range connatixResponse.SeatBid { | ||
for i := range sb.Bid { | ||
bid := sb.Bid[i] | ||
var bidExt bidExt | ||
var bidType openrtb_ext.BidType | ||
|
||
if err := jsonutil.Unmarshal(bid.Ext, &bidExt); err != nil { | ||
bidType = openrtb_ext.BidTypeBanner | ||
} else { | ||
bidType = getBidType(bidExt) | ||
} | ||
|
||
bidderResponse.Bids = append(bidderResponse.Bids, &adapters.TypedBid{ | ||
Bid: &bid, | ||
BidType: bidType, | ||
}) | ||
} | ||
} | ||
|
||
bidderResponse.Currency = "USD" | ||
|
||
return bidderResponse, errs | ||
} | ||
|
||
func validateAndBuildImpExt(imp *openrtb2.Imp) (impExtIncoming, error) { | ||
var ext impExtIncoming | ||
if err := jsonutil.Unmarshal(imp.Ext, &ext); err != nil { | ||
return impExtIncoming{}, err | ||
} | ||
|
||
return ext, nil | ||
} | ||
|
||
func splitRequests(imps []openrtb2.Imp, request *openrtb2.BidRequest, uri string) ([]*adapters.RequestData, []error) { | ||
var errs []error | ||
// Initial capacity for future array of requests, memory optimization. | ||
// Let's say there are 35 impressions and limit impressions per request equals to 10. | ||
// In this case we need to create 4 requests with 10, 10, 10 and 5 impressions. | ||
// With this formula initial capacity=(35+10-1)/10 = 4 | ||
initialCapacity := (len(imps) + maxImpsPerReq - 1) / maxImpsPerReq | ||
resArr := make([]*adapters.RequestData, 0, initialCapacity) | ||
startInd := 0 | ||
impsLeft := len(imps) > 0 | ||
|
||
headers := http.Header{} | ||
headers.Add("Content-Type", "application/json") | ||
headers.Add("Accept", "application/json") | ||
|
||
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) | ||
} | ||
} | ||
|
||
for impsLeft { | ||
endInd := startInd + maxImpsPerReq | ||
if endInd >= len(imps) { | ||
endInd = len(imps) | ||
impsLeft = false | ||
} | ||
impsForReq := imps[startInd:endInd] | ||
request.Imp = impsForReq | ||
|
||
reqJSON, err := jsonutil.Marshal(request) | ||
if err != nil { | ||
errs = append(errs, err) | ||
return nil, errs | ||
} | ||
|
||
resArr = append(resArr, &adapters.RequestData{ | ||
Method: "POST", | ||
Uri: uri, | ||
Body: reqJSON, | ||
Headers: headers, | ||
ImpIDs: openrtb_ext.GetImpIDs(request.Imp), | ||
}) | ||
startInd = endInd | ||
} | ||
return resArr, errs | ||
} | ||
|
||
func buildRequestImp(imp *openrtb2.Imp, ext impExtIncoming, displayManagerVer string, reqInfo *adapters.ExtraRequestInfo) error { | ||
if imp.Banner != nil { | ||
bannerCopy := *imp.Banner | ||
|
||
if bannerCopy.W == nil && bannerCopy.H == nil && len(bannerCopy.Format) > 0 { | ||
firstFormat := bannerCopy.Format[0] | ||
bannerCopy.W = &(firstFormat.W) | ||
bannerCopy.H = &(firstFormat.H) | ||
} | ||
imp.Banner = &bannerCopy | ||
} | ||
|
||
// Populate imp.displaymanagerver if the SDK failed to do it. | ||
if len(imp.DisplayManagerVer) == 0 && len(displayManagerVer) > 0 { | ||
imp.DisplayManagerVer = displayManagerVer | ||
} | ||
|
||
// Check if imp comes with bid floor amount defined in a foreign currency | ||
if imp.BidFloor > 0 && imp.BidFloorCur != "" && !strings.EqualFold(imp.BidFloorCur, "USD") { | ||
// Convert to US dollars | ||
convertedValue, err := reqInfo.ConvertCurrency(imp.BidFloor, imp.BidFloorCur, "USD") | ||
if err != nil { | ||
return err | ||
} | ||
// Update after conversion. All imp elements inside request.Imp are shallow copies | ||
// therefore, their non-pointer values are not shared memory and are safe to modify. | ||
imp.BidFloorCur = "USD" | ||
imp.BidFloor = convertedValue | ||
} | ||
|
||
impExt := impExt{ | ||
Connatix: impExtConnatix{ | ||
PlacementId: ext.Bidder.PlacementId, | ||
}, | ||
} | ||
|
||
var err error | ||
imp.Ext, err = json.Marshal(impExt) | ||
|
||
return err | ||
} | ||
|
||
func buildDisplayManagerVer(req *openrtb2.BidRequest) string { | ||
if req.App == nil { | ||
return "" | ||
} | ||
|
||
source, err := jsonparser.GetString(req.App.Ext, openrtb_ext.PrebidExtKey, "source") | ||
if err != nil { | ||
return "" | ||
} | ||
|
||
version, err := jsonparser.GetString(req.App.Ext, openrtb_ext.PrebidExtKey, "version") | ||
if err != nil { | ||
return "" | ||
} | ||
|
||
return fmt.Sprintf("%s-%s", source, version) | ||
} | ||
|
||
func getBidType(ext bidExt) openrtb_ext.BidType { | ||
if ext.Cnx.MediaType == "video" { | ||
return openrtb_ext.BidTypeVideo | ||
} | ||
|
||
return openrtb_ext.BidTypeBanner | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package connatix | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/prebid/prebid-server/v3/adapters/adapterstest" | ||
"github.com/prebid/prebid-server/v3/config" | ||
"github.com/prebid/prebid-server/v3/openrtb_ext" | ||
) | ||
|
||
func TestJsonSamples(t *testing.T) { | ||
bidder, buildErr := Builder(openrtb_ext.BidderConnatix, config.Adapter{ | ||
Endpoint: "http://example.com"}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}) | ||
|
||
if buildErr != nil { | ||
t.Fatalf("Builder returned unexpected error %v", buildErr) | ||
} | ||
|
||
adapterstest.RunJSONBidderTest(t, "connatixtest", bidder) | ||
} |
Oops, something went wrong.