-
Notifications
You must be signed in to change notification settings - Fork 762
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
New Adapter: Сointraffic #3647
New Adapter: Сointraffic #3647
Changes from 1 commit
ef97284
bf6223c
bb30f63
110d864
b3204a2
bf3caf1
c21d599
8872565
cbf5b42
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
package cointraffic | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"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" | ||
"github.com/prebid/prebid-server/v2/openrtb_ext" | ||
"net/http" | ||
) | ||
|
||
type adapter struct { | ||
endpoint string | ||
} | ||
|
||
// Builder builds a new instance of the Foo 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, requestInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { | ||
requestJSON, err := json.Marshal(request) | ||
if err != nil { | ||
return nil, []error{err} | ||
} | ||
|
||
headers := http.Header{} | ||
headers.Add("Content-Type", "application/json") | ||
headers.Add("Accept", "application/json") | ||
|
||
if request.Device != nil && len(request.Device.UA) > 0 { | ||
headers.Set("User-Agent", request.Device.UA) | ||
} | ||
if request.Device != nil && len(request.Device.IP) > 0 { | ||
headers.Set("X-Forwarded-For", request.Device.IP) | ||
} | ||
|
||
//if request.User != nil { | ||
// headers.Set("user-id", request.User.ID) | ||
// headers.Set("user-cd", request.User.CustomData) | ||
//} | ||
|
||
requestData := &adapters.RequestData{ | ||
Method: "POST", | ||
Uri: a.endpoint, | ||
Body: requestJSON, | ||
ImpIDs: openrtb_ext.GetImpIDs(request.Imp), | ||
Headers: headers, | ||
} | ||
|
||
return []*adapters.RequestData{requestData}, nil | ||
} | ||
|
||
func (a *adapter) buildRequest(request *openrtb2.BidRequest) (*adapters.RequestData, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
reqJSON, err := json.Marshal(request) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
headers := http.Header{} | ||
headers.Add("Content-Type", "application/json;charset=utf-8") | ||
headers.Add("Accept", "application/json") | ||
|
||
return &adapters.RequestData{ | ||
Method: "POST", | ||
Uri: a.endpoint, | ||
Body: reqJSON, | ||
Headers: headers, | ||
ImpIDs: openrtb_ext.GetImpIDs(request.Imp), | ||
}, nil | ||
} | ||
|
||
func getMediaTypeForBid(bid openrtb2.Bid) (openrtb_ext.BidType, error) { | ||
if bid.Ext != nil { | ||
var bidExt openrtb_ext.ExtBid | ||
err := json.Unmarshal(bid.Ext, &bidExt) | ||
if err == nil && bidExt.Prebid != nil { | ||
return openrtb_ext.ParseBidType(string(bidExt.Prebid.Type)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider this as a suggestion. Prebid server expects the media type to be explicitly set in the adapter response. Therefore, recommends implementing a pattern where the adapter server sets the MType field in the response to accurately determine the media type for the impression. |
||
} | ||
} | ||
|
||
return "", &errortypes.BadServerResponse{ | ||
Message: fmt.Sprintf("Failed to parse impression \"%s\" mediatype", bid.ImpID), | ||
} | ||
} | ||
|
||
func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) { | ||
if responseData.StatusCode == http.StatusNoContent { | ||
return nil, nil | ||
} | ||
|
||
if responseData.StatusCode == http.StatusBadRequest { | ||
err := &errortypes.BadInput{ | ||
Message: "Unexpected status code: 400. Bad request from publisher. Run with request.debug = 1 for more info.", | ||
} | ||
return nil, []error{err} | ||
} | ||
|
||
if responseData.StatusCode != http.StatusOK { | ||
err := &errortypes.BadServerResponse{ | ||
Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info.", responseData.StatusCode), | ||
} | ||
return nil, []error{err} | ||
} | ||
|
||
var response openrtb2.BidResponse | ||
if err := json.Unmarshal(responseData.Body, &response); err != nil { | ||
return nil, []error{err} | ||
} | ||
|
||
bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp)) | ||
bidResponse.Currency = response.Cur | ||
//var errors []error | ||
for _, seatBid := range response.SeatBid { | ||
for i, _ := range seatBid.Bid { | ||
bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ | ||
Bid: &seatBid.Bid[i], | ||
BidType: openrtb_ext.BidTypeBanner, | ||
}) | ||
} | ||
} | ||
return bidResponse, nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package cointraffic | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
|
||
"github.com/prebid/prebid-server/v2/adapters/adapterstest" | ||
"github.com/prebid/prebid-server/v2/config" | ||
"github.com/prebid/prebid-server/v2/openrtb_ext" | ||
) | ||
|
||
func TestJsonSamples(t *testing.T) { | ||
bidder, buildErr := Builder(openrtb_ext.BidderCointraffic, config.Adapter{ | ||
Endpoint: "http://localhost:3555/api/v1/rtb", | ||
ExtraAdapterInfo: "", | ||
}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}) | ||
|
||
if buildErr != nil { | ||
t.Fatalf("Builder returned unexpected error %v", buildErr) | ||
} | ||
|
||
adapterstest.RunJSONBidderTest(t, "cointraffictest", bidder) | ||
} | ||
|
||
func TestEndpointTemplateMalformed(t *testing.T) { | ||
_, buildErr := Builder(openrtb_ext.BidderCointraffic, config.Adapter{ | ||
Endpoint: "{{Malformed}}"}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}) | ||
|
||
assert.Nil(t, buildErr) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
{ | ||
"mockBidRequest": { | ||
"id": "test-request-id", | ||
"imp": [ | ||
{ | ||
"id": "1", | ||
"banner": { | ||
"format": [ | ||
{ | ||
"w": 320, | ||
"h": 50 | ||
} | ||
] | ||
}, | ||
"ext": { | ||
"bidder": { | ||
"placementId": "placementId-test" | ||
} | ||
} | ||
} | ||
], | ||
"device": { | ||
"ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36", | ||
"ip": "111.111.111.111" | ||
}, | ||
"user": { | ||
"id": "userid", | ||
"customData": "customdata" | ||
} | ||
}, | ||
"httpCalls": [ | ||
{ | ||
"expectedRequest": { | ||
"headers": { | ||
"Accept": [ | ||
"application/json" | ||
], | ||
"Content-Type": [ | ||
"application/json" | ||
], | ||
"X-Forwarded-For": [ | ||
"111.111.111.111" | ||
], | ||
"User-Agent": [ | ||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36" | ||
] | ||
}, | ||
"uri": "http://localhost:3555/api/v1/rtb", | ||
"body": { | ||
"id": "test-request-id", | ||
"imp": [ | ||
{ | ||
"id": "1", | ||
"banner": { | ||
"format": [ | ||
{ | ||
"w": 320, | ||
"h": 50 | ||
} | ||
] | ||
}, | ||
"ext": { | ||
"bidder": { | ||
"placementId": "placementId-test" | ||
} | ||
} | ||
} | ||
], | ||
"device":{"ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36","ip":"111.111.111.111"}, | ||
"user": { | ||
"id": "userid", | ||
"customdata": "customdata" | ||
} | ||
}, | ||
"impIDs":["1"] | ||
}, | ||
"mockResponse": { | ||
"status": 200, | ||
"body": { | ||
"id": "test-request-id", | ||
"seatbid": [ | ||
{ | ||
"seat": "cointraffic", | ||
"bid": [ | ||
{ | ||
"id": "test-bid-id", | ||
"impid": "1", | ||
"price": 1.50, | ||
"adm": "some-test-ad", | ||
"crid": "test-crid", | ||
"h": 50, | ||
"w": 320 | ||
} | ||
] | ||
} | ||
], | ||
"cur": "USD" | ||
} | ||
} | ||
} | ||
], | ||
"expectedBidResponses": [ | ||
{ | ||
"currency": "USD", | ||
"bids": [ | ||
{ | ||
"bid": { | ||
"id": "test-bid-id", | ||
"impid": "1", | ||
"price": 1.50, | ||
"adm": "some-test-ad", | ||
"crid": "test-crid", | ||
"w": 320, | ||
"h": 50 | ||
}, | ||
"type": "banner" | ||
} | ||
] | ||
} | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package cointraffic | ||
|
||
import ( | ||
"encoding/json" | ||
"testing" | ||
|
||
"github.com/prebid/prebid-server/v2/openrtb_ext" | ||
) | ||
|
||
// This file actually intends to test static/bidder-params/aax.json | ||
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.BidderCointraffic, json.RawMessage(validParam)); err != nil { | ||
t.Errorf("Schema rejected 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.BidderCointraffic, json.RawMessage(invalidParam)); err == nil { | ||
t.Errorf("Schema allowed unexpected params: %s", invalidParam) | ||
} | ||
} | ||
} | ||
|
||
var validParams = []string{ | ||
`{"placementId":"123"}`, | ||
} | ||
|
||
var invalidParams = []string{ | ||
``, | ||
`null`, | ||
`true`, | ||
`5`, | ||
`4.2`, | ||
`[]`, | ||
`{}`, | ||
`{"cid":"", "crid":""}`, | ||
`{"cid":"only cid is present"}`, | ||
`{"crid":"only crid is present"}`, | ||
`{"ccid":"123","ccrid":"123"}`, | ||
`{"aid":123, "siteId":"321"}`, | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -80,6 +80,7 @@ var coreBidderNames []BidderName = []BidderName{ | |
BidderCadentApertureMX, | ||
BidderCcx, | ||
BidderCoinzilla, | ||
BidderCointraffic, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Super nitpick: please move this above |
||
BidderColossus, | ||
BidderCompass, | ||
BidderConnectAd, | ||
|
@@ -366,6 +367,7 @@ const ( | |
BidderCadentApertureMX BidderName = "cadent_aperture_mx" | ||
BidderCcx BidderName = "ccx" | ||
BidderCoinzilla BidderName = "coinzilla" | ||
BidderCointraffic BidderName = "cointraffic" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Super nitpick: please move this above |
||
BidderColossus BidderName = "colossus" | ||
BidderCompass BidderName = "compass" | ||
BidderConnectAd BidderName = "connectad" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package openrtb_ext | ||
|
||
type ExtImpCointraffic struct { | ||
PlacementId string `json:"PlacementId"` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please consider using all lower case "placementid" or snake case "placementId" for bidder parameters. |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
endpoint: "http://localhost:3555/api/v1/rtb" # todo: static load balancer | ||
geoscope: | ||
- EUU | ||
- CAN | ||
maintainer: | ||
email: [email protected] | ||
modifyingVastXmlAllowed: true | ||
capabilities: | ||
app: | ||
mediaTypes: | ||
- banner | ||
- native | ||
site: | ||
mediaTypes: | ||
- banner | ||
- native | ||
#userSync: | ||
# redirect: | ||
# url: https://foo.com/sync?gdpr={{.GDPR}}&consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect={{.RedirectURL}} | ||
# userMacro: $UID |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for using the template from the docs. Please rename "Foo" to "Cointraffic" for your adapter.