-
Notifications
You must be signed in to change notification settings - Fork 739
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: Epom #1680
New Adapter: Epom #1680
Changes from 1 commit
64b80fe
89c104f
ff556f8
0c98ec5
cbf13c7
ed58567
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,172 @@ | ||||
package epom | ||||
|
||||
import ( | ||||
"encoding/json" | ||||
"fmt" | ||||
"net/http" | ||||
|
||||
"github.com/mxmCherry/openrtb" | ||||
"github.com/prebid/prebid-server/adapters" | ||||
"github.com/prebid/prebid-server/config" | ||||
"github.com/prebid/prebid-server/errortypes" | ||||
"github.com/prebid/prebid-server/openrtb_ext" | ||||
) | ||||
|
||||
type EpomAdapter struct { | ||||
endpoint string | ||||
} | ||||
|
||||
// Builder builds a new instance of the Epom adapter for the given bidder with the given config. | ||||
func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters.Bidder, error) { | ||||
bidder := &EpomAdapter{ | ||||
endpoint: config.Endpoint, | ||||
} | ||||
return bidder, nil | ||||
} | ||||
|
||||
func (a *EpomAdapter) MakeRequests(request *openrtb.BidRequest, reqInfo *adapters.ExtraRequestInfo) (requests []*adapters.RequestData, errors []error) { | ||||
rq, errs := a.makeRequest(request) | ||||
|
||||
if len(errs) > 0 { | ||||
errors = append(errors, errs...) | ||||
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 can return the
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 are right. Fixed! |
||||
return nil, errors | ||||
} | ||||
|
||||
if rq != nil { | ||||
requests = append(requests, rq) | ||||
} | ||||
|
||||
return requests, errors | ||||
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. Errors will always be empty here. Consider returning
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. Done |
||||
} | ||||
|
||||
func (a *EpomAdapter) makeRequest(request *openrtb.BidRequest) (*adapters.RequestData, []error) { | ||||
var errs []error | ||||
var validImps []openrtb.Imp | ||||
|
||||
if len(request.Imp) == 0 { | ||||
return nil, []error{&errortypes.BadInput{ | ||||
Message: "No impressions in request", | ||||
}} | ||||
} | ||||
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. The imp length check is performed by PBS-Core. It does not need to be repeated here. 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. Ok. Removed! |
||||
|
||||
if request.Device == nil || request.Device.IP == "" { | ||||
SyntaxNode marked this conversation as resolved.
Show resolved
Hide resolved
|
||||
return nil, []error{&errortypes.BadInput{ | ||||
Message: "No ip address in request", | ||||
}} | ||||
} | ||||
|
||||
if request.Site == nil && request.App == nil { | ||||
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. This check is performed by PBS-Core. You can remove it here. You can assume you'll always have either a Site or App defined here, not both and not neither. 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. Ok. Removed |
||||
return nil, []error{&errortypes.BadInput{ | ||||
Message: "Site or app field shouldn't be empty", | ||||
}} | ||||
} | ||||
|
||||
if request.Site != nil && request.App != nil { | ||||
return nil, []error{&errortypes.BadInput{ | ||||
Message: "Site and app can't be filled simultaneously", | ||||
}} | ||||
} | ||||
SyntaxNode marked this conversation as resolved.
Show resolved
Hide resolved
|
||||
|
||||
for _, imp := range request.Imp { | ||||
if err := preprocess(&imp); err != nil { | ||||
errs = append(errs, err) | ||||
continue | ||||
} | ||||
validImps = append(validImps, imp) | ||||
} | ||||
|
||||
if len(validImps) == 0 { | ||||
return nil, errs | ||||
} | ||||
|
||||
request.Imp = validImps | ||||
|
||||
reqJSON, err := json.Marshal(request) | ||||
if err != nil { | ||||
errs = append(errs, err) | ||||
return nil, errs | ||||
} | ||||
|
||||
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, | ||||
}, errs | ||||
} | ||||
|
||||
func preprocess(imp *openrtb.Imp) 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. I actually don't think you need this check. PBS-Core has you covered here too. See: prebid-server/endpoints/openrtb2/auction.go Line 472 in ef06fac
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. Ok. Here I removed id check and added check if impression media type is not audio (we don't support audio) |
||||
if imp.ID == "" { | ||||
return &errortypes.BadInput{ | ||||
Message: "Impression id is empty", | ||||
} | ||||
} | ||||
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. This check is also covered by PBS-Core, since audio excluded as an acceptable type in the yaml file. You can remove the entire In the end, I think this would be sufficient:
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. Thank you! Used your code. Check please. |
||||
|
||||
return nil | ||||
} | ||||
|
||||
func (a *EpomAdapter) MakeBids(internalRequest *openrtb.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { | ||||
if response.StatusCode == http.StatusNoContent { | ||||
return nil, nil | ||||
} | ||||
|
||||
if response.StatusCode >= http.StatusInternalServerError { | ||||
return nil, []error{&errortypes.BadServerResponse{ | ||||
Message: fmt.Sprintf("Unexpected status code: %d. Dsp server internal error", response.StatusCode), | ||||
}} | ||||
} | ||||
|
||||
if response.StatusCode >= http.StatusBadRequest { | ||||
return nil, []error{&errortypes.BadInput{ | ||||
Message: fmt.Sprintf("Unexpected status code: %d. Bad request to dsp", response.StatusCode), | ||||
}} | ||||
} | ||||
|
||||
if response.StatusCode != http.StatusOK { | ||||
return nil, []error{&errortypes.BadServerResponse{ | ||||
Message: fmt.Sprintf("Unexpected status code: %d", response.StatusCode), | ||||
}} | ||||
} | ||||
|
||||
var bidResp openrtb.BidResponse | ||||
if err := json.Unmarshal(response.Body, &bidResp); err != nil { | ||||
return nil, []error{err} | ||||
} | ||||
|
||||
//additional no content check | ||||
if len(bidResp.SeatBid) == 0 || len(bidResp.SeatBid[0].Bid) == 0 { | ||||
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. Could you please add a test for this condition. 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. Tests with empty seatbid and bid objects added |
||||
return nil, nil | ||||
} | ||||
|
||||
bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(bidResp.SeatBid[0].Bid)) | ||||
|
||||
var errs []error | ||||
for _, seatBid := range bidResp.SeatBid { | ||||
for _, bid := range seatBid.Bid { | ||||
b := &adapters.TypedBid{ | ||||
Bid: &bid, | ||||
BidType: getMediaTypeForImp(bid.ImpID, internalRequest.Imp), | ||||
} | ||||
bidResponse.Bids = append(bidResponse.Bids, b) | ||||
} | ||||
} | ||||
return bidResponse, errs | ||||
} | ||||
|
||||
func getMediaTypeForImp(impID string, imps []openrtb.Imp) openrtb_ext.BidType { | ||||
for _, imp := range imps { | ||||
if imp.ID == impID { | ||||
if imp.Banner != nil { | ||||
return openrtb_ext.BidTypeBanner | ||||
} else if imp.Video != nil { | ||||
return openrtb_ext.BidTypeVideo | ||||
} else if imp.Native != nil { | ||||
return openrtb_ext.BidTypeNative | ||||
} | ||||
} | ||||
} | ||||
return openrtb_ext.BidTypeBanner | ||||
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. Does your bidding server include the bid format in the response? 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. Epom bidding server responds according to OpenRtb 2.5 spec. So, bid doesn't have any bid format info. 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. It's preferable to include metadata in your bidding server response to be sure PBS has the right creative type to ensure proper rendering. If we can't receive a hint from your server, please ensure the order of preference matches your server. For example, banner is always chosen over video. 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. Yes, Epom Bidder always choose media type these way. Banner type is the first priority, then - video and then - native. |
||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package epom | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/prebid/prebid-server/adapters/adapterstest" | ||
"github.com/prebid/prebid-server/config" | ||
"github.com/prebid/prebid-server/openrtb_ext" | ||
) | ||
|
||
func TestJsonSamples(t *testing.T) { | ||
bidder, buildErr := Builder(openrtb_ext.BidderEpom, config.Adapter{ | ||
Endpoint: "https://an.epom.com/ortb"}) | ||
|
||
if buildErr != nil { | ||
t.Fatalf("Builder returned unexpected error %v", buildErr) | ||
} | ||
|
||
adapterstest.RunJSONBidderTest(t, "epomtest", bidder) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
{ | ||
"mockBidRequest": { | ||
"id": "test-request-id", | ||
"app": { | ||
"bundle": "com.prebid" | ||
}, | ||
"device": { | ||
"ip":"238.89.104.156" | ||
}, | ||
"imp": [ | ||
{ | ||
"id": "test-imp-id", | ||
"banner": { | ||
"format": [ | ||
{ | ||
"w": 300, | ||
"h": 50 | ||
} | ||
] | ||
} | ||
} | ||
] | ||
}, | ||
|
||
"httpCalls": [ | ||
{ | ||
"expectedRequest": { | ||
"uri": "https://an.epom.com/ortb", | ||
"headers": { | ||
"Accept": [ | ||
"application/json" | ||
], | ||
"Content-Type": [ | ||
"application/json;charset=utf-8" | ||
] | ||
}, | ||
"body": { | ||
"id": "test-request-id", | ||
"app": { | ||
"bundle": "com.prebid" | ||
}, | ||
"device": { | ||
"ip":"238.89.104.156" | ||
}, | ||
"imp": [ | ||
{ | ||
"id": "test-imp-id", | ||
"banner": { | ||
"format": [ | ||
{ | ||
"w": 300, | ||
"h": 50 | ||
} | ||
] | ||
} | ||
} | ||
] | ||
} | ||
}, | ||
"mockResponse": { | ||
"status": 200, | ||
"body": { | ||
"id": "test-request-id", | ||
"seatbid": [ | ||
{ | ||
"seat": "epom", | ||
"bid": [ | ||
{ | ||
"id": "1", | ||
"impid": "test-imp-id", | ||
"price": 0.500000, | ||
"adm": "test-adm", | ||
"crid": "test-crid", | ||
"h": 50, | ||
"w": 300 | ||
} | ||
] | ||
} | ||
], | ||
"cur": "USD" | ||
} | ||
} | ||
} | ||
], | ||
|
||
"expectedBidResponses": [ | ||
{ | ||
"currency": "USD", | ||
"bids": [ | ||
{ | ||
"bid": { | ||
"id": "1", | ||
"impid": "test-imp-id", | ||
"price": 0.5, | ||
"adm": "test-adm", | ||
"crid": "test-crid", | ||
"w": 300, | ||
"h": 50 | ||
}, | ||
"type": "banner" | ||
} | ||
] | ||
} | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
{ | ||
"mockBidRequest": { | ||
"id": "test-request-id", | ||
"app": { | ||
"bundle": "com.prebid" | ||
}, | ||
"device": { | ||
"ip":"238.89.104.156" | ||
}, | ||
"imp": [ | ||
{ | ||
"id": "test-imp-id", | ||
"native": { | ||
"ver": "1.1", | ||
"request": "{\"ver\":\"1.0\",\"layout\":1,\"adunit\":1,\"plcmttype\":1,\"plcmtcnt\":1,\"seq\":0,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":75}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":60,\"hmin\":60,\"mimes\":[\"image/jpeg\",\"image/jpg\",\"image/png\"]}},{\"id\":3,\"required\":0,\"data\":{\"type\":2,\"len\":75}},{\"id\":4,\"required\":0,\"data\":{\"type\":6,\"len\":1000}},{\"id\":5,\"required\":0,\"data\":{\"type\":7,\"len\":1000}},{\"id\":6,\"required\":0,\"data\":{\"type\":11,\"len\":1000}}]}" | ||
} | ||
} | ||
] | ||
}, | ||
|
||
"httpCalls": [ | ||
{ | ||
"expectedRequest": { | ||
"uri": "https://an.epom.com/ortb", | ||
"headers": { | ||
"Accept": [ | ||
"application/json" | ||
], | ||
"Content-Type": [ | ||
"application/json;charset=utf-8" | ||
] | ||
}, | ||
"body": { | ||
"id": "test-request-id", | ||
"app": { | ||
"bundle": "com.prebid" | ||
}, | ||
"device": { | ||
"ip":"238.89.104.156" | ||
}, | ||
"imp": [ | ||
{ | ||
"id": "test-imp-id", | ||
"native": { | ||
"ver": "1.1", | ||
"request": "{\"ver\":\"1.0\",\"layout\":1,\"adunit\":1,\"plcmttype\":1,\"plcmtcnt\":1,\"seq\":0,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":75}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":60,\"hmin\":60,\"mimes\":[\"image/jpeg\",\"image/jpg\",\"image/png\"]}},{\"id\":3,\"required\":0,\"data\":{\"type\":2,\"len\":75}},{\"id\":4,\"required\":0,\"data\":{\"type\":6,\"len\":1000}},{\"id\":5,\"required\":0,\"data\":{\"type\":7,\"len\":1000}},{\"id\":6,\"required\":0,\"data\":{\"type\":11,\"len\":1000}}]}" | ||
} | ||
} | ||
] | ||
} | ||
}, | ||
"mockResponse": { | ||
"status": 200, | ||
"body": { | ||
"id": "test-request-id", | ||
"seatbid": [ | ||
{ | ||
"seat": "epom", | ||
"bid": [{ | ||
"id": "1", | ||
"impid": "test-imp-id", | ||
"price": 0.500000, | ||
"adm": "some-test-adm", | ||
"crid": "test-crid" | ||
}] | ||
} | ||
], | ||
"cur": "USD" | ||
} | ||
} | ||
} | ||
], | ||
|
||
"expectedBidResponses": [ | ||
{ | ||
"currency": "USD", | ||
"bids": [ | ||
{ | ||
"bid": { | ||
"id": "1", | ||
"impid": "test-imp-id", | ||
"price": 0.5, | ||
"adm": "some-test-adm", | ||
"crid": "test-crid" | ||
}, | ||
"type": "native" | ||
} | ||
] | ||
} | ||
] | ||
} |
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.
Please use the name
adapter
. There is no need to repeat the adapter name from the package and there is no need to export the type (it should start with a lower case letter to be package private).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.
Renamed