-
Notifications
You must be signed in to change notification settings - Fork 860
New Adapter: targetVideo #4593
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
base: master
Are you sure you want to change the base?
New Adapter: targetVideo #4593
Changes from all commits
d48e042
197d704
85c95b5
192ff51
b5eebc5
e0eac3d
8331306
377a133
4fe67ea
5e5d533
fc2551a
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,49 @@ | ||
| package targetVideo | ||
|
|
||
| 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.BidderTargetVideo, json.RawMessage(validParam)); err != nil { | ||
| t.Errorf("Schema rejected targetVideo 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.BidderTargetVideo, json.RawMessage(invalidParam)); err == nil { | ||
| t.Errorf("Schema allowed unexpected params: %s", invalidParam) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| var validParams = []string{ | ||
| `{"placementId":846}`, | ||
| `{"placementId":"846"}`, | ||
| } | ||
|
|
||
| var invalidParams = []string{ | ||
| `null`, | ||
| `nil`, | ||
| `undefined`, | ||
| `{"placementId": "%9"}`, | ||
| `{"publisherId": "as9""}`, | ||
| `{"placementId": true}`, | ||
| `{"placementId": ""}`, | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,140 @@ | ||
| package targetVideo | ||
|
|
||
| import ( | ||
| "encoding/json" | ||
| "fmt" | ||
| "net/http" | ||
|
|
||
| "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 | ||
| } | ||
|
|
||
| type impExtPrebid struct { | ||
| Prebid *openrtb_ext.ExtImpPrebid `json:"prebid,omitempty"` | ||
| } | ||
|
|
||
| func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { | ||
| totalImps := len(request.Imp) | ||
| errors := make([]error, 0) | ||
| adapterRequests := make([]*adapters.RequestData, 0, totalImps) | ||
|
|
||
| // Split multi-imp request into multiple ad server requests. SRA is currently not recommended. | ||
| for i := 0; i < totalImps; i++ { | ||
| adapterReq, err := a.makeRequest(*request, request.Imp[i]) | ||
| if err != nil { | ||
| errors = append(errors, err) | ||
| continue | ||
| } | ||
| adapterRequests = append(adapterRequests, adapterReq) | ||
| } | ||
|
|
||
| return adapterRequests, errors | ||
| } | ||
|
|
||
| func (a *adapter) makeRequest(request openrtb2.BidRequest, imp openrtb2.Imp) (*adapters.RequestData, error) { | ||
|
Collaborator
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're missing error path test coverage. After you've made the suggested simplifications to this function, please add additional tests to the supplemental folder to cover each of the unmarshal error paths. You can do this by simply sending a mock bid request with the data under consideration malformed or of a mismatched type. |
||
|
|
||
| // For now, this adapter sends one imp per request, but we still | ||
| // iterate over all imps in the request to perform the required | ||
| // imp.ext transformation. | ||
| request.Imp = []openrtb2.Imp{imp} | ||
|
|
||
| for i := range request.Imp { | ||
|
|
||
| var extBidder adapters.ExtImpBidder | ||
| if err := jsonutil.Unmarshal(imp.Ext, &extBidder); err != nil { | ||
| return nil, &errortypes.BadInput{Message: fmt.Sprintf("Invalid ext.bidder")} | ||
| } | ||
| var extImpTargetVideo openrtb_ext.ExtImpTargetVideo | ||
| if err := jsonutil.Unmarshal(extBidder.Bidder, &extImpTargetVideo); err != nil { | ||
| return nil, &errortypes.BadInput{Message: fmt.Sprintf("Placement ID missing")} | ||
| } | ||
| var prebid *openrtb_ext.ExtImpPrebid | ||
| if extBidder.Prebid == nil { | ||
| prebid = &openrtb_ext.ExtImpPrebid{} | ||
| } | ||
| if prebid.StoredRequest == nil { | ||
| prebid.StoredRequest = &openrtb_ext.ExtStoredRequest{} | ||
| } | ||
| prebid.StoredRequest.ID = fmt.Sprintf("%d", extImpTargetVideo.PlacementId) | ||
|
|
||
| ext := impExtPrebid{ | ||
| Prebid: prebid, | ||
| } | ||
|
|
||
| extRaw, err := jsonutil.Marshal(ext) | ||
| if err != nil { | ||
| return nil, &errortypes.BadInput{Message: fmt.Sprintf("error building imp.ext, err: %s", err)} | ||
| } | ||
|
|
||
| request.Imp[i].Ext = extRaw | ||
|
|
||
| } | ||
|
|
||
| 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") | ||
|
|
||
| //fmt.Println("TARGET VIDEO reqJson: ", string(reqJSON)) | ||
|
|
||
| return &adapters.RequestData{ | ||
| Method: "POST", | ||
| Uri: a.endpoint, | ||
| Body: reqJSON, | ||
| Headers: headers, | ||
| ImpIDs: openrtb_ext.GetImpIDs(request.Imp), | ||
| }, nil | ||
| } | ||
|
|
||
| func (a *adapter) MakeBids(bidReq *openrtb2.BidRequest, unused *adapters.RequestData, httpRes *adapters.ResponseData) (*adapters.BidderResponse, []error) { | ||
| if adapters.IsResponseStatusCodeNoContent(httpRes) { | ||
| return nil, nil | ||
| } | ||
| if statusError := adapters.CheckResponseStatusCodeForErrors(httpRes); statusError != nil { | ||
| return nil, []error{statusError} | ||
| } | ||
|
|
||
| bidResp, errResp := prepareBidResponse(httpRes.Body) | ||
| if errResp != nil { | ||
| return nil, []error{errResp} | ||
| } | ||
|
|
||
| br := adapters.NewBidderResponse() | ||
| errs := []error{} | ||
|
|
||
| for _, sb := range bidResp.SeatBid { | ||
| for i := range sb.Bid { | ||
| bid := sb.Bid[i] | ||
| br.Bids = append(br.Bids, &adapters.TypedBid{Bid: &bid, BidType: openrtb_ext.BidTypeVideo}) | ||
| br.Currency = bidResp.Cur | ||
| } | ||
| } | ||
| return br, errs | ||
| } | ||
|
|
||
| func prepareBidResponse(body []byte) (openrtb2.BidResponse, error) { | ||
| var response openrtb2.BidResponse | ||
| if err := jsonutil.Unmarshal(body, &response); err != nil { | ||
| return response, err | ||
| } | ||
| return response, nil | ||
| } | ||
|
|
||
| func Builder(bidderName openrtb_ext.BidderName, cfg config.Adapter, server config.Server) (adapters.Bidder, error) { | ||
| bidder := &adapter{ | ||
| endpoint: cfg.Endpoint, | ||
| } | ||
| return bidder, nil | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| package targetVideo | ||
|
|
||
| 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.BidderTargetVideo, config.Adapter{ | ||
| Endpoint: "http://localhost/pbs"}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}) | ||
|
|
||
| if buildErr != nil { | ||
| t.Fatalf("Builder returned unexpected error %v", buildErr) | ||
| } | ||
|
|
||
| adapterstest.RunJSONBidderTest(t, "targetvideotest", bidder) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,116 @@ | ||
| { | ||
| "mockBidRequest": { | ||
| "id": "test-request-id-video", | ||
| "app": { | ||
| "id": "appID", | ||
| "publisher": { | ||
| "id": "uniq_pub_id" | ||
| } | ||
| }, | ||
| "cur": ["EUR"], | ||
| "imp": [ | ||
| { | ||
| "id": "test-imp-id-video", | ||
| "video": { | ||
| "mimes": ["video/mp4"], | ||
| "w": 640, | ||
| "h": 360 | ||
| }, | ||
| "ext": { | ||
| "bidder": { | ||
| "placementId": "77777" | ||
| } | ||
| } | ||
| } | ||
| ], | ||
| "device": { | ||
| "ua": "test-user-agent" | ||
| } | ||
| }, | ||
| "httpCalls": [ | ||
| { | ||
| "expectedRequest": { | ||
| "headers": { | ||
| "Accept": ["application/json"], | ||
| "Content-Type": ["application/json;charset=utf-8"] | ||
| }, | ||
| "uri": "http://localhost/pbs", | ||
| "body": { | ||
| "id": "test-request-id-video", | ||
| "app": { | ||
| "id": "appID", | ||
| "publisher": { | ||
| "id": "uniq_pub_id" | ||
| } | ||
| }, | ||
| "imp": [ | ||
| { | ||
| "id": "test-imp-id-video", | ||
| "video": { | ||
| "mimes": ["video/mp4"], | ||
| "w": 640, | ||
| "h": 360 | ||
| }, | ||
| "ext": { | ||
| "prebid": { | ||
| "storedrequest": { | ||
| "id": "77777" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| ], | ||
| "device": { | ||
| "ua": "test-user-agent" | ||
| }, | ||
| "cur": ["EUR"] | ||
| }, | ||
| "impIDs":["test-imp-id-video"] | ||
| }, | ||
| "mockResponse": { | ||
| "status": 200, | ||
| "body": { | ||
| "id": "test-request-id-video", | ||
| "seatbid": [ | ||
| { | ||
| "seat": "targetVideo", | ||
| "bid": [ | ||
| { | ||
| "id": "randomID", | ||
| "impid": "test-imp-id-video", | ||
| "price": 5.5, | ||
| "adid": "12345678", | ||
| "adm": "test-imp-id-video", | ||
| "cid": "789", | ||
| "crid": "12345678", | ||
| "h": 360, | ||
| "w": 640 | ||
| } | ||
| ] | ||
| } | ||
| ], | ||
| "cur": "EUR" | ||
| } | ||
| } | ||
| } | ||
| ], | ||
| "expectedBidResponses": [ | ||
| { | ||
| "currency": "EUR", | ||
| "bids" : [{ | ||
| "bid": { | ||
| "id": "randomID", | ||
| "adid": "12345678", | ||
| "impid": "test-imp-id-video", | ||
| "price": 5.5, | ||
| "adm": "test-imp-id-video", | ||
| "crid": "12345678", | ||
| "cid": "789", | ||
| "h": 360, | ||
| "w": 640 | ||
| }, | ||
| "type": "video" | ||
| }] | ||
| } | ||
| ] | ||
| } |
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 add
{"placementId": ""}to invalid params to ensure your regex is correct.