-
Notifications
You must be signed in to change notification settings - Fork 760
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: Ogury #4082
base: master
Are you sure you want to change the base?
New Adapter: Ogury #4082
Changes from all commits
f26eff9
a7b2104
ec83b52
0eaa327
3a6c990
c4d6496
57fe53a
cfc66d0
1125795
2289c6c
119a517
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,200 @@ | ||
package ogury | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
"strings" | ||
|
||
"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" | ||
) | ||
|
||
type adapter struct { | ||
endpoint string | ||
} | ||
|
||
func Builder(_ openrtb_ext.BidderName, config config.Adapter, _ config.Server) (adapters.Bidder, error) { | ||
return &adapter{endpoint: config.Endpoint}, nil | ||
} | ||
|
||
func (a adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { | ||
headers := buildHeaders(request) | ||
|
||
request.Imp = filterValidImps(request) | ||
if len(request.Imp) == 0 { | ||
return nil, []error{&errortypes.BadInput{ | ||
Message: "Invalid request. assetKey/adUnitId or request.site.publisher.id required", | ||
}} | ||
} | ||
|
||
var errors []error | ||
for i, imp := range request.Imp { | ||
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 consolidate this for loop with the for loop starting at the line 72. |
||
var impExt, impExtBidderHoist map[string]json.RawMessage | ||
// extract ext | ||
if err := jsonutil.Unmarshal(imp.Ext, &impExt); err != nil { | ||
return nil, append(errors, &errortypes.BadInput{ | ||
Message: "Bidder extension not provided or can't be unmarshalled", | ||
}) | ||
} | ||
// find Ogury bidder params | ||
if bidder, ok := impExt[openrtb_ext.PrebidExtBidderKey]; ok { | ||
if err := jsonutil.Unmarshal(bidder, &impExtBidderHoist); err != nil { | ||
return nil, append(errors, &errortypes.BadInput{ | ||
Message: "Ogury bidder extension not provided or can't be unmarshalled", | ||
}) | ||
} | ||
} | ||
|
||
// extract every value from imp[].ext.bidder to imp[].ext | ||
for key, value := range impExtBidderHoist { | ||
impExt[key] = value | ||
} | ||
|
||
ext, err := jsonutil.Marshal(impExt) | ||
if err != nil { | ||
return nil, append(errors, &errortypes.BadInput{ | ||
Message: "Error while marshaling Imp.Ext bidder exension", | ||
}) | ||
} | ||
request.Imp[i].Ext = ext | ||
Comment on lines
+38
to
+65
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. Can you modify this to var impExt adapters.ExtImpBidder
if err := jsonutil.Unmarshal(imp.Ext, &impExt); err != nil {
return ..
}
var impExtOgury openrtb_ext.ImpExtOgury
if err := jsonutil.Unmarshal(impExt.Bidder, &impExtOgury); err != nil {
return...
} this is a preferable way to handle imp.ext in PBS. 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. If we do If we do var impExtOgury openrtb_ext.ImpExtOgury
if err := jsonutil.Unmarshal(impExt.Bidder, &impExtOgury); err != nil {
return...
} then we will lose all the other field besides what is in ImpExtOgury (we often experiment with some optional fields in the So the best way I see to handle this problem is like this, to unmarshal to |
||
|
||
// save adUnitCode | ||
request.Imp[i].TagID = imp.ID | ||
} | ||
|
||
// currency conversion | ||
for i, imp := range request.Imp { | ||
// Check if imp comes with bid floor amount defined in a foreign currency | ||
if imp.BidFloor > 0 && imp.BidFloorCur != "" && strings.ToUpper(imp.BidFloorCur) != "USD" { | ||
|
||
// Convert to US dollars | ||
convertedValue, err := requestInfo.ConvertCurrency(imp.BidFloor, imp.BidFloorCur, "USD") | ||
if err != nil { | ||
return nil, []error{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. | ||
request.Imp[i].BidFloorCur = "USD" | ||
request.Imp[i].BidFloor = convertedValue | ||
} | ||
} | ||
|
||
requestJSON, err := jsonutil.Marshal(request) | ||
if err != nil { | ||
return nil, []error{err} | ||
} | ||
|
||
requestData := &adapters.RequestData{ | ||
Method: "POST", | ||
Uri: a.endpoint, | ||
Body: requestJSON, | ||
Headers: headers, | ||
ImpIDs: openrtb_ext.GetImpIDs(request.Imp), | ||
} | ||
|
||
return []*adapters.RequestData{requestData}, nil | ||
|
||
} | ||
|
||
func filterValidImps(request *openrtb2.BidRequest) (validImps []openrtb2.Imp) { | ||
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. You may want to return an array of the results of unmarshling the imp.ext's since you unmarshal them again in the calling function. It is true that you unmarshal |
||
for _, imp := range request.Imp { | ||
var impExt adapters.ExtImpBidder | ||
var impExtOgury openrtb_ext.ImpExtOgury | ||
|
||
if err := jsonutil.Unmarshal(imp.Ext, &impExt); err != nil { | ||
continue | ||
} | ||
if err := jsonutil.Unmarshal(impExt.Bidder, &impExtOgury); err != nil { | ||
continue | ||
} | ||
if impExtOgury.AssetKey != "" && impExtOgury.AdUnitID != "" { | ||
validImps = append(validImps, imp) | ||
} | ||
} | ||
|
||
// if we have imp with assetKey/adUnitId then we want to serve them | ||
if len(validImps) > 0 { | ||
return validImps | ||
} | ||
|
||
// no assetKey/adUnitId imps then we serve everything if publisher.ID exists | ||
if request.Site != nil && request.Site.Publisher.ID != "" { | ||
return request.Imp | ||
} | ||
|
||
// else no valid imp | ||
return nil | ||
} | ||
|
||
func buildHeaders(request *openrtb2.BidRequest) http.Header { | ||
headers := http.Header{} | ||
headers.Add("Content-Type", "application/json;charset=utf-8") | ||
if request.Device != nil { | ||
headers.Add("X-Forwarded-For", request.Device.IP) | ||
krdzo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
headers.Add("X-Forwarded-For", request.Device.IPv6) | ||
headers.Add("User-Agent", request.Device.UA) | ||
headers.Add("Accept-Language", request.Device.Language) | ||
} | ||
return headers | ||
|
||
} | ||
|
||
func getMediaTypeForBid(bid openrtb2.Bid) (openrtb_ext.BidType, error) { | ||
switch bid.MType { | ||
case openrtb2.MarkupBanner: | ||
return openrtb_ext.BidTypeBanner, nil | ||
case openrtb2.MarkupAudio: | ||
return openrtb_ext.BidTypeAudio, nil | ||
case openrtb2.MarkupNative: | ||
return openrtb_ext.BidTypeNative, nil | ||
case openrtb2.MarkupVideo: | ||
return openrtb_ext.BidTypeVideo, nil | ||
default: | ||
return "", &errortypes.BadServerResponse{ | ||
Message: fmt.Sprintf("Unsupported MType \"%d\", for impression \"%s\"", bid.MType, bid.ImpID), | ||
} | ||
} | ||
} | ||
krdzo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
func (a adapter) MakeBids(request *openrtb2.BidRequest, _ *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) { | ||
if adapters.IsResponseStatusCodeNoContent(responseData) { | ||
return nil, nil | ||
} | ||
if err := adapters.CheckResponseStatusCodeForErrors(responseData); err != nil { | ||
return nil, []error{err} | ||
} | ||
|
||
var response openrtb2.BidResponse | ||
if err := jsonutil.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, bid := range seatBid.Bid { | ||
bidType, err := getMediaTypeForBid(bid) | ||
if err != nil { | ||
errors = append(errors, err) | ||
continue | ||
} | ||
bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ | ||
Bid: &seatBid.Bid[i], | ||
BidType: bidType, | ||
}) | ||
} | ||
} | ||
if errors != nil { | ||
return nil, errors | ||
} | ||
|
||
return bidResponse, nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package ogury | ||
|
||
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.BidderOgury, config.Adapter{ | ||
Endpoint: "http://ogury.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, "ogurytest", bidder) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
{ | ||
"mockBidRequest": { | ||
"id": "test-request-id", | ||
"imp": [ | ||
{ | ||
"id": "ad-unit-code-as-imp-id", | ||
"banner": { | ||
"format": [{"w": 128, "h": 100}] | ||
}, | ||
"ext": { | ||
"gpid": "global position id", | ||
"bidder": { | ||
"assetKey": "OGY", | ||
"adUnitId": "123" | ||
} | ||
} | ||
} | ||
] | ||
}, | ||
|
||
"httpCalls": [ | ||
{ | ||
"expectedRequest": { | ||
"uri": "http://ogury.example.com", | ||
"body": { | ||
"id": "test-request-id", | ||
"imp": [ | ||
{ | ||
"id":"ad-unit-code-as-imp-id", | ||
"tagid": "ad-unit-code-as-imp-id", | ||
"banner": { | ||
"format": [{"w": 128, "h": 100}] | ||
}, | ||
"ext": { | ||
"gpid": "global position id", | ||
"assetKey": "OGY", | ||
"adUnitId": "123", | ||
"bidder": { | ||
"assetKey": "OGY", | ||
"adUnitId": "123" | ||
} | ||
} | ||
} | ||
] | ||
}, | ||
"impIDs":["ad-unit-code-as-imp-id"] | ||
}, | ||
"mockResponse": { | ||
"status": 200, | ||
"body": { | ||
"id": "test-request-id", | ||
"cur": "USD", | ||
"seatbid": [ | ||
{ | ||
"seat": "seat", | ||
"bid": [{ | ||
"id": "some-UUID", | ||
"impid": "ad-unit-code-as-imp-id", | ||
"price": 0.500000, | ||
"adm": "adm string", | ||
"crid": "crid_10", | ||
"h": 100, | ||
"w": 128, | ||
"mtype": 1 | ||
}] | ||
} | ||
] | ||
} | ||
} | ||
} | ||
], | ||
|
||
"expectedBidResponses": [ | ||
{ | ||
"currency": "USD", | ||
"bids": [ | ||
{ | ||
"bid": { | ||
"id": "some-UUID", | ||
"impid": "ad-unit-code-as-imp-id", | ||
"price": 0.5, | ||
"adm": "adm string", | ||
"crid": "crid_10", | ||
"h": 100, | ||
"w": 128, | ||
"mtype": 1 | ||
}, | ||
"type": "banner" | ||
} | ||
] | ||
} | ||
] | ||
} |
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.
I believe this function can be deleted, please my another comment in
augury.json
file