-
Notifications
You must be signed in to change notification settings - Fork 867
New Adapter: BeOp (WIP) #4566
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: BeOp (WIP) #4566
Changes from all commits
0c56b14
3b044f2
db6bc4e
b0b4833
70e7896
68f08c5
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,178 @@ | ||
| package beop | ||
|
|
||
| import ( | ||
| "encoding/json" | ||
| "fmt" | ||
| "net/http" | ||
| "net/url" | ||
|
|
||
| "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( | ||
| bidderName openrtb_ext.BidderName, | ||
| config config.Adapter, | ||
| server config.Server) ( | ||
| adapters.Bidder, error, | ||
| ) { | ||
| bidder := &adapter{ | ||
| endpoint: config.Endpoint, | ||
| } | ||
| return bidder, nil | ||
| } | ||
|
|
||
| func (a *adapter) getRequestExtImpBeop(imp *openrtb2.Imp) (*openrtb_ext.ExtImpBeop, error) { | ||
| var bidderExt adapters.ExtImpBidder | ||
| if err := jsonutil.Unmarshal(imp.Ext, &bidderExt); err != nil { | ||
| return nil, &errortypes.BadInput{ | ||
| Message: "ext.bidder not provided", | ||
| } | ||
| } | ||
| var beopExt openrtb_ext.ExtImpBeop | ||
| if err := jsonutil.Unmarshal(bidderExt.Bidder, &beopExt); err != nil { | ||
| return nil, &errortypes.BadInput{ | ||
| Message: "ext.bidder not provided", | ||
| } | ||
| } | ||
| if beopExt.BeopPublisherID == "" && beopExt.BeopNetworkID == "" { | ||
| return nil, &errortypes.BadInput{ | ||
| Message: "Missing pid or nid parameters", | ||
| } | ||
| } | ||
| return &beopExt, nil | ||
| } | ||
|
|
||
| func (a *adapter) buildEndpointURL(params *openrtb_ext.ExtImpBeop) (string, error) { | ||
| url, err := url.Parse(a.endpoint) | ||
| if err != nil { | ||
| return "", &errortypes.Warning{ | ||
| Message: "Failed to parse endpoint", | ||
| } | ||
| } | ||
| query := url.Query() | ||
| if pid := params.BeopPublisherID; len(pid) != 0 { | ||
| query.Set("pid", pid) | ||
| } | ||
| if nid := params.BeopNetworkID; len(nid) != 0 { | ||
| query.Set("nid", nid) | ||
| } | ||
| if nptnid := params.BeopNetworkPartnerID; len(nptnid) != 0 { | ||
| query.Set("nptnid", nptnid) | ||
| } | ||
| url.RawQuery = query.Encode() | ||
| return url.String(), nil | ||
| } | ||
|
|
||
| func (a *adapter) MakeRequests( | ||
| request *openrtb2.BidRequest, | ||
| requestInfo *adapters.ExtraRequestInfo) ( | ||
| []*adapters.RequestData, []error, | ||
| ) { | ||
| var beopExt *openrtb_ext.ExtImpBeop | ||
| var err error | ||
|
|
||
| beopExt, err = a.getRequestExtImpBeop(&request.Imp[0]) | ||
| if err != nil { | ||
| return nil, []error{err} | ||
| } | ||
|
|
||
| requestJSON, err := json.Marshal(request) | ||
| if err != nil { | ||
| return nil, []error{err} | ||
| } | ||
|
|
||
| headers := http.Header{} | ||
| headers.Add("Content-Type", "application/json;charset=utf-8") | ||
| headers.Add("Accept", "application/json") | ||
|
|
||
| url, err := a.buildEndpointURL(beopExt) | ||
| if err != nil { | ||
| return nil, []error{err} | ||
| } | ||
|
|
||
| requestData := &adapters.RequestData{ | ||
| Method: "POST", | ||
| Uri: url, | ||
| Body: requestJSON, | ||
| Headers: headers, | ||
| ImpIDs: openrtb_ext.GetImpIDs(request.Imp), | ||
| } | ||
|
|
||
| return []*adapters.RequestData{requestData}, nil | ||
| } | ||
|
|
||
| func getMediaTypeForBid(bid openrtb2.Bid) (openrtb_ext.BidType, error) { | ||
| if bid.Ext != nil { | ||
| var bidExt openrtb_ext.ExtBid | ||
| err := jsonutil.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. 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. 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. 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. 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. 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.StatusServiceUnavailable { | ||
| return nil, []error{&errortypes.BadInput{ | ||
| Message: fmt.Sprintf("Service Unavailable. Status Code: [ %d ] ", responseData.StatusCode), | ||
| }} | ||
| } | ||
|
|
||
| if responseData.StatusCode == http.StatusBadRequest { | ||
| 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 responseBody openrtb2.BidResponse | ||
| if err := jsonutil.Unmarshal(responseData.Body, &responseBody); err != nil { | ||
| return nil, []error{&errortypes.BadServerResponse{ | ||
| Message: "Bad Server Response", | ||
| }} | ||
| } | ||
|
|
||
| if len(responseBody.SeatBid) == 0 { | ||
| return nil, []error{&errortypes.BadServerResponse{ | ||
| Message: "Empty SeatBid array", | ||
| }} | ||
| } | ||
|
|
||
| bidResponseFinal := adapters.NewBidderResponseWithBidsCapacity(len(responseBody.SeatBid[0].Bid)) | ||
| seatBid := responseBody.SeatBid[0] | ||
| var errors []error | ||
| for _, bid := range seatBid.Bid { | ||
| bidType, err := getMediaTypeForBid(bid) | ||
| if err != nil { | ||
| errors = append(errors, err) | ||
| continue | ||
| } | ||
| bidResponseFinal.Bids = append(bidResponseFinal.Bids, &adapters.TypedBid{ | ||
| Bid: &bid, | ||
|
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. Found incorrect assignment made to Bid. bid variable receives a new value in each iteration of range loop. Assigning the address of bid 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. Found incorrect assignment made to Bid. bid variable receives a new value in each iteration of range loop. Assigning the address of bid 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. Found incorrect assignment made to Bid. bid variable receives a new value in each iteration of range loop. Assigning the address of bid 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. Found incorrect assignment made to Bid. bid variable receives a new value in each iteration of range loop. Assigning the address of bid 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. Found incorrect assignment made to Bid. bid variable receives a new value in each iteration of range loop. Assigning the address of bid 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. Found incorrect assignment made to Bid. bid variable receives a new value in each iteration of range loop. Assigning the address of bid 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. Found incorrect assignment made to Bid. bid variable receives a new value in each iteration of range loop. Assigning the address of bid |
||
| BidType: bidType, | ||
| }) | ||
| } | ||
| return bidResponseFinal, errors | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| package beop | ||
|
|
||
| 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.BidderBeop, config.Adapter{ | ||
| Endpoint: "http://hb-test.collectiveaudience.co/rtb/bid"}, | ||
| config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}) | ||
|
|
||
| if buildErr != nil { | ||
| t.Fatalf("Builder returned unexpected error %v", buildErr) | ||
| } | ||
|
|
||
| adapterstest.RunJSONBidderTest(t, "beoptest", bidder) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,153 @@ | ||
| { | ||
| "mockBidRequest": { | ||
| "id": "request-id", | ||
| "site": { | ||
| "page": "test.com/page", | ||
| "domain": "test.com", | ||
| "cat": [ | ||
| "IAB9-1" | ||
| ], | ||
| "publisher": { | ||
| "id": "123456789" | ||
| } | ||
| }, | ||
| "device": { | ||
| "ua": "useragent", | ||
| "ip": "100.100.100.100", | ||
| "language": "en" | ||
| }, | ||
| "tmax": 1000, | ||
| "user": { | ||
| "id": "some-user" | ||
| }, | ||
| "imp": [ | ||
| { | ||
| "id": "impression-id", | ||
| "tagid": "tid", | ||
| "banner": { | ||
| "w": 320, | ||
| "h": 50 | ||
| }, | ||
| "ext": { | ||
| "bidder": { | ||
| "nid": "aaaaaaaaaaaaaaaaaaaaaaaa", | ||
| "nptnid": "1234" | ||
| } | ||
| } | ||
| } | ||
| ] | ||
| }, | ||
| "httpCalls": [ | ||
| { | ||
| "expectedRequest": { | ||
| "method": "POST", | ||
| "uri": "http://hb-test.collectiveaudience.co/rtb/bid?nid=aaaaaaaaaaaaaaaaaaaaaaaa&nptnid=1234", | ||
| "headers": { | ||
| "Content-Type": [ | ||
| "application/json;charset=utf-8" | ||
| ], | ||
| "Accept": [ | ||
| "application/json" | ||
| ] | ||
| }, | ||
| "body": { | ||
| "id": "request-id", | ||
| "device": { | ||
| "ua": "useragent", | ||
| "ip": "100.100.100.100", | ||
| "language": "en" | ||
| }, | ||
| "imp": [ | ||
| { | ||
| "id": "impression-id", | ||
| "banner": { | ||
| "w": 320, | ||
| "h": 50 | ||
| }, | ||
| "tagid": "tid", | ||
| "ext": { | ||
| "bidder": { | ||
| "nid": "aaaaaaaaaaaaaaaaaaaaaaaa", | ||
| "nptnid": "1234" | ||
| } | ||
| } | ||
| } | ||
| ], | ||
| "site": { | ||
| "page": "test.com/page", | ||
| "domain": "test.com", | ||
| "cat": [ | ||
| "IAB9-1" | ||
| ], | ||
| "publisher": { | ||
| "id": "123456789" | ||
| } | ||
| }, | ||
| "user": { | ||
| "id": "some-user" | ||
| }, | ||
| "tmax": 1000 | ||
| }, | ||
| "impIDs": [ | ||
| "impression-id" | ||
| ] | ||
| }, | ||
| "mockResponse": { | ||
| "status": 200, | ||
| "body": { | ||
| "id": "resp-id", | ||
| "seatbid": [ | ||
| { | ||
| "bid": [ | ||
| { | ||
| "id": "123456789", | ||
| "impid": "impression-id", | ||
| "price": 2, | ||
| "adm": "adm code", | ||
| "adomain": [ | ||
| "testdomain.com" | ||
| ], | ||
| "crid": "100", | ||
| "w": 320, | ||
| "h": 50, | ||
| "ext": { | ||
| "prebid": { | ||
| "type": "banner" | ||
| } | ||
| } | ||
| } | ||
| ] | ||
| } | ||
| ], | ||
| "cur": "USD" | ||
| } | ||
| } | ||
| } | ||
| ], | ||
| "expectedBidResponses": [ | ||
| { | ||
| "bids": [ | ||
| { | ||
| "bid": { | ||
| "id": "123456789", | ||
| "impid": "impression-id", | ||
| "price": 2, | ||
| "adm": "adm code", | ||
| "adomain": [ | ||
| "testdomain.com" | ||
| ], | ||
| "crid": "100", | ||
| "w": 320, | ||
| "h": 50, | ||
| "ext": { | ||
| "prebid": { | ||
| "type": "banner" | ||
| } | ||
| } | ||
| }, | ||
| "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.
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.