From dcdddfa883df3d65c212cc14c9a4d80762273f7c Mon Sep 17 00:00:00 2001 From: Shubham <127132399+shubhamc-ins@users.noreply.github.com> Date: Wed, 10 Jul 2024 01:13:27 +0530 Subject: [PATCH 01/18] Create a basic insticator adaptor (#3) * init insticator adaptor * update modules * add mediaType for bids * update insticator adaptor with tests * update insticator for test cases * fix test cases * update InstAdapter * update insticator adaptor * fix test cases for adUnitId * update insticator adapter type * Updates - add currency converter support - Add video validation support * remove default plcmt and placement * add more test cases * update for publisher ID * fix tests --- adapters/insticator/insticator.go | 509 ++++++++++++++++++ adapters/insticator/insticator_test.go | 21 + .../exemplary/multi-format.json | 121 +++++ .../insticatortest/exemplary/site-banner.json | 118 ++++ .../insticatortest/exemplary/site-video.json | 130 +++++ .../multi-imp-mixed-validation.json | 133 +++++ .../supplemental/status-not-ok.json | 86 +++ .../supplemental/video-validation-fail.json | 33 ++ adapters/insticator/params_test.go | 51 ++ exchange/adapter_builders.go | 2 + openrtb_ext/bidders.go | 2 + openrtb_ext/imp_insticator.go | 7 + static/bidder-info/insticator.yaml | 19 + static/bidder-params/insticator.json | 19 + 14 files changed, 1251 insertions(+) create mode 100644 adapters/insticator/insticator.go create mode 100644 adapters/insticator/insticator_test.go create mode 100644 adapters/insticator/insticatortest/exemplary/multi-format.json create mode 100644 adapters/insticator/insticatortest/exemplary/site-banner.json create mode 100644 adapters/insticator/insticatortest/exemplary/site-video.json create mode 100644 adapters/insticator/insticatortest/supplemental/multi-imp-mixed-validation.json create mode 100644 adapters/insticator/insticatortest/supplemental/status-not-ok.json create mode 100644 adapters/insticator/insticatortest/supplemental/video-validation-fail.json create mode 100644 adapters/insticator/params_test.go create mode 100644 openrtb_ext/imp_insticator.go create mode 100644 static/bidder-info/insticator.yaml create mode 100644 static/bidder-params/insticator.json diff --git a/adapters/insticator/insticator.go b/adapters/insticator/insticator.go new file mode 100644 index 00000000000..9b1b5066933 --- /dev/null +++ b/adapters/insticator/insticator.go @@ -0,0 +1,509 @@ +package insticator + +import ( + "encoding/json" + "fmt" + "log" + "math" + "net/http" + "reflect" + "strconv" + "strings" + + "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" +) + +// type adapter struct { +// endpoint string +// } + +type Ext struct { + Insticator impInsticatorExt `json:"insticator"` +} + +type insticatorUserExt struct { + Eids []openrtb2.EID `json:"eids,omitempty"` + Data json.RawMessage `json:"data,omitempty"` + Consent string `json:"consent,omitempty"` +} + +type impInsticatorExt struct { + AdUnitId string `json:"adUnitId,omitempty"` + PublisherId string `json:"publisherId,omitempty"` +} + +type adapter struct { + endpoint string +} + +type reqExt struct { + Insticator *reqInsticatorExt `json:"insticator,omitempty"` +} + +type reqInsticatorExt struct { + Caller []InsticatorCaller `json:"caller,omitempty"` +} + +type InsticatorCaller struct { + Name string `json:"name,omitempty"` + Version string `json:"version,omitempty"` +} + +// CALLER Info used to track Prebid Server +// as one of the hops in the request to exchange +var CALLER = InsticatorCaller{"Prebid-Server", "n/a"} + +type bidExt struct { + Insticator bidInsticatorExt `json:"insticator,omitempty"` +} + +type bidInsticatorExt struct { + MediaType string `json:"mediaType,omitempty"` +} + +// Placeholder for the actual openrtb2.Video struct +type Video struct { + W *int `json:"w"` + H *int `json:"h"` + MIMEs []string `json:"mimes"` + Placement int `json:"placement"` + Plcmt int `json:"plcmt"` + MinDuration *int `json:"minduration"` + MaxDuration *int `json:"maxduration"` + Protocols []int `json:"protocols"` + StartDelay *int `json:"startdelay"` + Linearity *int `json:"linearity"` + Skip *int `json:"skip"` + SkipMin *int `json:"skipmin"` + SkipAfter *int `json:"skipafter"` + Sequence *int `json:"sequence"` + Battr []int `json:"battr"` + MaxExtended *int `json:"maxextended"` + MinBitrate *int `json:"minbitrate"` + MaxBitrate *int `json:"maxbitrate"` + PlaybackMethod []int `json:"playbackmethod"` + PlaybackEnd *int `json:"playbackend"` + Delivery []int `json:"delivery"` + Pos *int `json:"pos"` + API []int `json:"api"` +} + +type BadInput struct { + Message string +} + +func (e *BadInput) Error() string { + return e.Message +} + +// Validation functions +func isInteger(value interface{}) bool { + switch v := value.(type) { + case int: + return true + case float64: + return v == float64(int(v)) + case string: + _, err := strconv.Atoi(v) + return err == nil + default: + return false + } +} + +func isArrayOfNums(value interface{}) bool { + switch v := value.(type) { + case []int: + return true + case []float64: + for _, num := range v { + if num != float64(int(num)) { + return false + } + } + return true + case []string: + for _, str := range v { + if _, err := strconv.Atoi(str); err != nil { + return false + } + } + return true + default: + return false + } +} + +// Define valid values +var validLinearity = map[int]bool{1: true} +var validSkip = map[int]bool{0: true, 1: true} +var validPlaybackEnd = map[int]bool{1: true, 2: true, 3: true} +var validPos = map[int]bool{0: true, 1: true, 2: true, 3: true, 4: true, 5: true, 6: true, 7: true} + +// Map parameters to validation functions +var optionalVideoParams = map[string]func(interface{}) bool{ + "minduration": isInteger, + "maxduration": isInteger, + "protocols": isArrayOfNums, + "startdelay": isInteger, + "linearity": func(value interface{}) bool { return isInteger(value) && validLinearity[toInt(value)] }, + "skip": func(value interface{}) bool { return isInteger(value) && validSkip[toInt(value)] }, + "skipmin": isInteger, + "skipafter": isInteger, + "sequence": isInteger, + "battr": isArrayOfNums, + "maxextended": isInteger, + "minbitrate": isInteger, + "maxbitrate": isInteger, + "playbackmethod": isArrayOfNums, + "playbackend": func(value interface{}) bool { return isInteger(value) && validPlaybackEnd[toInt(value)] }, + "delivery": isArrayOfNums, + "pos": func(value interface{}) bool { return isInteger(value) && validPos[toInt(value)] }, + "api": isArrayOfNums, +} + +// Helper function to convert interface to int +func toInt(value interface{}) int { + switch v := value.(type) { + case int: + return v + case float64: + return int(v) + case string: + if i, err := strconv.Atoi(v); err == nil { + return i + } + } + return 0 +} + +// Builder builds a new insticatorance 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 +} + +// getMediaTypeForImp figures out which media type this bid is for +func getMediaTypeForBid(bid *openrtb2.Bid) openrtb_ext.BidType { + switch bid.MType { + case openrtb2.MarkupBanner: + return openrtb_ext.BidTypeBanner + case openrtb2.MarkupVideo: + return openrtb_ext.BidTypeVideo + default: + return openrtb_ext.BidTypeBanner + } +} + +func getBidType(ext bidExt) openrtb_ext.BidType { + if ext.Insticator.MediaType == "video" { + return openrtb_ext.BidTypeVideo + } + + return openrtb_ext.BidTypeBanner +} + +func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { + + log.Printf("IN makeRequests") + + var errs []error + var adapterRequests []*adapters.RequestData + var groupedImps = make(map[string][]openrtb2.Imp) + + // Construct request extension common to all imps + // NOTE: not blocking adapter requests on errors + // since request extension is optional. + reqExt, err := makeReqExt(request) + if err != nil { + errs = append(errs, err) + } + request.Ext = reqExt + + for i := 0; i < len(request.Imp); i++ { + if impCopy, err := makeImps(request.Imp[i]); err == nil { + var impExt Ext + // Populate site.publisher.id from imp extension only once + if request.Site != nil && i == 0 { + populateSitePublisherId(&impCopy, request.Site) + } + + // group together the imp hacing insticator adUnitId. However let's not block request creation. + if err := json.Unmarshal(impCopy.Ext, &impExt); err == nil { + impKey := impExt.Insticator.AdUnitId + + resolvedBidFloor, errFloor := resolveBidFloor(impCopy.BidFloor, impCopy.BidFloorCur, requestInfo) + if errFloor != nil { + errs = append(errs, errFloor) + } else { + if resolvedBidFloor > 0 { + impCopy.BidFloor = resolvedBidFloor + impCopy.BidFloorCur = "USD" + } + } + + groupedImps[impKey] = append(groupedImps[impKey], impCopy) + } else { + errs = append(errs, err) + } + } else { + errs = append(errs, err) + } + } + + for _, impList := range groupedImps { + if adapterReq, err := a.makeRequest(*request, impList); err == nil { + adapterRequests = append(adapterRequests, adapterReq) + } else { + errs = append(errs, err) + } + } + return adapterRequests, errs +} + +func (a *adapter) makeRequest(request openrtb2.BidRequest, impList []openrtb2.Imp) (*adapters.RequestData, error) { + request.Imp = impList + + // Last Step + reqJSON, err := json.Marshal(request) + if err != nil { + return nil, err + } + // log reqJson + // log.Printf("reqJSON Before makerequest: %s", reqJSON) + + headers := http.Header{} + headers.Add("Content-Type", "application/json;charset=utf-8") + + return &adapters.RequestData{ + Method: "POST", + Uri: a.endpoint, + Body: reqJSON, + Headers: headers, + ImpIDs: openrtb_ext.GetImpIDs(request.Imp), + }, nil +} + +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: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info.", responseData.StatusCode), + } + 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 + for _, seatBid := range response.SeatBid { + for i := range seatBid.Bid { + bid := &seatBid.Bid[i] + bidType := getMediaTypeForBid(bid) + b := &adapters.TypedBid{ + Bid: &seatBid.Bid[i], + BidType: bidType, + } + bidResponse.Bids = append(bidResponse.Bids, b) + } + } + return bidResponse, nil +} + +func makeImps(imp openrtb2.Imp) (openrtb2.Imp, error) { + if imp.Banner == nil && imp.Video == nil { + return openrtb2.Imp{}, &errortypes.BadInput{ + Message: fmt.Sprintf("Imp ID %s must have at least one of [Banner, Video] defined", imp.ID), + } + } + + var bidderExt adapters.ExtImpBidder + if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil { + return openrtb2.Imp{}, &errortypes.BadInput{ + Message: err.Error(), + } + } + + var insticatorExt openrtb_ext.ExtImpInsticator + if err := json.Unmarshal(bidderExt.Bidder, &insticatorExt); err != nil { + return openrtb2.Imp{}, &errortypes.BadInput{ + Message: err.Error(), + } + } + + var impExt Ext + impExt.Insticator.AdUnitId = insticatorExt.AdUnitId + impExt.Insticator.PublisherId = insticatorExt.PublisherId + + impExtJSON, err := json.Marshal(impExt) + if err != nil { + return openrtb2.Imp{}, &errortypes.BadInput{ + Message: err.Error(), + } + } + + imp.Ext = impExtJSON + + // Validate Video if it exists + if imp.Video != nil { + videoCopy, err := validateVideoParams(imp.Video) + + imp.Video = videoCopy + + if err != nil { + return openrtb2.Imp{}, &errortypes.BadInput{ + Message: err.Error(), + } + } + } + + return imp, nil +} + +func validateVideoParams(video *openrtb2.Video) (*openrtb2.Video, error) { + videoCopy := *video + if (videoCopy.W == nil || *videoCopy.W == 0) || + (videoCopy.H == nil || *videoCopy.H == 0) || + videoCopy.MIMEs == nil { + + return nil, &errortypes.BadInput{ + Message: "One or more invalid or missing video field(s) w, h, mimes", + } + } + + // Validate optional parameters and remove invalid ones + cleanedVideo, err := validateOptionalVideoParams(&videoCopy) + if err != nil { + return nil, err + } + + return cleanedVideo, nil +} + +func makeReqExt(request *openrtb2.BidRequest) ([]byte, error) { + var reqExt reqExt + + if len(request.Ext) > 0 { + if err := json.Unmarshal(request.Ext, &reqExt); err != nil { + return nil, err + } + } + + if reqExt.Insticator == nil { + reqExt.Insticator = &reqInsticatorExt{} + } + + if reqExt.Insticator.Caller == nil { + reqExt.Insticator.Caller = make([]InsticatorCaller, 0) + } + + reqExt.Insticator.Caller = append(reqExt.Insticator.Caller, CALLER) + + return json.Marshal(reqExt) +} + +func resolveBidFloor(bidFloor float64, bidFloorCur string, reqInfo *adapters.ExtraRequestInfo) (float64, error) { + if bidFloor > 0 && bidFloorCur != "" && strings.ToUpper(bidFloorCur) != "USD" { + floor, err := reqInfo.ConvertCurrency(bidFloor, bidFloorCur, "USD") + return roundTo4Decimals(floor), err + } + + return bidFloor, nil +} + +// roundTo4Decimals function +func roundTo4Decimals(amount float64) float64 { + return math.Round(amount*10000) / 10000 +} + +func validateOptionalVideoParams(video *openrtb2.Video) (*openrtb2.Video, error) { + v := reflect.ValueOf(video).Elem() + t := v.Type() + + for i := 0; i < t.NumField(); i++ { + field := t.Field(i) + fieldValue := v.Field(i) + + // Convert the field name to camelCase for matching in optionalVideoParams map + jsonTag := field.Tag.Get("json") + if jsonTag == "" { + jsonTag = toCamelCase(field.Name) + } + + // Skip fields that are not in optionalVideoParams + validator, exists := optionalVideoParams[jsonTag] + if !exists { + continue + } + + // Check if the field value is zero/nil and skip if true + if isZeroOrNil(fieldValue) { + continue + } + + // Validate the field value + if !validator(fieldValue.Interface()) { + // If invalid, set the field to zero value + fieldValue.Set(reflect.Zero(fieldValue.Type())) + } + } + return video, nil +} + +// Helper function to convert field name to camelCase +func toCamelCase(s string) string { + if s == "" { + return s + } + return strings.ToLower(string(s[0])) + s[1:] +} + +// Helper function to check if a value is zero or nil +func isZeroOrNil(value reflect.Value) bool { + switch value.Kind() { + case reflect.Ptr, reflect.Interface: + return value.IsNil() + case reflect.Slice, reflect.Array: + return value.Len() == 0 + case reflect.Map: + return len(value.MapKeys()) == 0 + default: + return value.IsZero() + } +} + +// populate publisherId to site object from imp extension +func populateSitePublisherId(imp *openrtb2.Imp, site *openrtb2.Site) { + var ext Ext + + if site.Publisher == nil { + site.Publisher = &openrtb2.Publisher{} + log.Printf("Created Publisher object in Site") + } + + if err := json.Unmarshal(imp.Ext, &ext); err == nil { + site.Publisher.ID = ext.Insticator.PublisherId + } else { + log.Printf("Error unmarshalling imp extension: %v", err) + } +} diff --git a/adapters/insticator/insticator_test.go b/adapters/insticator/insticator_test.go new file mode 100644 index 00000000000..e929402b822 --- /dev/null +++ b/adapters/insticator/insticator_test.go @@ -0,0 +1,21 @@ +package insticator + +import ( + "testing" + + "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.BidderInsticator, config.Adapter{ + Endpoint: "https://ex.ingage.tech/v1/prebidserver"}, + config.Server{ExternalUrl: "https://ex.ingage.tech/v1/prebidserver", GvlID: 1, DataCenter: "2"}) + + if buildErr != nil { + t.Fatalf("Builder returned unexpected error %v", buildErr) + } + + adapterstest.RunJSONBidderTest(t, "insticatortest", bidder) +} diff --git a/adapters/insticator/insticatortest/exemplary/multi-format.json b/adapters/insticator/insticatortest/exemplary/multi-format.json new file mode 100644 index 00000000000..9bcf7873e86 --- /dev/null +++ b/adapters/insticator/insticatortest/exemplary/multi-format.json @@ -0,0 +1,121 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "video": { + "w": 728, + "h": 90, + "protocols": [2], + "playbackmethod": [2], + "mimes": ["foo", "bar"] + }, + "ext": { + "bidder": { + "adUnitId": "inview", + "publisherId": "test-publisher-id" + } + } + } + ], + "site": { + "publisher": { + "id": "test-publisher-id" + } + } + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://ex.ingage.tech/v1/prebidserver", + "body": { + "ext": { + "insticator": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, + "id": "test-request-id", + "imp": [ + { + "id":"test-imp-id", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "video": { + "w": 728, + "h": 90, + "protocols": [2], + "playbackmethod": [2], + "mimes": ["foo", "bar"] + }, + "ext": { + "insticator": { + "adUnitId": "inview", + "publisherId": "test-publisher-id" + } + } + } + ], + "site": { + "publisher": { + "id": "test-publisher-id" + } + } + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "insticator", + "bid": [{ + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.500000, + "adm": "some-test-ad", + "crid": "crid_10", + "h": 90, + "w": 728 + }] + } + ], + "cur": "USD" + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.5, + "adm": "some-test-ad", + "crid": "crid_10", + "w": 728, + "h": 90 + }, + "type": "banner" + } + ] + } + ] + } + \ No newline at end of file diff --git a/adapters/insticator/insticatortest/exemplary/site-banner.json b/adapters/insticator/insticatortest/exemplary/site-banner.json new file mode 100644 index 00000000000..783bcf4dec2 --- /dev/null +++ b/adapters/insticator/insticatortest/exemplary/site-banner.json @@ -0,0 +1,118 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "bidder": { + "adUnitId": "fake-site-id", + "publisherId": "test-publisher-id" + } + } + } + ], + "site": { + "publisher": { + "id": "test-publisher-id" + } + } + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://ex.ingage.tech/v1/prebidserver", + "body": { + "ext": { + "insticator": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, + "id": "test-request-id", + "imp": [ + { + "id":"test-imp-id", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "insticator": { + "adUnitId": "fake-site-id", + "publisherId": "test-publisher-id" + } + } + } + ], + "site": { + "publisher": { + "id": "test-publisher-id" + } + } + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "insticator", + "bid": [{ + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.500000, + "adm": "some-test-ad", + "crid": "crid_10", + "h": 90, + "w": 728, + "mtype": 1, + "ext": { + "insticator": { + "mediaType": "banner" + } + } + }] + } + ], + "cur": "USD" + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.5, + "adm": "some-test-ad", + "crid": "crid_10", + "w": 728, + "h": 90, + "mtype": 1, + "ext": { + "insticator": { + "mediaType": "banner" + } + } + }, + "type": "banner" + } + ] + } + ] +} diff --git a/adapters/insticator/insticatortest/exemplary/site-video.json b/adapters/insticator/insticatortest/exemplary/site-video.json new file mode 100644 index 00000000000..7ed9f846a02 --- /dev/null +++ b/adapters/insticator/insticatortest/exemplary/site-video.json @@ -0,0 +1,130 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "w": 728, + "h": 90, + "protocols": [2], + "placement": 1, + "startdelay": -2, + "playbackmethod": [2], + "mimes": ["foo", "bar"] + }, + "ext": { + "bidder": { + "adUnitId": "fake-site-id", + "publisherId": "test-publisher-id" + } + } + } + ], + "site": { + "publisher": { + "id": "test-publisher-id" + } + } + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://ex.ingage.tech/v1/prebidserver", + "body": { + "ext": { + "insticator": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, + "id": "test-request-id", + "imp": [ + { + "id":"test-imp-id", + "video": { + "w": 728, + "h": 90, + "protocols": [2], + "placement": 1, + "startdelay": -2, + "playbackmethod": [2], + "mimes": ["foo", "bar"] + }, + "ext": { + "insticator": { + "adUnitId": "fake-site-id", + "publisherId": "test-publisher-id" + } + } + } + ], + "site": { + "publisher": { + "id": "test-publisher-id" + } + } + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "insticator", + "bid": [{ + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.500000, + "adm": "some-test-vast-ad", + "mtype": 2, + "crid": "crid_10", + "h": 90, + "w": 728, + "ext": { + "insticator": { + "mediaType": "video" + } + } + }] + } + ], + "cur": "USD" + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.5, + "adm": "some-test-vast-ad", + "crid": "crid_10", + "w": 728, + "mtype": 2, + "h": 90, + "ext": { + "insticator": { + "mediaType": "video" + } + } + }, + "type": "video" + } + ] + } + ] +} diff --git a/adapters/insticator/insticatortest/supplemental/multi-imp-mixed-validation.json b/adapters/insticator/insticatortest/supplemental/multi-imp-mixed-validation.json new file mode 100644 index 00000000000..6f6cc5e3545 --- /dev/null +++ b/adapters/insticator/insticatortest/supplemental/multi-imp-mixed-validation.json @@ -0,0 +1,133 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id1", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "bidder": { + "adUnitId": "fake-site-id", + "publisherId": "test-publisher-id" + } + } + }, + { + "id": "test-imp-id2", + "ext": { + "bidder": { + "adUnitId": "fake-site-id", + "publisherId": "test-publisher-id" + } + } + } + ], + "site": { + "publisher": { + "id": "test-publisher-id" + } + } + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://ex.ingage.tech/v1/prebidserver", + "body": { + "ext": { + "insticator": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, + "id": "test-request-id", + "imp": [ + { + "id":"test-imp-id1", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "insticator": { + "adUnitId": "fake-site-id", + "publisherId": "test-publisher-id" + } + } + } + ], + "site": { + "publisher": { + "id": "test-publisher-id" + } + } + }, + "impIDs":["test-imp-id1"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "insticator", + "bid": [{ + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id1", + "price": 0.500000, + "adm": "some-test-ad", + "crid": "crid_10", + "h": 90, + "w": 728, + "mtype": 1, + "ext": { + "insticator": { + "mediaType": "banner" + } + } + }] + } + ], + "cur": "USD" + } + } + } + ], + "expectedMakeRequestsErrors": [ + { + "value": "Imp ID test-imp-id2 must have at least one of [Banner, Video] defined", + "comparison": "literal" + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id1", + "price": 0.5, + "adm": "some-test-ad", + "crid": "crid_10", + "w": 728, + "h": 90, + "mtype": 1, + "ext": { + "insticator": { + "mediaType": "banner" + } + } + }, + "type": "banner" + } + ] + } + ] + } + \ No newline at end of file diff --git a/adapters/insticator/insticatortest/supplemental/status-not-ok.json b/adapters/insticator/insticatortest/supplemental/status-not-ok.json new file mode 100644 index 00000000000..814e2eeff2c --- /dev/null +++ b/adapters/insticator/insticatortest/supplemental/status-not-ok.json @@ -0,0 +1,86 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "bidder": { + "adUnitId": "fake-invalid-site-id", + "publisherId": "test-publisher-id" + } + } + } + ], + "site": { + "publisher": { + "id": "test-publisher-id" + } + } + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://ex.ingage.tech/v1/prebidserver", + "body": { + "ext": { + "insticator": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, + "id": "test-request-id", + "imp": [ + { + "id":"test-imp-id", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "insticator": { + "adUnitId": "fake-invalid-site-id", + "publisherId": "test-publisher-id" + } + } + } + ], + "site": { + "publisher": { + "id": "test-publisher-id" + } + } + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 400, + "body": { + "error": { + "message": "Validation failed", + "details": [ + { + "message": "site.id is invalid" + } + ] + } + } + } + } + ], + + "expectedMakeBidsErrors": [ + { + "value": "Unexpected status code: 400. Run with request.debug = 1 for more info.", + "comparison": "literal" + } + ] + } + \ No newline at end of file diff --git a/adapters/insticator/insticatortest/supplemental/video-validation-fail.json b/adapters/insticator/insticatortest/supplemental/video-validation-fail.json new file mode 100644 index 00000000000..553b0f68c67 --- /dev/null +++ b/adapters/insticator/insticatortest/supplemental/video-validation-fail.json @@ -0,0 +1,33 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "w": 728, + "h": 90 + }, + "ext": { + "bidder": { + "adUnitId": "fake-site-id", + "publisherId": "test-publisher-id" + } + } + } + ], + "site": { + "publisher": { + "id": "test-publisher-id" + } + } + }, + + "expectedMakeRequestsErrors": [ + { + "value": "One or more invalid or missing video field(s) w, h, mimes", + "comparison": "literal" + } + ] + } + \ No newline at end of file diff --git a/adapters/insticator/params_test.go b/adapters/insticator/params_test.go new file mode 100644 index 00000000000..ba4465ea4a3 --- /dev/null +++ b/adapters/insticator/params_test.go @@ -0,0 +1,51 @@ +package insticator + +import ( + "encoding/json" + "testing" + + "github.com/prebid/prebid-server/v2/openrtb_ext" +) + +// This file actually intends to test static/bidder-params/Insticator.json +// +// These also validate the format of the external API: request.imp[i].ext.prebid.bidder.Insticator + +// TestValidParams makes sure that the Insticator schema accepts all imp.ext fields which we intend to support. +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.BidderInsticator, json.RawMessage(validParam)); err != nil { + t.Errorf("Schema rejected Insticator params: %s", validParam) + } + } +} + +// TestInvalidParams makes sure that the Insticator schema rejects all the imp.ext fields we don't support. +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.BidderInsticator, json.RawMessage(invalidParam)); err == nil { + t.Errorf("Schema allowed unexpected params: %s", invalidParam) + } + } +} + +var validParams = []string{ + `{"publisherId": "inview", "adUnitId": "fakesiteid1"}`, + `{"publisherId": "siab", "adUnitId": "fakesiteid2"}`, + `{"publisherId": "inview", "adUnitId": "foo.ba"}`, +} + +var invalidParams = []string{ + `{"publisherId": "inview"}`, + `{"publisherId": 123, "adUnitId": "fakesiteid2"}`, +} diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go index fdbc0dbf213..5c1738073ea 100755 --- a/exchange/adapter_builders.go +++ b/exchange/adapter_builders.go @@ -103,6 +103,7 @@ import ( "github.com/prebid/prebid-server/v2/adapters/improvedigital" "github.com/prebid/prebid-server/v2/adapters/infytv" "github.com/prebid/prebid-server/v2/adapters/inmobi" + "github.com/prebid/prebid-server/v2/adapters/insticator" "github.com/prebid/prebid-server/v2/adapters/interactiveoffers" "github.com/prebid/prebid-server/v2/adapters/invibes" "github.com/prebid/prebid-server/v2/adapters/iqx" @@ -320,6 +321,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder { openrtb_ext.BidderImprovedigital: improvedigital.Builder, openrtb_ext.BidderInfyTV: infytv.Builder, openrtb_ext.BidderInMobi: inmobi.Builder, + openrtb_ext.BidderInsticator: insticator.Builder, openrtb_ext.BidderInteractiveoffers: interactiveoffers.Builder, openrtb_ext.BidderInvibes: invibes.Builder, openrtb_ext.BidderIQX: iqx.Builder, diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go index 5af05d90b6f..282fb314947 100644 --- a/openrtb_ext/bidders.go +++ b/openrtb_ext/bidders.go @@ -120,6 +120,7 @@ var coreBidderNames []BidderName = []BidderName{ BidderImprovedigital, BidderInfyTV, BidderInMobi, + BidderInsticator, BidderInteractiveoffers, BidderInvibes, BidderIQX, @@ -436,6 +437,7 @@ const ( BidderImprovedigital BidderName = "improvedigital" BidderInfyTV BidderName = "infytv" BidderInMobi BidderName = "inmobi" + BidderInsticator BidderName = "insticator" BidderInteractiveoffers BidderName = "interactiveoffers" BidderInvibes BidderName = "invibes" BidderIQX BidderName = "iqx" diff --git a/openrtb_ext/imp_insticator.go b/openrtb_ext/imp_insticator.go new file mode 100644 index 00000000000..cb33223dfec --- /dev/null +++ b/openrtb_ext/imp_insticator.go @@ -0,0 +1,7 @@ +package openrtb_ext + +// ExtImpInsticator defines the contract for bidrequest.imp[i].ext.prebid.bidder.insticator +type ExtImpInsticator struct { + AdUnitId string `json:"adUnitId,omitempty"` + PublisherId string `json:"publisherId,omitempty"` +} diff --git a/static/bidder-info/insticator.yaml b/static/bidder-info/insticator.yaml new file mode 100644 index 00000000000..e9e6651433a --- /dev/null +++ b/static/bidder-info/insticator.yaml @@ -0,0 +1,19 @@ +endpoint: "http://ex.hunchme.com/v1/prebidserver?debug=true" +geoscope: + - global +maintainer: + email: "predid@insticator.com" +gvlVendorID: 910 +capabilities: + app: + mediaTypes: + - banner + - video + site: + mediaTypes: + - banner + - video +userSync: + iframe: + url: "https://usync.hunchme.com?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect={{.RedirectURL}}" + userMacro: "" \ No newline at end of file diff --git a/static/bidder-params/insticator.json b/static/bidder-params/insticator.json new file mode 100644 index 00000000000..586a6e2c83f --- /dev/null +++ b/static/bidder-params/insticator.json @@ -0,0 +1,19 @@ + +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Insticator Adapter Params", + "description": "A schema which validates params accepted by Insticator", + + "type": "object", + "properties": { + "adUnitId": { + "type": "string", + "description": "Ad Unit Id" + }, + "publisherId": { + "type": "string", + "description": "Publisher Id" + } + }, + "required": ["adUnitId", "publisherId"] + } \ No newline at end of file From 56feaa02d3cb6685b6836dd2073cd071d090b81d Mon Sep 17 00:00:00 2001 From: Shubham <127132399+shubhamc-ins@users.noreply.github.com> Date: Wed, 10 Jul 2024 02:01:01 +0530 Subject: [PATCH 02/18] Update insticator.yaml --- static/bidder-info/insticator.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/static/bidder-info/insticator.yaml b/static/bidder-info/insticator.yaml index e9e6651433a..0912d647acf 100644 --- a/static/bidder-info/insticator.yaml +++ b/static/bidder-info/insticator.yaml @@ -1,6 +1,8 @@ -endpoint: "http://ex.hunchme.com/v1/prebidserver?debug=true" +endpoint: "https://ex.hunchme.com/v1/prebidserver?debug=true" geoscope: - global +disable: + - false maintainer: email: "predid@insticator.com" gvlVendorID: 910 @@ -16,4 +18,4 @@ capabilities: userSync: iframe: url: "https://usync.hunchme.com?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect={{.RedirectURL}}" - userMacro: "" \ No newline at end of file + userMacro: "" From db6d2c315d0946810f2ca1d767ce09d908ffc351 Mon Sep 17 00:00:00 2001 From: Shubham <127132399+shubhamc-ins@users.noreply.github.com> Date: Wed, 10 Jul 2024 20:54:59 +0530 Subject: [PATCH 03/18] add multi-imps testJson (#6) --- adapters/insticator/insticator.go | 27 +- .../insticatortest/exemplary/multi-imps.json | 329 ++++++++++++++++++ 2 files changed, 346 insertions(+), 10 deletions(-) create mode 100644 adapters/insticator/insticatortest/exemplary/multi-imps.json diff --git a/adapters/insticator/insticator.go b/adapters/insticator/insticator.go index 9b1b5066933..c1d421fb9bd 100644 --- a/adapters/insticator/insticator.go +++ b/adapters/insticator/insticator.go @@ -211,19 +211,15 @@ func getBidType(ext bidExt) openrtb_ext.BidType { func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { - log.Printf("IN makeRequests") - var errs []error var adapterRequests []*adapters.RequestData var groupedImps = make(map[string][]openrtb2.Imp) - // Construct request extension common to all imps - // NOTE: not blocking adapter requests on errors - // since request extension is optional. reqExt, err := makeReqExt(request) if err != nil { errs = append(errs, err) } + request.Ext = reqExt for i := 0; i < len(request.Imp); i++ { @@ -270,16 +266,29 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapte func (a *adapter) makeRequest(request openrtb2.BidRequest, impList []openrtb2.Imp) (*adapters.RequestData, error) { request.Imp = impList - // Last Step reqJSON, err := json.Marshal(request) if err != nil { return nil, err } - // log reqJson - // log.Printf("reqJSON Before makerequest: %s", reqJSON) headers := http.Header{} headers.Add("Content-Type", "application/json;charset=utf-8") + headers.Add("Accept", "application/json") + + if request.Device != nil { + if len(request.Device.UA) > 0 { + headers.Add("User-Agent", request.Device.UA) + } + + if len(request.Device.IPv6) > 0 { + headers.Add("X-Forwarded-For", request.Device.IPv6) + } + + if len(request.Device.IP) > 0 { + headers.Add("X-Forwarded-For", request.Device.IP) + headers.Add("IP", request.Device.IP) + } + } return &adapters.RequestData{ Method: "POST", @@ -376,7 +385,6 @@ func makeImps(imp openrtb2.Imp) (openrtb2.Imp, error) { } } } - return imp, nil } @@ -498,7 +506,6 @@ func populateSitePublisherId(imp *openrtb2.Imp, site *openrtb2.Site) { if site.Publisher == nil { site.Publisher = &openrtb2.Publisher{} - log.Printf("Created Publisher object in Site") } if err := json.Unmarshal(imp.Ext, &ext); err == nil { diff --git a/adapters/insticator/insticatortest/exemplary/multi-imps.json b/adapters/insticator/insticatortest/exemplary/multi-imps.json new file mode 100644 index 00000000000..9d311c16acd --- /dev/null +++ b/adapters/insticator/insticatortest/exemplary/multi-imps.json @@ -0,0 +1,329 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id1", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "bidder": { + "adUnitId": "inview", + "publisherId": "test-publisher-id" + } + } + }, + { + "id": "test-imp-id2", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "bidder": { + "adUnitId": "inview", + "publisherId": "test-publisher-id" + } + } + }, + { + "id": "test-imp-id3", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "bidder": { + "adUnitId": "inview", + "publisherId": "test-publisher-id" + } + } + }, + { + "id": "test-imp-id4", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "bidder": { + "adUnitId": "siab", + "publisherId": "test-publisher-id" + } + } + } + ], + "site": { + "publisher": { + "id": "test-publisher-id" + } + } + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://ex.ingage.tech/v1/prebidserver", + "body": { + "ext": { + "insticator": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, + "id": "test-request-id", + "imp": [ + { + "id":"test-imp-id1", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "insticator": { + "adUnitId": "inview", + "publisherId": "test-publisher-id" + } + } + }, + { + "id":"test-imp-id2", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "insticator": { + "adUnitId": "inview", + "publisherId": "test-publisher-id" + } + } + }, + { + "id":"test-imp-id3", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "insticator": { + "adUnitId": "inview", + "publisherId": "test-publisher-id" + } + } + } + ], + "site": { + "publisher": { + "id": "test-publisher-id" + } + } + }, + "impIDs":["test-imp-id1","test-imp-id2", "test-imp-id3"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "insticator", + "bid": [ + { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id1", + "price": 0.500000, + "adm": "some-test-ad", + "crid": "crid_10", + "h": 90, + "w": 728, + "ext": { + "insticator": { + "mediaType": "banner" + } + } + }, + { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id2", + "price": 0.600000, + "adm": "some-test-ad", + "crid": "crid_10", + "h": 90, + "w": 728, + "ext": { + "insticator": { + "mediaType": "banner" + } + } + }, + { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id3", + "price": 0.500000, + "adm": "some-test-ad", + "crid": "crid_10", + "h": 90, + "w": 728, + "ext": { + "insticator": { + "mediaType": "banner" + } + } + } + ] + } + ], + "cur": "USD" + } + } + }, + { + "expectedRequest": { + "uri": "https://ex.ingage.tech/v1/prebidserver", + "body": { + "ext": { + "insticator": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, + "id": "test-request-id", + "imp": [ + { + "id":"test-imp-id4", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "insticator": { + "adUnitId": "siab", + "publisherId": "test-publisher-id" + } + } + } + ], + "site": { + "publisher": { + "id": "test-publisher-id" + } + } + }, + "impIDs":["test-imp-id4"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "insticator", + "bid": [ + { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id4", + "price": 0.500000, + "adm": "some-test-ad", + "crid": "crid_10", + "h": 90, + "w": 728, + "ext": { + "insticator": { + "mediaType": "banner" + } + } + } + ] + } + ], + "cur": "USD" + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id1", + "price": 0.5, + "adm": "some-test-ad", + "crid": "crid_10", + "w": 728, + "h": 90, + "ext": { + "insticator": { + "mediaType": "banner" + } + } + }, + "type": "banner" + }, + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id2", + "price": 0.6, + "adm": "some-test-ad", + "crid": "crid_10", + "w": 728, + "h": 90, + "ext": { + "insticator": { + "mediaType": "banner" + } + } + }, + "type": "banner" + }, + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id3", + "price": 0.5, + "adm": "some-test-ad", + "crid": "crid_10", + "w": 728, + "h": 90, + "ext": { + "insticator": { + "mediaType": "banner" + } + } + }, + "type": "banner" + } + ] + }, + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id4", + "price": 0.5, + "adm": "some-test-ad", + "crid": "crid_10", + "w": 728, + "h": 90, + "ext": { + "insticator": { + "mediaType": "banner" + } + } + }, + "type": "banner" + } + ] + } + ] + } + \ No newline at end of file From b751ff9d37a191bad4e98836f843c5f741c3d674 Mon Sep 17 00:00:00 2001 From: Shubham <127132399+shubhamc-ins@users.noreply.github.com> Date: Wed, 10 Jul 2024 23:38:55 +0530 Subject: [PATCH 04/18] Instissp 790 create a basic insticator go lang adapter new (#7) * add multi-imps testJson * fix pubId parsing for request --- adapters/insticator/insticator.go | 28 ++-- .../insticatortest/exemplary/app-banner.json | 119 ++++++++++++++++ .../insticatortest/exemplary/app-video.json | 131 ++++++++++++++++++ 3 files changed, 269 insertions(+), 9 deletions(-) create mode 100644 adapters/insticator/insticatortest/exemplary/app-banner.json create mode 100644 adapters/insticator/insticatortest/exemplary/app-video.json diff --git a/adapters/insticator/insticator.go b/adapters/insticator/insticator.go index c1d421fb9bd..2f7c10e3246 100644 --- a/adapters/insticator/insticator.go +++ b/adapters/insticator/insticator.go @@ -227,7 +227,9 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapte var impExt Ext // Populate site.publisher.id from imp extension only once if request.Site != nil && i == 0 { - populateSitePublisherId(&impCopy, request.Site) + populatePublisherId(&impCopy, request) + } else if request.App != nil && i == 0 { + populatePublisherId(&impCopy, request) } // group together the imp hacing insticator adUnitId. However let's not block request creation. @@ -500,17 +502,25 @@ func isZeroOrNil(value reflect.Value) bool { } } -// populate publisherId to site object from imp extension -func populateSitePublisherId(imp *openrtb2.Imp, site *openrtb2.Site) { +// populate publisherId to site/app object from imp extension +func populatePublisherId(imp *openrtb2.Imp, request *openrtb2.BidRequest) { var ext Ext - if site.Publisher == nil { - site.Publisher = &openrtb2.Publisher{} + if request.Site != nil && request.Site.Publisher == nil { + request.Site.Publisher = &openrtb2.Publisher{} + if err := json.Unmarshal(imp.Ext, &ext); err == nil { + request.Site.Publisher.ID = ext.Insticator.PublisherId + } else { + log.Printf("Error unmarshalling imp extension: %v", err) + } } - if err := json.Unmarshal(imp.Ext, &ext); err == nil { - site.Publisher.ID = ext.Insticator.PublisherId - } else { - log.Printf("Error unmarshalling imp extension: %v", err) + if request.App != nil && request.App.Publisher == nil { + request.App.Publisher = &openrtb2.Publisher{} + if err := json.Unmarshal(imp.Ext, &ext); err == nil { + request.App.Publisher.ID = ext.Insticator.PublisherId + } else { + log.Printf("Error unmarshalling imp extension: %v", err) + } } } diff --git a/adapters/insticator/insticatortest/exemplary/app-banner.json b/adapters/insticator/insticatortest/exemplary/app-banner.json new file mode 100644 index 00000000000..503689a899b --- /dev/null +++ b/adapters/insticator/insticatortest/exemplary/app-banner.json @@ -0,0 +1,119 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "bidder": { + "adUnitId": "fake-site-id", + "publisherId": "test-publisher-id" + } + } + } + ], + "app": { + "publisher": { + "id": "test-publisher-id" + } + } + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://ex.ingage.tech/v1/prebidserver", + "body": { + "ext": { + "insticator": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, + "id": "test-request-id", + "imp": [ + { + "id":"test-imp-id", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "insticator": { + "adUnitId": "fake-site-id", + "publisherId": "test-publisher-id" + } + } + } + ], + "app": { + "publisher": { + "id": "test-publisher-id" + } + } + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "insticator", + "bid": [{ + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.500000, + "adm": "some-test-ad", + "crid": "crid_10", + "h": 90, + "w": 728, + "mtype": 1, + "ext": { + "insticator": { + "mediaType": "banner" + } + } + }] + } + ], + "cur": "USD" + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.5, + "adm": "some-test-ad", + "crid": "crid_10", + "w": 728, + "h": 90, + "mtype": 1, + "ext": { + "insticator": { + "mediaType": "banner" + } + } + }, + "type": "banner" + } + ] + } + ] + } + \ No newline at end of file diff --git a/adapters/insticator/insticatortest/exemplary/app-video.json b/adapters/insticator/insticatortest/exemplary/app-video.json new file mode 100644 index 00000000000..1b68238ff7a --- /dev/null +++ b/adapters/insticator/insticatortest/exemplary/app-video.json @@ -0,0 +1,131 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "w": 728, + "h": 90, + "protocols": [2], + "placement": 1, + "startdelay": -2, + "playbackmethod": [2], + "mimes": ["foo", "bar"] + }, + "ext": { + "bidder": { + "adUnitId": "fake-site-id", + "publisherId": "test-publisher-id" + } + } + } + ], + "app": { + "publisher": { + "id": "test-publisher-id" + } + } + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://ex.ingage.tech/v1/prebidserver", + "body": { + "ext": { + "insticator": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, + "id": "test-request-id", + "imp": [ + { + "id":"test-imp-id", + "video": { + "w": 728, + "h": 90, + "protocols": [2], + "placement": 1, + "startdelay": -2, + "playbackmethod": [2], + "mimes": ["foo", "bar"] + }, + "ext": { + "insticator": { + "adUnitId": "fake-site-id", + "publisherId": "test-publisher-id" + } + } + } + ], + "app": { + "publisher": { + "id": "test-publisher-id" + } + } + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "insticator", + "bid": [{ + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.500000, + "adm": "some-test-vast-ad", + "mtype": 2, + "crid": "crid_10", + "h": 90, + "w": 728, + "ext": { + "insticator": { + "mediaType": "video" + } + } + }] + } + ], + "cur": "USD" + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.5, + "adm": "some-test-vast-ad", + "crid": "crid_10", + "w": 728, + "mtype": 2, + "h": 90, + "ext": { + "insticator": { + "mediaType": "video" + } + } + }, + "type": "video" + } + ] + } + ] + } + \ No newline at end of file From 92e859af6b9c9d7714ddad970afec41e93adc272 Mon Sep 17 00:00:00 2001 From: shubhamc-ins Date: Wed, 10 Jul 2024 23:53:00 +0530 Subject: [PATCH 05/18] update insticator yaml --- static/bidder-info/insticator.yaml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/static/bidder-info/insticator.yaml b/static/bidder-info/insticator.yaml index 0912d647acf..2f93324f6de 100644 --- a/static/bidder-info/insticator.yaml +++ b/static/bidder-info/insticator.yaml @@ -1,8 +1,4 @@ -endpoint: "https://ex.hunchme.com/v1/prebidserver?debug=true" -geoscope: - - global -disable: - - false +endpoint: "https://ex.ingage.tech/v1/prebidserver" maintainer: email: "predid@insticator.com" gvlVendorID: 910 @@ -17,5 +13,5 @@ capabilities: - video userSync: iframe: - url: "https://usync.hunchme.com?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect={{.RedirectURL}}" + url: "https://usync.ingage.tech?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect={{.RedirectURL}}" userMacro: "" From 24d9b3976fab7c8ab0de396e93b8e9ce92bf80c2 Mon Sep 17 00:00:00 2001 From: shubhamc-ins Date: Mon, 12 Aug 2024 19:07:21 +0530 Subject: [PATCH 06/18] update insticator bid adaptor | remove validations | fixed interfaces --- adapters/insticator/insticator.go | 260 ++---------------- .../multi-imp-mixed-validation.json | 15 - .../supplemental/status-not-ok.json | 2 +- 3 files changed, 24 insertions(+), 253 deletions(-) diff --git a/adapters/insticator/insticator.go b/adapters/insticator/insticator.go index 2f7c10e3246..b8f79cf6e09 100644 --- a/adapters/insticator/insticator.go +++ b/adapters/insticator/insticator.go @@ -2,12 +2,9 @@ package insticator import ( "encoding/json" - "fmt" "log" "math" "net/http" - "reflect" - "strconv" "strings" "github.com/prebid/openrtb/v20/openrtb2" @@ -17,23 +14,13 @@ import ( "github.com/prebid/prebid-server/v2/openrtb_ext" ) -// type adapter struct { -// endpoint string -// } - -type Ext struct { +type ext struct { Insticator impInsticatorExt `json:"insticator"` } -type insticatorUserExt struct { - Eids []openrtb2.EID `json:"eids,omitempty"` - Data json.RawMessage `json:"data,omitempty"` - Consent string `json:"consent,omitempty"` -} - type impInsticatorExt struct { - AdUnitId string `json:"adUnitId,omitempty"` - PublisherId string `json:"publisherId,omitempty"` + AdUnitId string `json:"adUnitId"` + PublisherId string `json:"publisherId"` } type adapter struct { @@ -45,17 +32,17 @@ type reqExt struct { } type reqInsticatorExt struct { - Caller []InsticatorCaller `json:"caller,omitempty"` + Caller []insticatorCaller `json:"caller,omitempty"` } -type InsticatorCaller struct { +type insticatorCaller struct { Name string `json:"name,omitempty"` Version string `json:"version,omitempty"` } -// CALLER Info used to track Prebid Server +// caller Info used to track Prebid Server // as one of the hops in the request to exchange -var CALLER = InsticatorCaller{"Prebid-Server", "n/a"} +var caller = insticatorCaller{"Prebid-Server", "n/a"} type bidExt struct { Insticator bidInsticatorExt `json:"insticator,omitempty"` @@ -65,122 +52,6 @@ type bidInsticatorExt struct { MediaType string `json:"mediaType,omitempty"` } -// Placeholder for the actual openrtb2.Video struct -type Video struct { - W *int `json:"w"` - H *int `json:"h"` - MIMEs []string `json:"mimes"` - Placement int `json:"placement"` - Plcmt int `json:"plcmt"` - MinDuration *int `json:"minduration"` - MaxDuration *int `json:"maxduration"` - Protocols []int `json:"protocols"` - StartDelay *int `json:"startdelay"` - Linearity *int `json:"linearity"` - Skip *int `json:"skip"` - SkipMin *int `json:"skipmin"` - SkipAfter *int `json:"skipafter"` - Sequence *int `json:"sequence"` - Battr []int `json:"battr"` - MaxExtended *int `json:"maxextended"` - MinBitrate *int `json:"minbitrate"` - MaxBitrate *int `json:"maxbitrate"` - PlaybackMethod []int `json:"playbackmethod"` - PlaybackEnd *int `json:"playbackend"` - Delivery []int `json:"delivery"` - Pos *int `json:"pos"` - API []int `json:"api"` -} - -type BadInput struct { - Message string -} - -func (e *BadInput) Error() string { - return e.Message -} - -// Validation functions -func isInteger(value interface{}) bool { - switch v := value.(type) { - case int: - return true - case float64: - return v == float64(int(v)) - case string: - _, err := strconv.Atoi(v) - return err == nil - default: - return false - } -} - -func isArrayOfNums(value interface{}) bool { - switch v := value.(type) { - case []int: - return true - case []float64: - for _, num := range v { - if num != float64(int(num)) { - return false - } - } - return true - case []string: - for _, str := range v { - if _, err := strconv.Atoi(str); err != nil { - return false - } - } - return true - default: - return false - } -} - -// Define valid values -var validLinearity = map[int]bool{1: true} -var validSkip = map[int]bool{0: true, 1: true} -var validPlaybackEnd = map[int]bool{1: true, 2: true, 3: true} -var validPos = map[int]bool{0: true, 1: true, 2: true, 3: true, 4: true, 5: true, 6: true, 7: true} - -// Map parameters to validation functions -var optionalVideoParams = map[string]func(interface{}) bool{ - "minduration": isInteger, - "maxduration": isInteger, - "protocols": isArrayOfNums, - "startdelay": isInteger, - "linearity": func(value interface{}) bool { return isInteger(value) && validLinearity[toInt(value)] }, - "skip": func(value interface{}) bool { return isInteger(value) && validSkip[toInt(value)] }, - "skipmin": isInteger, - "skipafter": isInteger, - "sequence": isInteger, - "battr": isArrayOfNums, - "maxextended": isInteger, - "minbitrate": isInteger, - "maxbitrate": isInteger, - "playbackmethod": isArrayOfNums, - "playbackend": func(value interface{}) bool { return isInteger(value) && validPlaybackEnd[toInt(value)] }, - "delivery": isArrayOfNums, - "pos": func(value interface{}) bool { return isInteger(value) && validPos[toInt(value)] }, - "api": isArrayOfNums, -} - -// Helper function to convert interface to int -func toInt(value interface{}) int { - switch v := value.(type) { - case int: - return v - case float64: - return int(v) - case string: - if i, err := strconv.Atoi(v); err == nil { - return i - } - } - return 0 -} - // Builder builds a new insticatorance 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{ @@ -201,14 +72,6 @@ func getMediaTypeForBid(bid *openrtb2.Bid) openrtb_ext.BidType { } } -func getBidType(ext bidExt) openrtb_ext.BidType { - if ext.Insticator.MediaType == "video" { - return openrtb_ext.BidTypeVideo - } - - return openrtb_ext.BidTypeBanner -} - func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { var errs []error @@ -224,7 +87,7 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapte for i := 0; i < len(request.Imp); i++ { if impCopy, err := makeImps(request.Imp[i]); err == nil { - var impExt Ext + var impExt ext // Populate site.publisher.id from imp extension only once if request.Site != nil && i == 0 { populatePublisherId(&impCopy, request) @@ -302,21 +165,11 @@ func (a *adapter) makeRequest(request openrtb2.BidRequest, impList []openrtb2.Im } func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) { - if responseData.StatusCode == http.StatusNoContent { + if adapters.IsResponseStatusCodeNoContent(responseData) { return nil, nil } - if responseData.StatusCode == http.StatusBadRequest { - err := &errortypes.BadInput{ - Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info.", responseData.StatusCode), - } - 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), - } + if err := adapters.CheckResponseStatusCodeForErrors(responseData); err != nil { return nil, []error{err} } @@ -342,11 +195,6 @@ func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.R } func makeImps(imp openrtb2.Imp) (openrtb2.Imp, error) { - if imp.Banner == nil && imp.Video == nil { - return openrtb2.Imp{}, &errortypes.BadInput{ - Message: fmt.Sprintf("Imp ID %s must have at least one of [Banner, Video] defined", imp.ID), - } - } var bidderExt adapters.ExtImpBidder if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil { @@ -362,7 +210,7 @@ func makeImps(imp openrtb2.Imp) (openrtb2.Imp, error) { } } - var impExt Ext + var impExt ext impExt.Insticator.AdUnitId = insticatorExt.AdUnitId impExt.Insticator.PublisherId = insticatorExt.PublisherId @@ -374,7 +222,6 @@ func makeImps(imp openrtb2.Imp) (openrtb2.Imp, error) { } imp.Ext = impExtJSON - // Validate Video if it exists if imp.Video != nil { videoCopy, err := validateVideoParams(imp.Video) @@ -387,27 +234,8 @@ func makeImps(imp openrtb2.Imp) (openrtb2.Imp, error) { } } } - return imp, nil -} - -func validateVideoParams(video *openrtb2.Video) (*openrtb2.Video, error) { - videoCopy := *video - if (videoCopy.W == nil || *videoCopy.W == 0) || - (videoCopy.H == nil || *videoCopy.H == 0) || - videoCopy.MIMEs == nil { - - return nil, &errortypes.BadInput{ - Message: "One or more invalid or missing video field(s) w, h, mimes", - } - } - - // Validate optional parameters and remove invalid ones - cleanedVideo, err := validateOptionalVideoParams(&videoCopy) - if err != nil { - return nil, err - } - return cleanedVideo, nil + return imp, nil } func makeReqExt(request *openrtb2.BidRequest) ([]byte, error) { @@ -424,10 +252,10 @@ func makeReqExt(request *openrtb2.BidRequest) ([]byte, error) { } if reqExt.Insticator.Caller == nil { - reqExt.Insticator.Caller = make([]InsticatorCaller, 0) + reqExt.Insticator.Caller = make([]insticatorCaller, 0) } - reqExt.Insticator.Caller = append(reqExt.Insticator.Caller, CALLER) + reqExt.Insticator.Caller = append(reqExt.Insticator.Caller, caller) return json.Marshal(reqExt) } @@ -446,65 +274,23 @@ func roundTo4Decimals(amount float64) float64 { return math.Round(amount*10000) / 10000 } -func validateOptionalVideoParams(video *openrtb2.Video) (*openrtb2.Video, error) { - v := reflect.ValueOf(video).Elem() - t := v.Type() - - for i := 0; i < t.NumField(); i++ { - field := t.Field(i) - fieldValue := v.Field(i) - - // Convert the field name to camelCase for matching in optionalVideoParams map - jsonTag := field.Tag.Get("json") - if jsonTag == "" { - jsonTag = toCamelCase(field.Name) - } - - // Skip fields that are not in optionalVideoParams - validator, exists := optionalVideoParams[jsonTag] - if !exists { - continue - } - - // Check if the field value is zero/nil and skip if true - if isZeroOrNil(fieldValue) { - continue - } +func validateVideoParams(video *openrtb2.Video) (*openrtb2.Video, error) { + videoCopy := *video + if (videoCopy.W == nil || *videoCopy.W == 0) || + (videoCopy.H == nil || *videoCopy.H == 0) || + videoCopy.MIMEs == nil { - // Validate the field value - if !validator(fieldValue.Interface()) { - // If invalid, set the field to zero value - fieldValue.Set(reflect.Zero(fieldValue.Type())) + return nil, &errortypes.BadInput{ + Message: "One or more invalid or missing video field(s) w, h, mimes", } } - return video, nil -} -// Helper function to convert field name to camelCase -func toCamelCase(s string) string { - if s == "" { - return s - } - return strings.ToLower(string(s[0])) + s[1:] -} - -// Helper function to check if a value is zero or nil -func isZeroOrNil(value reflect.Value) bool { - switch value.Kind() { - case reflect.Ptr, reflect.Interface: - return value.IsNil() - case reflect.Slice, reflect.Array: - return value.Len() == 0 - case reflect.Map: - return len(value.MapKeys()) == 0 - default: - return value.IsZero() - } + return &videoCopy, nil } // populate publisherId to site/app object from imp extension func populatePublisherId(imp *openrtb2.Imp, request *openrtb2.BidRequest) { - var ext Ext + var ext ext if request.Site != nil && request.Site.Publisher == nil { request.Site.Publisher = &openrtb2.Publisher{} diff --git a/adapters/insticator/insticatortest/supplemental/multi-imp-mixed-validation.json b/adapters/insticator/insticatortest/supplemental/multi-imp-mixed-validation.json index 6f6cc5e3545..81ec46e84d5 100644 --- a/adapters/insticator/insticatortest/supplemental/multi-imp-mixed-validation.json +++ b/adapters/insticator/insticatortest/supplemental/multi-imp-mixed-validation.json @@ -13,15 +13,6 @@ "publisherId": "test-publisher-id" } } - }, - { - "id": "test-imp-id2", - "ext": { - "bidder": { - "adUnitId": "fake-site-id", - "publisherId": "test-publisher-id" - } - } } ], "site": { @@ -98,12 +89,6 @@ } } ], - "expectedMakeRequestsErrors": [ - { - "value": "Imp ID test-imp-id2 must have at least one of [Banner, Video] defined", - "comparison": "literal" - } - ], "expectedBidResponses": [ { "currency": "USD", diff --git a/adapters/insticator/insticatortest/supplemental/status-not-ok.json b/adapters/insticator/insticatortest/supplemental/status-not-ok.json index 814e2eeff2c..e2778985e11 100644 --- a/adapters/insticator/insticatortest/supplemental/status-not-ok.json +++ b/adapters/insticator/insticatortest/supplemental/status-not-ok.json @@ -78,7 +78,7 @@ "expectedMakeBidsErrors": [ { - "value": "Unexpected status code: 400. Run with request.debug = 1 for more info.", + "value": "Unexpected status code: 400. Run with request.debug = 1 for more info", "comparison": "literal" } ] From 1f439784433840b069a24f0c4695a4f22819f6fb Mon Sep 17 00:00:00 2001 From: shubhamc-ins Date: Mon, 12 Aug 2024 19:35:16 +0530 Subject: [PATCH 07/18] refactor error checks --- adapters/insticator/insticator.go | 60 ++++++++++++++++--------------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/adapters/insticator/insticator.go b/adapters/insticator/insticator.go index b8f79cf6e09..79f1c9d1ae6 100644 --- a/adapters/insticator/insticator.go +++ b/adapters/insticator/insticator.go @@ -86,36 +86,38 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapte request.Ext = reqExt for i := 0; i < len(request.Imp); i++ { - if impCopy, err := makeImps(request.Imp[i]); err == nil { - var impExt ext - // Populate site.publisher.id from imp extension only once - if request.Site != nil && i == 0 { - populatePublisherId(&impCopy, request) - } else if request.App != nil && i == 0 { - populatePublisherId(&impCopy, request) - } + impCopy, err := makeImps(request.Imp[i]) + if err != nil { + errs = append(errs, err) + continue + } - // group together the imp hacing insticator adUnitId. However let's not block request creation. - if err := json.Unmarshal(impCopy.Ext, &impExt); err == nil { - impKey := impExt.Insticator.AdUnitId - - resolvedBidFloor, errFloor := resolveBidFloor(impCopy.BidFloor, impCopy.BidFloorCur, requestInfo) - if errFloor != nil { - errs = append(errs, errFloor) - } else { - if resolvedBidFloor > 0 { - impCopy.BidFloor = resolvedBidFloor - impCopy.BidFloorCur = "USD" - } - } - - groupedImps[impKey] = append(groupedImps[impKey], impCopy) - } else { - errs = append(errs, err) - } - } else { + var impExt ext + + // Populate site.publisher.id from imp extension + if request.Site != nil || request.App != nil { + populatePublisherId(&impCopy, request) + } + + // Group together the imps having Insticator adUnitId. However, let's not block request creation. + if err := json.Unmarshal(impCopy.Ext, &impExt); err != nil { errs = append(errs, err) + continue + } + + impKey := impExt.Insticator.AdUnitId + + resolvedBidFloor, errFloor := resolveBidFloor(impCopy.BidFloor, impCopy.BidFloorCur, requestInfo) + if errFloor != nil { + errs = append(errs, errFloor) + } else { + if resolvedBidFloor > 0 { + impCopy.BidFloor = resolvedBidFloor + impCopy.BidFloorCur = "USD" + } } + + groupedImps[impKey] = append(groupedImps[impKey], impCopy) } for _, impList := range groupedImps { @@ -179,7 +181,9 @@ func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.R } bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp)) - bidResponse.Currency = response.Cur + if response.Cur != "" { + bidResponse.Currency = response.Cur + } for _, seatBid := range response.SeatBid { for i := range seatBid.Bid { bid := &seatBid.Bid[i] From c5b5e247c3e832b4b4e6de50a4de19937ff30f62 Mon Sep 17 00:00:00 2001 From: shubhamc-ins Date: Thu, 3 Oct 2024 16:09:16 +0530 Subject: [PATCH 08/18] fix email typo --- static/bidder-info/insticator.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/bidder-info/insticator.yaml b/static/bidder-info/insticator.yaml index 2f93324f6de..240345cb06d 100644 --- a/static/bidder-info/insticator.yaml +++ b/static/bidder-info/insticator.yaml @@ -1,6 +1,6 @@ endpoint: "https://ex.ingage.tech/v1/prebidserver" maintainer: - email: "predid@insticator.com" + email: "prebid@insticator.com" gvlVendorID: 910 capabilities: app: From 4dfb854347ad6570c98bb2c48c3e7a30fad943c2 Mon Sep 17 00:00:00 2001 From: shubhamc-ins Date: Wed, 30 Oct 2024 01:06:44 +0530 Subject: [PATCH 09/18] add invalidparams for insticator --- adapters/insticator/params_test.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/adapters/insticator/params_test.go b/adapters/insticator/params_test.go index ba4465ea4a3..fd8682a2f03 100644 --- a/adapters/insticator/params_test.go +++ b/adapters/insticator/params_test.go @@ -46,6 +46,12 @@ var validParams = []string{ } var invalidParams = []string{ - `{"publisherId": "inview"}`, - `{"publisherId": 123, "adUnitId": "fakesiteid2"}`, + `{"publisherId": "inview"}`, // Missing adUnitId + `{"publisherId": 123, "adUnitId": "fakesiteid2"}`, // publisherId should be a string + `{"adUnitId": "fakesiteid3"}`, // Missing publisherId + `{"publisherId": "inview", "adUnitId": 456}`, // adUnitId should be a string + `{"publisherId": null, "adUnitId": "fakesiteid5"}`, // Null publisherId + `{"publisherId": "inview", "adUnitId": null}`, // Null adUnitId + `{"publisherId": true, "adUnitId": "fakesiteid6"}`, // publisherId should be a string, got boolean + `{"publisherId": "inview", "adUnitId": [1, 2, 3]}`, // adUnitId should be a string, got array } From c776f19d11b9e7535f0b4bba01303de6421b08f5 Mon Sep 17 00:00:00 2001 From: shubhamc-ins Date: Mon, 4 Nov 2024 22:07:54 +0530 Subject: [PATCH 10/18] update imports to v3 for insticator --- adapters/insticator/insticator.go | 8 ++++---- adapters/insticator/insticator_test.go | 6 +++--- adapters/insticator/params_test.go | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/adapters/insticator/insticator.go b/adapters/insticator/insticator.go index 79f1c9d1ae6..e659c21d31c 100644 --- a/adapters/insticator/insticator.go +++ b/adapters/insticator/insticator.go @@ -8,10 +8,10 @@ import ( "strings" "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" + "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" ) type ext struct { diff --git a/adapters/insticator/insticator_test.go b/adapters/insticator/insticator_test.go index e929402b822..b34595177b5 100644 --- a/adapters/insticator/insticator_test.go +++ b/adapters/insticator/insticator_test.go @@ -3,9 +3,9 @@ package insticator import ( "testing" - "github.com/prebid/prebid-server/v2/adapters/adapterstest" - "github.com/prebid/prebid-server/v2/config" - "github.com/prebid/prebid-server/v2/openrtb_ext" + "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) { diff --git a/adapters/insticator/params_test.go b/adapters/insticator/params_test.go index fd8682a2f03..47d2bdf44fc 100644 --- a/adapters/insticator/params_test.go +++ b/adapters/insticator/params_test.go @@ -4,7 +4,7 @@ import ( "encoding/json" "testing" - "github.com/prebid/prebid-server/v2/openrtb_ext" + "github.com/prebid/prebid-server/v3/openrtb_ext" ) // This file actually intends to test static/bidder-params/Insticator.json From 46501913437e8e1ca2f0d907c7f09d2bfbdab3c5 Mon Sep 17 00:00:00 2001 From: shubhamc-ins Date: Fri, 8 Nov 2024 04:10:14 +0530 Subject: [PATCH 11/18] use request clone and add macro --- adapters/insticator/insticator.go | 42 ++++++++++++++++++------------ static/bidder-info/insticator.yaml | 2 +- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/adapters/insticator/insticator.go b/adapters/insticator/insticator.go index e659c21d31c..5c14eb8a831 100644 --- a/adapters/insticator/insticator.go +++ b/adapters/insticator/insticator.go @@ -73,7 +73,6 @@ func getMediaTypeForBid(bid *openrtb2.Bid) openrtb_ext.BidType { } func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { - var errs []error var adapterRequests []*adapters.RequestData var groupedImps = make(map[string][]openrtb2.Imp) @@ -85,6 +84,11 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapte request.Ext = reqExt + // Create a deep copy of the request to avoid modifying the original request + requestCopy := *request + requestCopy.Site = request.Site + requestCopy.App = request.App + for i := 0; i < len(request.Imp); i++ { impCopy, err := makeImps(request.Imp[i]) if err != nil { @@ -95,8 +99,8 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapte var impExt ext // Populate site.publisher.id from imp extension - if request.Site != nil || request.App != nil { - populatePublisherId(&impCopy, request) + if requestCopy.Site != nil || requestCopy.App != nil { + populatePublisherId(&impCopy, &requestCopy) } // Group together the imps having Insticator adUnitId. However, let's not block request creation. @@ -121,7 +125,7 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapte } for _, impList := range groupedImps { - if adapterReq, err := a.makeRequest(*request, impList); err == nil { + if adapterReq, err := a.makeRequest(requestCopy, impList); err == nil { adapterRequests = append(adapterRequests, adapterReq) } else { errs = append(errs, err) @@ -292,25 +296,29 @@ func validateVideoParams(video *openrtb2.Video) (*openrtb2.Video, error) { return &videoCopy, nil } -// populate publisherId to site/app object from imp extension +// populatePublisherId function populates site.publisher.id or app.publisher.id func populatePublisherId(imp *openrtb2.Imp, request *openrtb2.BidRequest) { var ext ext - if request.Site != nil && request.Site.Publisher == nil { - request.Site.Publisher = &openrtb2.Publisher{} - if err := json.Unmarshal(imp.Ext, &ext); err == nil { - request.Site.Publisher.ID = ext.Insticator.PublisherId - } else { - log.Printf("Error unmarshalling imp extension: %v", err) + // Unmarshal the imp extension to get the publisher ID + if err := json.Unmarshal(imp.Ext, &ext); err != nil { + log.Printf("Error unmarshalling imp extension: %v", err) + return + } + + // Populate site.publisher.id if request.Site is not nil + if request.Site != nil { + if request.Site.Publisher == nil { + request.Site.Publisher = &openrtb2.Publisher{} } + request.Site.Publisher.ID = ext.Insticator.PublisherId } - if request.App != nil && request.App.Publisher == nil { - request.App.Publisher = &openrtb2.Publisher{} - if err := json.Unmarshal(imp.Ext, &ext); err == nil { - request.App.Publisher.ID = ext.Insticator.PublisherId - } else { - log.Printf("Error unmarshalling imp extension: %v", err) + // Populate app.publisher.id if request.App is not nil + if request.App != nil { + if request.App.Publisher == nil { + request.App.Publisher = &openrtb2.Publisher{} } + request.App.Publisher.ID = ext.Insticator.PublisherId } } diff --git a/static/bidder-info/insticator.yaml b/static/bidder-info/insticator.yaml index 240345cb06d..907ff4a50d1 100644 --- a/static/bidder-info/insticator.yaml +++ b/static/bidder-info/insticator.yaml @@ -14,4 +14,4 @@ capabilities: userSync: iframe: url: "https://usync.ingage.tech?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect={{.RedirectURL}}" - userMacro: "" + userMacro: "$UID" From e3b07a8f6d3da388283e7d5d6ef721c3c4427cdc Mon Sep 17 00:00:00 2001 From: shubhamc-ins Date: Wed, 13 Nov 2024 00:12:48 +0530 Subject: [PATCH 12/18] update insticator adaptor: - fix comments - fix return types - stop the flow, with imp having errors --- adapters/insticator/insticator.go | 48 +++++++++++++++++-------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/adapters/insticator/insticator.go b/adapters/insticator/insticator.go index 5c14eb8a831..4681074cb0f 100644 --- a/adapters/insticator/insticator.go +++ b/adapters/insticator/insticator.go @@ -2,7 +2,7 @@ package insticator import ( "encoding/json" - "log" + "fmt" "math" "net/http" "strings" @@ -52,7 +52,7 @@ type bidInsticatorExt struct { MediaType string `json:"mediaType,omitempty"` } -// Builder builds a new insticatorance of the Foo adapter for the given bidder with the given config. +// Builder builds a new instance of the Insticator adapter with the given config. func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { bidder := &adapter{ endpoint: config.Endpoint, @@ -60,7 +60,7 @@ func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server co return bidder, nil } -// getMediaTypeForImp figures out which media type this bid is for +// getMediaTypeForBid figures out which media type this bid is for func getMediaTypeForBid(bid *openrtb2.Bid) openrtb_ext.BidType { switch bid.MType { case openrtb2.MarkupBanner: @@ -100,7 +100,10 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapte // Populate site.publisher.id from imp extension if requestCopy.Site != nil || requestCopy.App != nil { - populatePublisherId(&impCopy, &requestCopy) + if err := populatePublisherId(&impCopy, &requestCopy); err != nil { + errs = append(errs, err) + continue + } } // Group together the imps having Insticator adUnitId. However, let's not block request creation. @@ -113,7 +116,11 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapte resolvedBidFloor, errFloor := resolveBidFloor(impCopy.BidFloor, impCopy.BidFloorCur, requestInfo) if errFloor != nil { - errs = append(errs, errFloor) + errs = append(errs, &errortypes.BadInput{ + Message: fmt.Sprintf("Error in converting the provided bid floor currency from %s to USD", + impCopy.BidFloorCur), + }) + continue } else { if resolvedBidFloor > 0 { impCopy.BidFloor = resolvedBidFloor @@ -203,7 +210,6 @@ func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.R } func makeImps(imp openrtb2.Imp) (openrtb2.Imp, error) { - var bidderExt adapters.ExtImpBidder if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil { return openrtb2.Imp{}, &errortypes.BadInput{ @@ -218,9 +224,13 @@ func makeImps(imp openrtb2.Imp) (openrtb2.Imp, error) { } } - var impExt ext - impExt.Insticator.AdUnitId = insticatorExt.AdUnitId - impExt.Insticator.PublisherId = insticatorExt.PublisherId + // Directly construct the impExt + impExt := ext{ + Insticator: impInsticatorExt{ + AdUnitId: insticatorExt.AdUnitId, + PublisherId: insticatorExt.PublisherId, + }, + } impExtJSON, err := json.Marshal(impExt) if err != nil { @@ -228,15 +238,11 @@ func makeImps(imp openrtb2.Imp) (openrtb2.Imp, error) { Message: err.Error(), } } - imp.Ext = impExtJSON + // Validate Video if it exists if imp.Video != nil { - videoCopy, err := validateVideoParams(imp.Video) - - imp.Video = videoCopy - - if err != nil { + if err := validateVideoParams(imp.Video); err != nil { return openrtb2.Imp{}, &errortypes.BadInput{ Message: err.Error(), } @@ -282,28 +288,27 @@ func roundTo4Decimals(amount float64) float64 { return math.Round(amount*10000) / 10000 } -func validateVideoParams(video *openrtb2.Video) (*openrtb2.Video, error) { +func validateVideoParams(video *openrtb2.Video) error { videoCopy := *video if (videoCopy.W == nil || *videoCopy.W == 0) || (videoCopy.H == nil || *videoCopy.H == 0) || videoCopy.MIMEs == nil { - return nil, &errortypes.BadInput{ + return &errortypes.BadInput{ Message: "One or more invalid or missing video field(s) w, h, mimes", } } - return &videoCopy, nil + return nil } // populatePublisherId function populates site.publisher.id or app.publisher.id -func populatePublisherId(imp *openrtb2.Imp, request *openrtb2.BidRequest) { +func populatePublisherId(imp *openrtb2.Imp, request *openrtb2.BidRequest) error { var ext ext // Unmarshal the imp extension to get the publisher ID if err := json.Unmarshal(imp.Ext, &ext); err != nil { - log.Printf("Error unmarshalling imp extension: %v", err) - return + return &errortypes.BadInput{Message: "Error unmarshalling imp extension"} } // Populate site.publisher.id if request.Site is not nil @@ -321,4 +326,5 @@ func populatePublisherId(imp *openrtb2.Imp, request *openrtb2.BidRequest) { } request.App.Publisher.ID = ext.Insticator.PublisherId } + return nil } From f31772e6a8cb79568fcbab3999bac97330786c30 Mon Sep 17 00:00:00 2001 From: shubhamc-ins Date: Thu, 14 Nov 2024 23:57:41 +0530 Subject: [PATCH 13/18] refactor- remove unecessary unmarshal --- adapters/insticator/insticator.go | 39 +++++++++++++++++-------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/adapters/insticator/insticator.go b/adapters/insticator/insticator.go index 4681074cb0f..8c556d72752 100644 --- a/adapters/insticator/insticator.go +++ b/adapters/insticator/insticator.go @@ -90,14 +90,12 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapte requestCopy.App = request.App for i := 0; i < len(request.Imp); i++ { - impCopy, err := makeImps(request.Imp[i]) + impCopy, impKey, err := makeImps(request.Imp[i]) if err != nil { errs = append(errs, err) continue } - var impExt ext - // Populate site.publisher.id from imp extension if requestCopy.Site != nil || requestCopy.App != nil { if err := populatePublisherId(&impCopy, &requestCopy); err != nil { @@ -106,14 +104,6 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapte } } - // Group together the imps having Insticator adUnitId. However, let's not block request creation. - if err := json.Unmarshal(impCopy.Ext, &impExt); err != nil { - errs = append(errs, err) - continue - } - - impKey := impExt.Insticator.AdUnitId - resolvedBidFloor, errFloor := resolveBidFloor(impCopy.BidFloor, impCopy.BidFloorCur, requestInfo) if errFloor != nil { errs = append(errs, &errortypes.BadInput{ @@ -209,21 +199,35 @@ func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.R return bidResponse, nil } -func makeImps(imp openrtb2.Imp) (openrtb2.Imp, error) { +func makeImps(imp openrtb2.Imp) (openrtb2.Imp, string, error) { var bidderExt adapters.ExtImpBidder if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil { - return openrtb2.Imp{}, &errortypes.BadInput{ + return openrtb2.Imp{}, "", &errortypes.BadInput{ Message: err.Error(), } } var insticatorExt openrtb_ext.ExtImpInsticator if err := json.Unmarshal(bidderExt.Bidder, &insticatorExt); err != nil { - return openrtb2.Imp{}, &errortypes.BadInput{ + return openrtb2.Imp{}, "", &errortypes.BadInput{ Message: err.Error(), } } + // check if the adUnitId is not empty + if insticatorExt.AdUnitId == "" { + return openrtb2.Imp{}, "", &errortypes.BadInput{ + Message: "Missing adUnitId", + } + } + + // check if the publisherId is not empty + if insticatorExt.PublisherId == "" { + return openrtb2.Imp{}, insticatorExt.AdUnitId, &errortypes.BadInput{ + Message: "Missing publisherId", + } + } + // Directly construct the impExt impExt := ext{ Insticator: impInsticatorExt{ @@ -234,7 +238,7 @@ func makeImps(imp openrtb2.Imp) (openrtb2.Imp, error) { impExtJSON, err := json.Marshal(impExt) if err != nil { - return openrtb2.Imp{}, &errortypes.BadInput{ + return openrtb2.Imp{}, "", &errortypes.BadInput{ Message: err.Error(), } } @@ -243,13 +247,14 @@ func makeImps(imp openrtb2.Imp) (openrtb2.Imp, error) { // Validate Video if it exists if imp.Video != nil { if err := validateVideoParams(imp.Video); err != nil { - return openrtb2.Imp{}, &errortypes.BadInput{ + return openrtb2.Imp{}, insticatorExt.AdUnitId, &errortypes.BadInput{ Message: err.Error(), } } } - return imp, nil + // Return the imp, AdUnitId, and no error + return imp, insticatorExt.AdUnitId, nil } func makeReqExt(request *openrtb2.BidRequest) ([]byte, error) { From 5e78df85dc383e779e61390a6964a89e4b6eb753 Mon Sep 17 00:00:00 2001 From: shubhamc-ins Date: Mon, 18 Nov 2024 06:02:07 +0530 Subject: [PATCH 14/18] insticator updates: - use jsonutil - created mathutil package - using shallow copy to update publisher.id --- adapters/insticator/insticator.go | 73 +++++++++++++--------------- static/bidder-params/insticator.json | 6 ++- util/mathutil/mathutil.go | 9 ++++ 3 files changed, 48 insertions(+), 40 deletions(-) create mode 100644 util/mathutil/mathutil.go diff --git a/adapters/insticator/insticator.go b/adapters/insticator/insticator.go index 8c556d72752..6bfab626d79 100644 --- a/adapters/insticator/insticator.go +++ b/adapters/insticator/insticator.go @@ -1,9 +1,7 @@ package insticator import ( - "encoding/json" "fmt" - "math" "net/http" "strings" @@ -12,6 +10,8 @@ import ( "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" + "github.com/prebid/prebid-server/v3/util/mathutil" ) type ext struct { @@ -86,8 +86,6 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapte // Create a deep copy of the request to avoid modifying the original request requestCopy := *request - requestCopy.Site = request.Site - requestCopy.App = request.App for i := 0; i < len(request.Imp); i++ { impCopy, impKey, err := makeImps(request.Imp[i]) @@ -134,7 +132,7 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapte func (a *adapter) makeRequest(request openrtb2.BidRequest, impList []openrtb2.Imp) (*adapters.RequestData, error) { request.Imp = impList - reqJSON, err := json.Marshal(request) + reqJSON, err := jsonutil.Marshal(request) if err != nil { return nil, err } @@ -177,7 +175,7 @@ func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.R } var response openrtb2.BidResponse - if err := json.Unmarshal(responseData.Body, &response); err != nil { + if err := jsonutil.Unmarshal(responseData.Body, &response); err != nil { return nil, []error{err} } @@ -201,33 +199,19 @@ func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.R func makeImps(imp openrtb2.Imp) (openrtb2.Imp, string, error) { var bidderExt adapters.ExtImpBidder - if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil { + if err := jsonutil.Unmarshal(imp.Ext, &bidderExt); err != nil { return openrtb2.Imp{}, "", &errortypes.BadInput{ Message: err.Error(), } } var insticatorExt openrtb_ext.ExtImpInsticator - if err := json.Unmarshal(bidderExt.Bidder, &insticatorExt); err != nil { + if err := jsonutil.Unmarshal(bidderExt.Bidder, &insticatorExt); err != nil { return openrtb2.Imp{}, "", &errortypes.BadInput{ Message: err.Error(), } } - // check if the adUnitId is not empty - if insticatorExt.AdUnitId == "" { - return openrtb2.Imp{}, "", &errortypes.BadInput{ - Message: "Missing adUnitId", - } - } - - // check if the publisherId is not empty - if insticatorExt.PublisherId == "" { - return openrtb2.Imp{}, insticatorExt.AdUnitId, &errortypes.BadInput{ - Message: "Missing publisherId", - } - } - // Directly construct the impExt impExt := ext{ Insticator: impInsticatorExt{ @@ -236,7 +220,7 @@ func makeImps(imp openrtb2.Imp) (openrtb2.Imp, string, error) { }, } - impExtJSON, err := json.Marshal(impExt) + impExtJSON, err := jsonutil.Marshal(impExt) if err != nil { return openrtb2.Imp{}, "", &errortypes.BadInput{ Message: err.Error(), @@ -261,7 +245,7 @@ func makeReqExt(request *openrtb2.BidRequest) ([]byte, error) { var reqExt reqExt if len(request.Ext) > 0 { - if err := json.Unmarshal(request.Ext, &reqExt); err != nil { + if err := jsonutil.Unmarshal(request.Ext, &reqExt); err != nil { return nil, err } } @@ -276,28 +260,22 @@ func makeReqExt(request *openrtb2.BidRequest) ([]byte, error) { reqExt.Insticator.Caller = append(reqExt.Insticator.Caller, caller) - return json.Marshal(reqExt) + return jsonutil.Marshal(reqExt) } func resolveBidFloor(bidFloor float64, bidFloorCur string, reqInfo *adapters.ExtraRequestInfo) (float64, error) { if bidFloor > 0 && bidFloorCur != "" && strings.ToUpper(bidFloorCur) != "USD" { floor, err := reqInfo.ConvertCurrency(bidFloor, bidFloorCur, "USD") - return roundTo4Decimals(floor), err + return mathutil.RoundTo4Decimals(floor), err } return bidFloor, nil } -// roundTo4Decimals function -func roundTo4Decimals(amount float64) float64 { - return math.Round(amount*10000) / 10000 -} - func validateVideoParams(video *openrtb2.Video) error { - videoCopy := *video - if (videoCopy.W == nil || *videoCopy.W == 0) || - (videoCopy.H == nil || *videoCopy.H == 0) || - videoCopy.MIMEs == nil { + if (video.W == nil || *video.W == 0) || + (video.H == nil || *video.H == 0) || + video.MIMEs == nil { return &errortypes.BadInput{ Message: "One or more invalid or missing video field(s) w, h, mimes", @@ -312,24 +290,43 @@ func populatePublisherId(imp *openrtb2.Imp, request *openrtb2.BidRequest) error var ext ext // Unmarshal the imp extension to get the publisher ID - if err := json.Unmarshal(imp.Ext, &ext); err != nil { + if err := jsonutil.Unmarshal(imp.Ext, &ext); err != nil { return &errortypes.BadInput{Message: "Error unmarshalling imp extension"} } // Populate site.publisher.id if request.Site is not nil if request.Site != nil { - if request.Site.Publisher == nil { + // Make a shallow copy of Site if it already exists + siteCopy := *request.Site + request.Site = &siteCopy + + // Make a shallow copy of Publisher if it already exists + if request.Site.Publisher != nil { + publisherCopy := *request.Site.Publisher + request.Site.Publisher = &publisherCopy + } else { request.Site.Publisher = &openrtb2.Publisher{} } + request.Site.Publisher.ID = ext.Insticator.PublisherId } // Populate app.publisher.id if request.App is not nil if request.App != nil { - if request.App.Publisher == nil { + // Make a shallow copy of App if it already exists + appCopy := *request.App + request.App = &appCopy + + // Make a shallow copy of Publisher if it already exists + if request.App.Publisher != nil { + publisherCopy := *request.App.Publisher + request.App.Publisher = &publisherCopy + } else { request.App.Publisher = &openrtb2.Publisher{} } + request.App.Publisher.ID = ext.Insticator.PublisherId } + return nil } diff --git a/static/bidder-params/insticator.json b/static/bidder-params/insticator.json index 586a6e2c83f..358ec37f579 100644 --- a/static/bidder-params/insticator.json +++ b/static/bidder-params/insticator.json @@ -8,11 +8,13 @@ "properties": { "adUnitId": { "type": "string", - "description": "Ad Unit Id" + "description": "Ad Unit Id", + "minLength": 1 }, "publisherId": { "type": "string", - "description": "Publisher Id" + "description": "Publisher Id", + "minLength": 1 } }, "required": ["adUnitId", "publisherId"] diff --git a/util/mathutil/mathutil.go b/util/mathutil/mathutil.go new file mode 100644 index 00000000000..126244501d6 --- /dev/null +++ b/util/mathutil/mathutil.go @@ -0,0 +1,9 @@ +// Package mathutil provides utility functions for mathematical operations. +package mathutil + +import "math" + +// RoundTo4Decimals rounds a float64 value to 4 decimal places. +func RoundTo4Decimals(amount float64) float64 { + return math.Round(amount*10000) / 10000 +} From ff2df10cd14939ace2a72fc996ff9a592d7e150c Mon Sep 17 00:00:00 2001 From: shubhamc-ins Date: Fri, 22 Nov 2024 01:21:13 +0530 Subject: [PATCH 15/18] update makeRequest to use requestCopy as reference --- adapters/insticator/insticator.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/adapters/insticator/insticator.go b/adapters/insticator/insticator.go index 6bfab626d79..b061de1c19c 100644 --- a/adapters/insticator/insticator.go +++ b/adapters/insticator/insticator.go @@ -84,7 +84,7 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapte request.Ext = reqExt - // Create a deep copy of the request to avoid modifying the original request + // Create a copy of the request to avoid modifying the original request requestCopy := *request for i := 0; i < len(request.Imp); i++ { @@ -120,7 +120,7 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapte } for _, impList := range groupedImps { - if adapterReq, err := a.makeRequest(requestCopy, impList); err == nil { + if adapterReq, err := a.makeRequest(&requestCopy, impList); err == nil { adapterRequests = append(adapterRequests, adapterReq) } else { errs = append(errs, err) @@ -129,7 +129,7 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapte return adapterRequests, errs } -func (a *adapter) makeRequest(request openrtb2.BidRequest, impList []openrtb2.Imp) (*adapters.RequestData, error) { +func (a *adapter) makeRequest(request *openrtb2.BidRequest, impList []openrtb2.Imp) (*adapters.RequestData, error) { request.Imp = impList reqJSON, err := jsonutil.Marshal(request) From fdcdc596e45477a1df045ee0d1fb0cf6727f5ba0 Mon Sep 17 00:00:00 2001 From: shubhamc-ins Date: Sat, 7 Dec 2024 00:29:05 +0530 Subject: [PATCH 16/18] update and add test cases for insticator --- adapters/insticator/insticator.go | 14 +- adapters/insticator/insticator_test.go | 4 +- .../insticatortest/exemplary/app-banner.json | 10 +- .../insticatortest/exemplary/app-video.json | 12 +- .../exemplary/multi-format.json | 2 +- .../insticatortest/exemplary/multi-imps.json | 4 +- .../insticatortest/exemplary/site-banner.json | 2 +- .../insticatortest/exemplary/site-video.json | 2 +- .../insticatortest/supplemental/204.json | 71 ++++++++ .../supplemental/app-pubid-absent.json | 120 ++++++++++++++ .../supplemental/bad-imp-ext.json | 29 ++++ .../currency-conversion-fail.json | 52 ++++++ .../supplemental/currency-conversion.json | 152 ++++++++++++++++++ .../supplemental/device-validation.json | 139 ++++++++++++++++ .../multi-imp-mixed-validation.json | 38 ++++- .../request-ext-unmarhal-fail.json | 41 +++++ .../supplemental/response-unmarshal-fail.json | 102 ++++++++++++ .../supplemental/site-pubid-absent.json | 120 ++++++++++++++ .../supplemental/status-not-ok.json | 2 +- util/mathutil/mathutil_test.go | 49 ++++++ 20 files changed, 944 insertions(+), 21 deletions(-) create mode 100644 adapters/insticator/insticatortest/supplemental/204.json create mode 100644 adapters/insticator/insticatortest/supplemental/app-pubid-absent.json create mode 100644 adapters/insticator/insticatortest/supplemental/bad-imp-ext.json create mode 100644 adapters/insticator/insticatortest/supplemental/currency-conversion-fail.json create mode 100644 adapters/insticator/insticatortest/supplemental/currency-conversion.json create mode 100644 adapters/insticator/insticatortest/supplemental/device-validation.json create mode 100644 adapters/insticator/insticatortest/supplemental/request-ext-unmarhal-fail.json create mode 100644 adapters/insticator/insticatortest/supplemental/response-unmarshal-fail.json create mode 100644 adapters/insticator/insticatortest/supplemental/site-pubid-absent.json create mode 100644 util/mathutil/mathutil_test.go diff --git a/adapters/insticator/insticator.go b/adapters/insticator/insticator.go index b061de1c19c..cec2e9efa3c 100644 --- a/adapters/insticator/insticator.go +++ b/adapters/insticator/insticator.go @@ -109,11 +109,10 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapte impCopy.BidFloorCur), }) continue - } else { - if resolvedBidFloor > 0 { - impCopy.BidFloor = resolvedBidFloor - impCopy.BidFloorCur = "USD" - } + } + if resolvedBidFloor > 0 { + impCopy.BidFloor = resolvedBidFloor + impCopy.BidFloorCur = "USD" } groupedImps[impKey] = append(groupedImps[impKey], impCopy) @@ -273,10 +272,7 @@ func resolveBidFloor(bidFloor float64, bidFloorCur string, reqInfo *adapters.Ext } func validateVideoParams(video *openrtb2.Video) error { - if (video.W == nil || *video.W == 0) || - (video.H == nil || *video.H == 0) || - video.MIMEs == nil { - + if (video.W == nil || *video.W == 0) || (video.H == nil || *video.H == 0) || video.MIMEs == nil { return &errortypes.BadInput{ Message: "One or more invalid or missing video field(s) w, h, mimes", } diff --git a/adapters/insticator/insticator_test.go b/adapters/insticator/insticator_test.go index b34595177b5..b557aedce4e 100644 --- a/adapters/insticator/insticator_test.go +++ b/adapters/insticator/insticator_test.go @@ -10,8 +10,8 @@ import ( func TestJsonSamples(t *testing.T) { bidder, buildErr := Builder(openrtb_ext.BidderInsticator, config.Adapter{ - Endpoint: "https://ex.ingage.tech/v1/prebidserver"}, - config.Server{ExternalUrl: "https://ex.ingage.tech/v1/prebidserver", GvlID: 1, DataCenter: "2"}) + Endpoint: "https://insticator.example.com/v1/pbs"}, + config.Server{ExternalUrl: "https://insticator.example.com/v1/pbs", GvlID: 1, DataCenter: "2"}) if buildErr != nil { t.Fatalf("Builder returned unexpected error %v", buildErr) diff --git a/adapters/insticator/insticatortest/exemplary/app-banner.json b/adapters/insticator/insticatortest/exemplary/app-banner.json index 503689a899b..4c71760a73e 100644 --- a/adapters/insticator/insticatortest/exemplary/app-banner.json +++ b/adapters/insticator/insticatortest/exemplary/app-banner.json @@ -19,14 +19,22 @@ "publisher": { "id": "test-publisher-id" } + }, + "device": { + "ua": "", + "ip": "1.1.1.2", + "ipv6": "" } }, "httpCalls": [ { "expectedRequest": { - "uri": "https://ex.ingage.tech/v1/prebidserver", + "uri": "https://insticator.example.com/v1/pbs", "body": { + "device":{ + "ip": "1.1.1.2" + }, "ext": { "insticator": { "caller": [ diff --git a/adapters/insticator/insticatortest/exemplary/app-video.json b/adapters/insticator/insticatortest/exemplary/app-video.json index 1b68238ff7a..0dcca79edb7 100644 --- a/adapters/insticator/insticatortest/exemplary/app-video.json +++ b/adapters/insticator/insticatortest/exemplary/app-video.json @@ -25,14 +25,24 @@ "publisher": { "id": "test-publisher-id" } + }, + "device": { + "ipv6": "2001:0db8:85a3:0000:0000:8a2e:0370:7334", + "ip": "1.22.22.1", + "ua": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G960F Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36" } }, "httpCalls": [ { "expectedRequest": { - "uri": "https://ex.ingage.tech/v1/prebidserver", + "uri": "https://insticator.example.com/v1/pbs", "body": { + "device": { + "ip": "1.22.22.1", + "ipv6": "2001:0db8:85a3:0000:0000:8a2e:0370:7334", + "ua": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G960F Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36" + }, "ext": { "insticator": { "caller": [ diff --git a/adapters/insticator/insticatortest/exemplary/multi-format.json b/adapters/insticator/insticatortest/exemplary/multi-format.json index 9bcf7873e86..1fedfe8dc9f 100644 --- a/adapters/insticator/insticatortest/exemplary/multi-format.json +++ b/adapters/insticator/insticatortest/exemplary/multi-format.json @@ -32,7 +32,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "https://ex.ingage.tech/v1/prebidserver", + "uri": "https://insticator.example.com/v1/pbs", "body": { "ext": { "insticator": { diff --git a/adapters/insticator/insticatortest/exemplary/multi-imps.json b/adapters/insticator/insticatortest/exemplary/multi-imps.json index 9d311c16acd..eb744ced11e 100644 --- a/adapters/insticator/insticatortest/exemplary/multi-imps.json +++ b/adapters/insticator/insticatortest/exemplary/multi-imps.json @@ -61,7 +61,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "https://ex.ingage.tech/v1/prebidserver", + "uri": "https://insticator.example.com/v1/pbs", "body": { "ext": { "insticator": { @@ -179,7 +179,7 @@ }, { "expectedRequest": { - "uri": "https://ex.ingage.tech/v1/prebidserver", + "uri": "https://insticator.example.com/v1/pbs", "body": { "ext": { "insticator": { diff --git a/adapters/insticator/insticatortest/exemplary/site-banner.json b/adapters/insticator/insticatortest/exemplary/site-banner.json index 783bcf4dec2..738aa297edb 100644 --- a/adapters/insticator/insticatortest/exemplary/site-banner.json +++ b/adapters/insticator/insticatortest/exemplary/site-banner.json @@ -25,7 +25,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "https://ex.ingage.tech/v1/prebidserver", + "uri": "https://insticator.example.com/v1/pbs", "body": { "ext": { "insticator": { diff --git a/adapters/insticator/insticatortest/exemplary/site-video.json b/adapters/insticator/insticatortest/exemplary/site-video.json index 7ed9f846a02..bd7c40af20e 100644 --- a/adapters/insticator/insticatortest/exemplary/site-video.json +++ b/adapters/insticator/insticatortest/exemplary/site-video.json @@ -31,7 +31,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "https://ex.ingage.tech/v1/prebidserver", + "uri": "https://insticator.example.com/v1/pbs", "body": { "ext": { "insticator": { diff --git a/adapters/insticator/insticatortest/supplemental/204.json b/adapters/insticator/insticatortest/supplemental/204.json new file mode 100644 index 00000000000..f0a43defb12 --- /dev/null +++ b/adapters/insticator/insticatortest/supplemental/204.json @@ -0,0 +1,71 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "bidder": { + "adUnitId": "fake-site-id", + "publisherId": "test-publisher-id" + } + } + } + ], + "site": { + "publisher": { + "id": "test-publisher-id" + } + } + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://insticator.example.com/v1/pbs", + "body": { + "ext": { + "insticator": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, + "id": "test-request-id", + "imp": [ + { + "id":"test-imp-id", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "insticator": { + "adUnitId": "fake-site-id", + "publisherId": "test-publisher-id" + } + } + } + ], + "site": { + "publisher": { + "id": "test-publisher-id" + } + } + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 204, + "body": {} + } + } + ], + "expectedBidResponses": [] + } + \ No newline at end of file diff --git a/adapters/insticator/insticatortest/supplemental/app-pubid-absent.json b/adapters/insticator/insticatortest/supplemental/app-pubid-absent.json new file mode 100644 index 00000000000..0fcafa58b13 --- /dev/null +++ b/adapters/insticator/insticatortest/supplemental/app-pubid-absent.json @@ -0,0 +1,120 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "bidder": { + "adUnitId": "fake-app-id", + "publisherId": "test-publisher-id" + } + } + } + ], + "app": { + "id": "test-app-id", + "bundle": "test-app.com" + } + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://insticator.example.com/v1/pbs", + "body": { + "ext": { + "insticator": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, + "id": "test-request-id", + "imp": [ + { + "id":"test-imp-id", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "insticator": { + "adUnitId": "fake-app-id", + "publisherId": "test-publisher-id" + } + } + } + ], + "app": { + "id": "test-app-id", + "bundle": "test-app.com", + "publisher": { + "id": "test-publisher-id" + } + } + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "insticator", + "bid": [{ + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.500000, + "adm": "some-test-ad", + "crid": "crid_10", + "h": 90, + "w": 728, + "mtype": 1, + "ext": { + "insticator": { + "mediaType": "banner" + } + } + }] + } + ], + "cur": "USD" + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.5, + "adm": "some-test-ad", + "crid": "crid_10", + "w": 728, + "h": 90, + "mtype": 1, + "ext": { + "insticator": { + "mediaType": "banner" + } + } + }, + "type": "banner" + } + ] + } + ] + } + \ No newline at end of file diff --git a/adapters/insticator/insticatortest/supplemental/bad-imp-ext.json b/adapters/insticator/insticatortest/supplemental/bad-imp-ext.json new file mode 100644 index 00000000000..2e0507791a6 --- /dev/null +++ b/adapters/insticator/insticatortest/supplemental/bad-imp-ext.json @@ -0,0 +1,29 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "bidder": "invalid ext" + } + } + ], + "site": { + "publisher": { + "id": "test-publisher-id" + } + } + }, + + "expectedMakeRequestsErrors": [ + { + "value": "expect { or n, but found \"", + "comparison": "literal" + } + ] + } + \ No newline at end of file diff --git a/adapters/insticator/insticatortest/supplemental/currency-conversion-fail.json b/adapters/insticator/insticatortest/supplemental/currency-conversion-fail.json new file mode 100644 index 00000000000..4c7082f47d8 --- /dev/null +++ b/adapters/insticator/insticatortest/supplemental/currency-conversion-fail.json @@ -0,0 +1,52 @@ +{ + "mockBidRequest": { + "cur": [ + "GBP" + ], + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 728, + "h": 90 + } + ] + }, + "ext": { + "bidder": { + "adUnitId": "fake-site-id", + "publisherId": "test-publisher-id" + } + }, + "bidfloor": 1, + "bidfloorcur": "GBP" + } + ], + "site": { + "publisher": { + "id": "test-publisher-id" + } + }, + "ext": { + "prebid": { + "currency": { + "rates": { + "INR": { + "USD": 2 + } + }, + "usepbsrates": false + } + } + } + }, + "expectedMakeRequestsErrors": [ + { + "value": "Error in converting the provided bid floor currency from GBP to USD", + "comparison": "literal" + } + ] +} \ No newline at end of file diff --git a/adapters/insticator/insticatortest/supplemental/currency-conversion.json b/adapters/insticator/insticatortest/supplemental/currency-conversion.json new file mode 100644 index 00000000000..9ce11dcdfbc --- /dev/null +++ b/adapters/insticator/insticatortest/supplemental/currency-conversion.json @@ -0,0 +1,152 @@ +{ + "mockBidRequest": { + "cur": [ + "GBP" + ], + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 728, + "h": 90 + } + ] + }, + "ext": { + "bidder": { + "adUnitId": "fake-site-id", + "publisherId": "test-publisher-id" + } + }, + "bidfloor": 1, + "bidfloorcur": "GBP" + } + ], + "site": { + "publisher": { + "id": "test-publisher-id" + } + }, + "ext": { + "prebid": { + "currency": { + "rates": { + "GBP": { + "USD": 2 + } + }, + "usepbsrates": false + } + } + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://insticator.example.com/v1/pbs", + "body": { + "cur": [ + "GBP" + ], + "ext": { + "insticator": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 728, + "h": 90 + } + ] + }, + "ext": { + "insticator": { + "adUnitId": "fake-site-id", + "publisherId": "test-publisher-id" + } + }, + "bidfloor": 2, + "bidfloorcur": "USD" + } + ], + "site": { + "publisher": { + "id": "test-publisher-id" + } + } + }, + "impIDs": [ + "test-imp-id" + ] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "insticator", + "bid": [ + { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.500000, + "adm": "some-test-ad", + "crid": "crid_10", + "h": 90, + "w": 728, + "mtype": 1, + "ext": { + "insticator": { + "mediaType": "banner" + } + } + } + ] + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.5, + "adm": "some-test-ad", + "crid": "crid_10", + "w": 728, + "h": 90, + "mtype": 1, + "ext": { + "insticator": { + "mediaType": "banner" + } + } + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/insticator/insticatortest/supplemental/device-validation.json b/adapters/insticator/insticatortest/supplemental/device-validation.json new file mode 100644 index 00000000000..0238b23ebab --- /dev/null +++ b/adapters/insticator/insticatortest/supplemental/device-validation.json @@ -0,0 +1,139 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "w": 728, + "h": 90, + "protocols": [2], + "placement": 1, + "startdelay": -2, + "playbackmethod": [2], + "mimes": ["foo", "bar"] + }, + "ext": { + "bidder": { + "adUnitId": "fake-site-id", + "publisherId": "test-publisher-id" + } + } + } + ], + "app": { + "publisher": { + "id": "test-publisher-id" + } + }, + "device": { + "ipv6": "", + "ip": "1.22.22.1", + "ua": "" + } + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://insticator.example.com/v1/pbs", + "body": { + "device": { + "ip": "1.22.22.1" + }, + "ext": { + "insticator": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, + "id": "test-request-id", + "imp": [ + { + "id":"test-imp-id", + "video": { + "w": 728, + "h": 90, + "protocols": [2], + "placement": 1, + "startdelay": -2, + "playbackmethod": [2], + "mimes": ["foo", "bar"] + }, + "ext": { + "insticator": { + "adUnitId": "fake-site-id", + "publisherId": "test-publisher-id" + } + } + } + ], + "app": { + "publisher": { + "id": "test-publisher-id" + } + } + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "insticator", + "bid": [{ + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.500000, + "adm": "some-test-vast-ad", + "mtype": 2, + "crid": "crid_10", + "h": 90, + "w": 728, + "ext": { + "insticator": { + "mediaType": "video" + } + } + }] + } + ], + "cur": "USD" + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.5, + "adm": "some-test-vast-ad", + "crid": "crid_10", + "w": 728, + "mtype": 2, + "h": 90, + "ext": { + "insticator": { + "mediaType": "video" + } + } + }, + "type": "video" + } + ] + } + ] + } + \ No newline at end of file diff --git a/adapters/insticator/insticatortest/supplemental/multi-imp-mixed-validation.json b/adapters/insticator/insticatortest/supplemental/multi-imp-mixed-validation.json index 81ec46e84d5..18fa069aedc 100644 --- a/adapters/insticator/insticatortest/supplemental/multi-imp-mixed-validation.json +++ b/adapters/insticator/insticatortest/supplemental/multi-imp-mixed-validation.json @@ -13,6 +13,23 @@ "publisherId": "test-publisher-id" } } + }, + { + "id": "test-imp-id2", + "video": { + "mimes": ["video/mp4"], + "minduration": 5, + "maxduration": 30, + "protocols": [2, 3, 5, 6], + "w": 640, + "h": 480 + }, + "ext": { + "bidder": { + "adUnitId": "fake-site-id", + "publisherId": "test-publisher-id" + } + } } ], "site": { @@ -25,7 +42,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "https://ex.ingage.tech/v1/prebidserver", + "uri": "https://insticator.example.com/v1/pbs", "body": { "ext": { "insticator": { @@ -50,6 +67,23 @@ "publisherId": "test-publisher-id" } } + }, + { + "id":"test-imp-id2", + "video": { + "mimes": ["video/mp4"], + "minduration": 5, + "maxduration": 30, + "protocols": [2, 3, 5, 6], + "w": 640, + "h": 480 + }, + "ext": { + "insticator": { + "adUnitId": "fake-site-id", + "publisherId": "test-publisher-id" + } + } } ], "site": { @@ -58,7 +92,7 @@ } } }, - "impIDs":["test-imp-id1"] + "impIDs":["test-imp-id1", "test-imp-id2"] }, "mockResponse": { "status": 200, diff --git a/adapters/insticator/insticatortest/supplemental/request-ext-unmarhal-fail.json b/adapters/insticator/insticatortest/supplemental/request-ext-unmarhal-fail.json new file mode 100644 index 00000000000..1ea883a11c5 --- /dev/null +++ b/adapters/insticator/insticatortest/supplemental/request-ext-unmarhal-fail.json @@ -0,0 +1,41 @@ +{ +"mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "w": 728, + "h": 90, + "protocols": [2], + "placement": 1, + "startdelay": -2, + "playbackmethod": [2], + "mimes": ["foo", "bar"] + }, + "ext": { + "bidder": "invalid" + } + } + ], + "site": { + "publisher": { + "id": "test-publisher-id" + } + }, + "ext": { + "insticator": "invalid" + } + }, + + "expectedMakeRequestsErrors": [ + { + "value": "cannot unmarshal insticator.reqExt.Insticator: expect { or n, but found \"", + "comparison": "literal" + }, + { + "value": "expect { or n, but found \"", + "comparison": "literal" + } + ] +} \ No newline at end of file diff --git a/adapters/insticator/insticatortest/supplemental/response-unmarshal-fail.json b/adapters/insticator/insticatortest/supplemental/response-unmarshal-fail.json new file mode 100644 index 00000000000..a3b40b084e0 --- /dev/null +++ b/adapters/insticator/insticatortest/supplemental/response-unmarshal-fail.json @@ -0,0 +1,102 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "w": 728, + "h": 90, + "protocols": [ + 2 + ], + "placement": 1, + "startdelay": -2, + "playbackmethod": [ + 2 + ], + "mimes": [ + "foo", + "bar" + ] + }, + "ext": { + "bidder": { + "adUnitId": "fake-site-id", + "publisherId": "test-publisher-id" + } + } + } + ], + "site": { + "publisher": { + "id": "test-publisher-id" + } + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://insticator.example.com/v1/pbs", + "body": { + "ext": { + "insticator": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "w": 728, + "h": 90, + "protocols": [ + 2 + ], + "placement": 1, + "startdelay": -2, + "playbackmethod": [ + 2 + ], + "mimes": [ + "foo", + "bar" + ] + }, + "ext": { + "insticator": { + "adUnitId": "fake-site-id", + "publisherId": "test-publisher-id" + } + } + } + ], + "site": { + "publisher": { + "id": "test-publisher-id" + } + } + }, + "impIDs": [ + "test-imp-id" + ] + }, + "mockResponse": { + "status": 200, + "body": "invalid json" + } + } + ], + "expectedMakeBidsErrors": [ + { + "value": "expect { or n, but found \"", + "comparison": "literal" + } + ] +} \ No newline at end of file diff --git a/adapters/insticator/insticatortest/supplemental/site-pubid-absent.json b/adapters/insticator/insticatortest/supplemental/site-pubid-absent.json new file mode 100644 index 00000000000..00c694a1975 --- /dev/null +++ b/adapters/insticator/insticatortest/supplemental/site-pubid-absent.json @@ -0,0 +1,120 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "bidder": { + "adUnitId": "fake-site-id", + "publisherId": "test-publisher-id" + } + } + } + ], + "site": { + "id": "test-site-id", + "domain": "test-site.com" + } + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://insticator.example.com/v1/pbs", + "body": { + "ext": { + "insticator": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, + "id": "test-request-id", + "imp": [ + { + "id":"test-imp-id", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "insticator": { + "adUnitId": "fake-site-id", + "publisherId": "test-publisher-id" + } + } + } + ], + "site": { + "id": "test-site-id", + "domain": "test-site.com", + "publisher": { + "id": "test-publisher-id" + } + } + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "insticator", + "bid": [{ + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.500000, + "adm": "some-test-ad", + "crid": "crid_10", + "h": 90, + "w": 728, + "mtype": 1, + "ext": { + "insticator": { + "mediaType": "banner" + } + } + }] + } + ], + "cur": "USD" + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.5, + "adm": "some-test-ad", + "crid": "crid_10", + "w": 728, + "h": 90, + "mtype": 1, + "ext": { + "insticator": { + "mediaType": "banner" + } + } + }, + "type": "banner" + } + ] + } + ] + } + \ No newline at end of file diff --git a/adapters/insticator/insticatortest/supplemental/status-not-ok.json b/adapters/insticator/insticatortest/supplemental/status-not-ok.json index e2778985e11..e530896e2d8 100644 --- a/adapters/insticator/insticatortest/supplemental/status-not-ok.json +++ b/adapters/insticator/insticatortest/supplemental/status-not-ok.json @@ -25,7 +25,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "https://ex.ingage.tech/v1/prebidserver", + "uri": "https://insticator.example.com/v1/pbs", "body": { "ext": { "insticator": { diff --git a/util/mathutil/mathutil_test.go b/util/mathutil/mathutil_test.go new file mode 100644 index 00000000000..545b28b3f4e --- /dev/null +++ b/util/mathutil/mathutil_test.go @@ -0,0 +1,49 @@ +package mathutil + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestRoundTo4Decimals(t *testing.T) { + t.Run("positive-number", func(t *testing.T) { + r := RoundTo4Decimals(123.456789) + assert.Equal(t, 123.4568, r) + }) + + t.Run("negative-number", func(t *testing.T) { + r := RoundTo4Decimals(-123.456789) + assert.Equal(t, -123.4568, r) + }) + + t.Run("already-rounded", func(t *testing.T) { + r := RoundTo4Decimals(123.4567) + assert.Equal(t, 123.4567, r) + }) + + t.Run("round-up", func(t *testing.T) { + r := RoundTo4Decimals(123.45675) + assert.Equal(t, 123.4568, r) + }) + + t.Run("round-down", func(t *testing.T) { + r := RoundTo4Decimals(123.45674) + assert.Equal(t, 123.4567, r) + }) + + t.Run("small-number", func(t *testing.T) { + r := RoundTo4Decimals(0.00005) + assert.Equal(t, 0.0001, r) + }) + + t.Run("negative-small-number", func(t *testing.T) { + r := RoundTo4Decimals(-0.00005) + assert.Equal(t, -0.0001, r) + }) + + t.Run("zero", func(t *testing.T) { + r := RoundTo4Decimals(0) + assert.Equal(t, 0.0, r) + }) +} From d8f3ca3800d82ded41115b80f27c23085e89fc31 Mon Sep 17 00:00:00 2001 From: shubhamc-ins Date: Tue, 10 Dec 2024 02:22:25 +0530 Subject: [PATCH 17/18] update makeImps and populatepublisherid, remove multiple calls, remove ext unmarshal --- adapters/insticator/insticator.go | 34 ++++++++++++++----------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/adapters/insticator/insticator.go b/adapters/insticator/insticator.go index cec2e9efa3c..2e7c5d4235d 100644 --- a/adapters/insticator/insticator.go +++ b/adapters/insticator/insticator.go @@ -86,20 +86,22 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapte // Create a copy of the request to avoid modifying the original request requestCopy := *request + isPublisherIdPopulated := false // Flag to track if populatePublisherId has been called for i := 0; i < len(request.Imp); i++ { - impCopy, impKey, err := makeImps(request.Imp[i]) + impCopy, impKey, publisherId, err := makeImps(request.Imp[i]) if err != nil { errs = append(errs, err) continue } - // Populate site.publisher.id from imp extension - if requestCopy.Site != nil || requestCopy.App != nil { - if err := populatePublisherId(&impCopy, &requestCopy); err != nil { + // Populate publisher.id from imp extension + if !isPublisherIdPopulated && (requestCopy.Site != nil || requestCopy.App != nil) { + if err := populatePublisherId(publisherId, &requestCopy); err != nil { errs = append(errs, err) continue } + isPublisherIdPopulated = true } resolvedBidFloor, errFloor := resolveBidFloor(impCopy.BidFloor, impCopy.BidFloorCur, requestInfo) @@ -196,17 +198,17 @@ func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.R return bidResponse, nil } -func makeImps(imp openrtb2.Imp) (openrtb2.Imp, string, error) { +func makeImps(imp openrtb2.Imp) (openrtb2.Imp, string, string, error) { var bidderExt adapters.ExtImpBidder if err := jsonutil.Unmarshal(imp.Ext, &bidderExt); err != nil { - return openrtb2.Imp{}, "", &errortypes.BadInput{ + return openrtb2.Imp{}, "", "", &errortypes.BadInput{ Message: err.Error(), } } var insticatorExt openrtb_ext.ExtImpInsticator if err := jsonutil.Unmarshal(bidderExt.Bidder, &insticatorExt); err != nil { - return openrtb2.Imp{}, "", &errortypes.BadInput{ + return openrtb2.Imp{}, "", "", &errortypes.BadInput{ Message: err.Error(), } } @@ -221,7 +223,7 @@ func makeImps(imp openrtb2.Imp) (openrtb2.Imp, string, error) { impExtJSON, err := jsonutil.Marshal(impExt) if err != nil { - return openrtb2.Imp{}, "", &errortypes.BadInput{ + return openrtb2.Imp{}, "", "", &errortypes.BadInput{ Message: err.Error(), } } @@ -230,14 +232,14 @@ func makeImps(imp openrtb2.Imp) (openrtb2.Imp, string, error) { // Validate Video if it exists if imp.Video != nil { if err := validateVideoParams(imp.Video); err != nil { - return openrtb2.Imp{}, insticatorExt.AdUnitId, &errortypes.BadInput{ + return openrtb2.Imp{}, insticatorExt.AdUnitId, insticatorExt.PublisherId, &errortypes.BadInput{ Message: err.Error(), } } } // Return the imp, AdUnitId, and no error - return imp, insticatorExt.AdUnitId, nil + return imp, insticatorExt.AdUnitId, insticatorExt.PublisherId, nil } func makeReqExt(request *openrtb2.BidRequest) ([]byte, error) { @@ -282,13 +284,7 @@ func validateVideoParams(video *openrtb2.Video) error { } // populatePublisherId function populates site.publisher.id or app.publisher.id -func populatePublisherId(imp *openrtb2.Imp, request *openrtb2.BidRequest) error { - var ext ext - - // Unmarshal the imp extension to get the publisher ID - if err := jsonutil.Unmarshal(imp.Ext, &ext); err != nil { - return &errortypes.BadInput{Message: "Error unmarshalling imp extension"} - } +func populatePublisherId(publisherId string, request *openrtb2.BidRequest) error { // Populate site.publisher.id if request.Site is not nil if request.Site != nil { @@ -304,7 +300,7 @@ func populatePublisherId(imp *openrtb2.Imp, request *openrtb2.BidRequest) error request.Site.Publisher = &openrtb2.Publisher{} } - request.Site.Publisher.ID = ext.Insticator.PublisherId + request.Site.Publisher.ID = publisherId } // Populate app.publisher.id if request.App is not nil @@ -321,7 +317,7 @@ func populatePublisherId(imp *openrtb2.Imp, request *openrtb2.BidRequest) error request.App.Publisher = &openrtb2.Publisher{} } - request.App.Publisher.ID = ext.Insticator.PublisherId + request.App.Publisher.ID = publisherId } return nil From f0d12f003ca4baaaf01c3199c410380ba1ebe148 Mon Sep 17 00:00:00 2001 From: shubhamc-ins Date: Fri, 13 Dec 2024 00:17:12 +0530 Subject: [PATCH 18/18] update adaptor and test cases for headers validation --- adapters/insticator/insticator.go | 17 +- .../insticatortest/exemplary/app-video.json | 262 ++++++++++-------- .../insticatortest/exemplary/site-banner.json | 74 +++-- .../supplemental/device-validation.json | 255 +++++++++-------- ...l.json => request-ext-unmarshal-fail.json} | 0 5 files changed, 349 insertions(+), 259 deletions(-) rename adapters/insticator/insticatortest/supplemental/{request-ext-unmarhal-fail.json => request-ext-unmarshal-fail.json} (100%) diff --git a/adapters/insticator/insticator.go b/adapters/insticator/insticator.go index 2e7c5d4235d..fc8487971b6 100644 --- a/adapters/insticator/insticator.go +++ b/adapters/insticator/insticator.go @@ -96,11 +96,8 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapte } // Populate publisher.id from imp extension - if !isPublisherIdPopulated && (requestCopy.Site != nil || requestCopy.App != nil) { - if err := populatePublisherId(publisherId, &requestCopy); err != nil { - errs = append(errs, err) - continue - } + if !isPublisherIdPopulated { + populatePublisherId(publisherId, &requestCopy) isPublisherIdPopulated = true } @@ -148,11 +145,11 @@ func (a *adapter) makeRequest(request *openrtb2.BidRequest, impList []openrtb2.I } if len(request.Device.IPv6) > 0 { - headers.Add("X-Forwarded-For", request.Device.IPv6) + headers.Set("X-Forwarded-For", request.Device.IPv6) } if len(request.Device.IP) > 0 { - headers.Add("X-Forwarded-For", request.Device.IP) + headers.Set("X-Forwarded-For", request.Device.IP) headers.Add("IP", request.Device.IP) } } @@ -274,7 +271,7 @@ func resolveBidFloor(bidFloor float64, bidFloorCur string, reqInfo *adapters.Ext } func validateVideoParams(video *openrtb2.Video) error { - if (video.W == nil || *video.W == 0) || (video.H == nil || *video.H == 0) || video.MIMEs == nil { + if video.W == nil || *video.W == 0 || video.H == nil || *video.H == 0 || video.MIMEs == nil { return &errortypes.BadInput{ Message: "One or more invalid or missing video field(s) w, h, mimes", } @@ -284,7 +281,7 @@ func validateVideoParams(video *openrtb2.Video) error { } // populatePublisherId function populates site.publisher.id or app.publisher.id -func populatePublisherId(publisherId string, request *openrtb2.BidRequest) error { +func populatePublisherId(publisherId string, request *openrtb2.BidRequest) { // Populate site.publisher.id if request.Site is not nil if request.Site != nil { @@ -319,6 +316,4 @@ func populatePublisherId(publisherId string, request *openrtb2.BidRequest) error request.App.Publisher.ID = publisherId } - - return nil } diff --git a/adapters/insticator/insticatortest/exemplary/app-video.json b/adapters/insticator/insticatortest/exemplary/app-video.json index 0dcca79edb7..2f0143fe961 100644 --- a/adapters/insticator/insticatortest/exemplary/app-video.json +++ b/adapters/insticator/insticatortest/exemplary/app-video.json @@ -1,95 +1,128 @@ { - "mockBidRequest": { - "id": "test-request-id", - "imp": [ - { - "id": "test-imp-id", - "video": { - "w": 728, - "h": 90, - "protocols": [2], - "placement": 1, - "startdelay": -2, - "playbackmethod": [2], - "mimes": ["foo", "bar"] - }, - "ext": { - "bidder": { - "adUnitId": "fake-site-id", - "publisherId": "test-publisher-id" - } + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "w": 728, + "h": 90, + "protocols": [ + 2 + ], + "placement": 1, + "startdelay": -2, + "playbackmethod": [ + 2 + ], + "mimes": [ + "foo", + "bar" + ] + }, + "ext": { + "bidder": { + "adUnitId": "fake-site-id", + "publisherId": "test-publisher-id" } } - ], - "app": { - "publisher": { - "id": "test-publisher-id" - } - }, - "device": { - "ipv6": "2001:0db8:85a3:0000:0000:8a2e:0370:7334", - "ip": "1.22.22.1", - "ua": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G960F Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36" + } + ], + "app": { + "publisher": { + "id": "test-publisher-id" } }, - - "httpCalls": [ - { - "expectedRequest": { - "uri": "https://insticator.example.com/v1/pbs", - "body": { - "device": { - "ip": "1.22.22.1", - "ipv6": "2001:0db8:85a3:0000:0000:8a2e:0370:7334", - "ua": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G960F Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36" - }, - "ext": { - "insticator": { - "caller": [ - { - "name": "Prebid-Server", - "version": "n/a" - } + "device": { + "ipv6": "2001:0db8:85a3:0000:0000:8a2e:0370:7334", + "ip": "1.22.22.1", + "ua": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G960F Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "headers": { + "Content-Type": [ + "application/json;charset=utf-8" + ], + "Accept": [ + "application/json" + ], + "User-Agent": [ + "Mozilla/5.0 (Linux; Android 8.0.0; SM-G960F Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36" + ], + "X-Forwarded-For": [ + "1.22.22.1" + ], + "Ip": [ + "1.22.22.1" + ] + }, + "uri": "https://insticator.example.com/v1/pbs", + "body": { + "device": { + "ip": "1.22.22.1", + "ipv6": "2001:0db8:85a3:0000:0000:8a2e:0370:7334", + "ua": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G960F Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36" + }, + "ext": { + "insticator": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "w": 728, + "h": 90, + "protocols": [ + 2 + ], + "placement": 1, + "startdelay": -2, + "playbackmethod": [ + 2 + ], + "mimes": [ + "foo", + "bar" ] - } - }, - "id": "test-request-id", - "imp": [ - { - "id":"test-imp-id", - "video": { - "w": 728, - "h": 90, - "protocols": [2], - "placement": 1, - "startdelay": -2, - "playbackmethod": [2], - "mimes": ["foo", "bar"] - }, - "ext": { - "insticator": { - "adUnitId": "fake-site-id", - "publisherId": "test-publisher-id" - } + }, + "ext": { + "insticator": { + "adUnitId": "fake-site-id", + "publisherId": "test-publisher-id" } } - ], - "app": { - "publisher": { - "id": "test-publisher-id" - } } - }, - "impIDs":["test-imp-id"] + ], + "app": { + "publisher": { + "id": "test-publisher-id" + } + } }, - "mockResponse": { - "status": 200, - "body": { - "id": "test-request-id", - "seatbid": [ - { - "seat": "insticator", - "bid": [{ + "impIDs": [ + "test-imp-id" + ] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "insticator", + "bid": [ + { "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", "impid": "test-imp-id", "price": 0.500000, @@ -103,39 +136,38 @@ "mediaType": "video" } } - }] - } - ], - "cur": "USD" - } + } + ] + } + ], + "cur": "USD" } } - ], - - "expectedBidResponses": [ - { - "currency": "USD", - "bids": [ - { - "bid": { - "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", - "impid": "test-imp-id", - "price": 0.5, - "adm": "some-test-vast-ad", - "crid": "crid_10", - "w": 728, - "mtype": 2, - "h": 90, - "ext": { - "insticator": { - "mediaType": "video" - } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.5, + "adm": "some-test-vast-ad", + "crid": "crid_10", + "w": 728, + "mtype": 2, + "h": 90, + "ext": { + "insticator": { + "mediaType": "video" } - }, - "type": "video" - } - ] - } - ] - } - \ No newline at end of file + } + }, + "type": "video" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/insticator/insticatortest/exemplary/site-banner.json b/adapters/insticator/insticatortest/exemplary/site-banner.json index 738aa297edb..4586fdc1767 100644 --- a/adapters/insticator/insticatortest/exemplary/site-banner.json +++ b/adapters/insticator/insticatortest/exemplary/site-banner.json @@ -5,7 +5,12 @@ { "id": "test-imp-id", "banner": { - "format": [{"w": 728, "h": 90}] + "format": [ + { + "w": 728, + "h": 90 + } + ] }, "ext": { "bidder": { @@ -19,14 +24,35 @@ "publisher": { "id": "test-publisher-id" } + }, + "device": { + "ipv6": "2001:0db8:85a3:0000:0000:8a2e:0370:7334", + "ua": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G960F Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36" } }, - "httpCalls": [ { "expectedRequest": { + "headers": { + "Content-Type": [ + "application/json;charset=utf-8" + ], + "Accept": [ + "application/json" + ], + "User-Agent": [ + "Mozilla/5.0 (Linux; Android 8.0.0; SM-G960F Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36" + ], + "X-Forwarded-For": [ + "2001:0db8:85a3:0000:0000:8a2e:0370:7334" + ] + }, "uri": "https://insticator.example.com/v1/pbs", "body": { + "device": { + "ipv6": "2001:0db8:85a3:0000:0000:8a2e:0370:7334", + "ua": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G960F Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36" + }, "ext": { "insticator": { "caller": [ @@ -40,9 +66,14 @@ "id": "test-request-id", "imp": [ { - "id":"test-imp-id", + "id": "test-imp-id", "banner": { - "format": [{"w": 728, "h": 90}] + "format": [ + { + "w": 728, + "h": 90 + } + ] }, "ext": { "insticator": { @@ -58,7 +89,9 @@ } } }, - "impIDs":["test-imp-id"] + "impIDs": [ + "test-imp-id" + ] }, "mockResponse": { "status": 200, @@ -67,21 +100,23 @@ "seatbid": [ { "seat": "insticator", - "bid": [{ - "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", - "impid": "test-imp-id", - "price": 0.500000, - "adm": "some-test-ad", - "crid": "crid_10", - "h": 90, - "w": 728, - "mtype": 1, - "ext": { - "insticator": { - "mediaType": "banner" + "bid": [ + { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.500000, + "adm": "some-test-ad", + "crid": "crid_10", + "h": 90, + "w": 728, + "mtype": 1, + "ext": { + "insticator": { + "mediaType": "banner" + } } } - }] + ] } ], "cur": "USD" @@ -89,7 +124,6 @@ } } ], - "expectedBidResponses": [ { "currency": "USD", @@ -115,4 +149,4 @@ ] } ] -} +} \ No newline at end of file diff --git a/adapters/insticator/insticatortest/supplemental/device-validation.json b/adapters/insticator/insticatortest/supplemental/device-validation.json index 0238b23ebab..a493e1b28a2 100644 --- a/adapters/insticator/insticatortest/supplemental/device-validation.json +++ b/adapters/insticator/insticatortest/supplemental/device-validation.json @@ -1,93 +1,123 @@ { - "mockBidRequest": { - "id": "test-request-id", - "imp": [ - { - "id": "test-imp-id", - "video": { - "w": 728, - "h": 90, - "protocols": [2], - "placement": 1, - "startdelay": -2, - "playbackmethod": [2], - "mimes": ["foo", "bar"] - }, - "ext": { - "bidder": { - "adUnitId": "fake-site-id", - "publisherId": "test-publisher-id" - } + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "w": 728, + "h": 90, + "protocols": [ + 2 + ], + "placement": 1, + "startdelay": -2, + "playbackmethod": [ + 2 + ], + "mimes": [ + "foo", + "bar" + ] + }, + "ext": { + "bidder": { + "adUnitId": "fake-site-id", + "publisherId": "test-publisher-id" } } - ], - "app": { - "publisher": { - "id": "test-publisher-id" - } - }, - "device": { - "ipv6": "", - "ip": "1.22.22.1", - "ua": "" + } + ], + "app": { + "publisher": { + "id": "test-publisher-id" } }, - - "httpCalls": [ - { - "expectedRequest": { - "uri": "https://insticator.example.com/v1/pbs", - "body": { - "device": { - "ip": "1.22.22.1" - }, - "ext": { - "insticator": { - "caller": [ - { - "name": "Prebid-Server", - "version": "n/a" - } + "device": { + "ipv6": "", + "ip": "1.22.22.1", + "ua": "" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "headers": { + "Content-Type": [ + "application/json;charset=utf-8" + ], + "Accept": [ + "application/json" + ], + "X-Forwarded-For": [ + "1.22.22.1" + ], + "Ip": [ + "1.22.22.1" + ] + }, + "uri": "https://insticator.example.com/v1/pbs", + "body": { + "device": { + "ip": "1.22.22.1" + }, + "ext": { + "insticator": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "w": 728, + "h": 90, + "protocols": [ + 2 + ], + "placement": 1, + "startdelay": -2, + "playbackmethod": [ + 2 + ], + "mimes": [ + "foo", + "bar" ] - } - }, - "id": "test-request-id", - "imp": [ - { - "id":"test-imp-id", - "video": { - "w": 728, - "h": 90, - "protocols": [2], - "placement": 1, - "startdelay": -2, - "playbackmethod": [2], - "mimes": ["foo", "bar"] - }, - "ext": { - "insticator": { - "adUnitId": "fake-site-id", - "publisherId": "test-publisher-id" - } + }, + "ext": { + "insticator": { + "adUnitId": "fake-site-id", + "publisherId": "test-publisher-id" } } - ], - "app": { - "publisher": { - "id": "test-publisher-id" - } } - }, - "impIDs":["test-imp-id"] + ], + "app": { + "publisher": { + "id": "test-publisher-id" + } + } }, - "mockResponse": { - "status": 200, - "body": { - "id": "test-request-id", - "seatbid": [ - { - "seat": "insticator", - "bid": [{ + "impIDs": [ + "test-imp-id" + ] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "insticator", + "bid": [ + { "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", "impid": "test-imp-id", "price": 0.500000, @@ -101,39 +131,38 @@ "mediaType": "video" } } - }] - } - ], - "cur": "USD" - } + } + ] + } + ], + "cur": "USD" } } - ], - - "expectedBidResponses": [ - { - "currency": "USD", - "bids": [ - { - "bid": { - "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", - "impid": "test-imp-id", - "price": 0.5, - "adm": "some-test-vast-ad", - "crid": "crid_10", - "w": 728, - "mtype": 2, - "h": 90, - "ext": { - "insticator": { - "mediaType": "video" - } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.5, + "adm": "some-test-vast-ad", + "crid": "crid_10", + "w": 728, + "mtype": 2, + "h": 90, + "ext": { + "insticator": { + "mediaType": "video" } - }, - "type": "video" - } - ] - } - ] - } - \ No newline at end of file + } + }, + "type": "video" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/insticator/insticatortest/supplemental/request-ext-unmarhal-fail.json b/adapters/insticator/insticatortest/supplemental/request-ext-unmarshal-fail.json similarity index 100% rename from adapters/insticator/insticatortest/supplemental/request-ext-unmarhal-fail.json rename to adapters/insticator/insticatortest/supplemental/request-ext-unmarshal-fail.json