From 5645a812038893ff491344fea6b5e1e87ec7ae01 Mon Sep 17 00:00:00 2001 From: Nikitha Gaddam Date: Fri, 9 May 2025 11:16:21 +0530 Subject: [PATCH 01/13] Integration of RevX --- adapters/revx/params_test.go | 43 +++++ adapters/revx/revx.go | 151 ++++++++++++++++++ adapters/revx/revx_test.go | 32 ++++ .../revxtest/exemplary/simple-app-banner.json | 109 +++++++++++++ .../revxtest/exemplary/simple-app-native.json | 99 ++++++++++++ .../revxtest/exemplary/simple-app-video.json | 122 ++++++++++++++ .../revxtest/exemplary/simple-web-banner.json | 108 +++++++++++++ .../revxtest/exemplary/simple-web-native.json | 94 +++++++++++ .../revxtest/exemplary/simple-web-video.json | 118 ++++++++++++++ adapters/revx/revxtest/supplemental/204.json | 65 ++++++++ adapters/revx/revxtest/supplemental/400.json | 65 ++++++++ .../supplemental/banner-format-coersion.json | 81 ++++++++++ .../supplemental/ext-unmarshal-err.json | 33 ++++ .../revxtest/supplemental/invalid-mtype.json | 94 +++++++++++ .../supplemental/missing-plc-error.json | 34 ++++ .../revxtest/supplemental/no-imp-error.json | 13 ++ exchange/adapter_builders.go | 2 + openrtb_ext/bidders.go | 2 + openrtb_ext/imp_revx.go | 5 + static/bidder-info/revx.yaml | 24 +++ static/bidder-params/revx.json | 15 ++ 21 files changed, 1309 insertions(+) create mode 100644 adapters/revx/params_test.go create mode 100644 adapters/revx/revx.go create mode 100644 adapters/revx/revx_test.go create mode 100644 adapters/revx/revxtest/exemplary/simple-app-banner.json create mode 100644 adapters/revx/revxtest/exemplary/simple-app-native.json create mode 100644 adapters/revx/revxtest/exemplary/simple-app-video.json create mode 100644 adapters/revx/revxtest/exemplary/simple-web-banner.json create mode 100644 adapters/revx/revxtest/exemplary/simple-web-native.json create mode 100644 adapters/revx/revxtest/exemplary/simple-web-video.json create mode 100644 adapters/revx/revxtest/supplemental/204.json create mode 100644 adapters/revx/revxtest/supplemental/400.json create mode 100644 adapters/revx/revxtest/supplemental/banner-format-coersion.json create mode 100644 adapters/revx/revxtest/supplemental/ext-unmarshal-err.json create mode 100644 adapters/revx/revxtest/supplemental/invalid-mtype.json create mode 100644 adapters/revx/revxtest/supplemental/missing-plc-error.json create mode 100644 adapters/revx/revxtest/supplemental/no-imp-error.json create mode 100644 openrtb_ext/imp_revx.go create mode 100644 static/bidder-info/revx.yaml create mode 100644 static/bidder-params/revx.json diff --git a/adapters/revx/params_test.go b/adapters/revx/params_test.go new file mode 100644 index 00000000000..d81c85f382a --- /dev/null +++ b/adapters/revx/params_test.go @@ -0,0 +1,43 @@ +package revx + +import ( + "encoding/json" + "testing" + + "github.com/prebid/prebid-server/v3/openrtb_ext" +) + +func TestValidParams(t *testing.T) { + validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") + if err != nil { + t.Fatalf("Failed to load JSON schemas: %v", err) + } + + for _, validParam := range validParams { + if err := validator.Validate(openrtb_ext.BidderRevX, json.RawMessage(validParam)); err != nil { + t.Errorf("Schema rejected valid RevX params: %s\nError: %s", validParam, err) + } + } +} + +func TestInvalidParams(t *testing.T) { + validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") + if err != nil { + t.Fatalf("Failed to load JSON schemas: %v", err) + } + + for _, invalidParam := range invalidParams { + if err := validator.Validate(openrtb_ext.BidderRevX, json.RawMessage(invalidParam)); err == nil { + t.Errorf("Schema accepted invalid RevX params: %s", invalidParam) + } + } +} + +var validParams = []string{ + `{"pubname": "publisher123"}`, +} + +var invalidParams = []string{ + `{}`, + `{ "pubname": ""}`, +} diff --git a/adapters/revx/revx.go b/adapters/revx/revx.go new file mode 100644 index 00000000000..3c534eb7f05 --- /dev/null +++ b/adapters/revx/revx.go @@ -0,0 +1,151 @@ +package revx + +import ( + "fmt" + "net/http" + + "github.com/prebid/openrtb/v20/openrtb2" + "github.com/prebid/prebid-server/v3/adapters" + "github.com/prebid/prebid-server/v3/config" + "github.com/prebid/prebid-server/v3/errortypes" + "github.com/prebid/prebid-server/v3/openrtb_ext" + "github.com/prebid/prebid-server/v3/util/jsonutil" +) + +// RevXAdapter struct +type RevXAdapter struct { + endPoint string +} + +// Builder builds a new instance of the RevX adapter. +func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { + return &RevXAdapter{ + endPoint: config.Endpoint, // Default endpoint + }, nil +} + +// MakeRequests handles the OpenRTB bid request and returns адаптер.RequestData +func (a *RevXAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { + var requests []*adapters.RequestData + var errors []error + + if len(request.Imp) == 0 { + return nil, []error{&errortypes.BadInput{ + Message: "No valid impressions for grid", + }} + } + // Unmarshal imp.ext + var bidderExt adapters.ExtImpBidder + if err := jsonutil.Unmarshal(request.Imp[0].Ext, &bidderExt); err != nil { + errors = append(errors, &errortypes.BadInput{Message: fmt.Sprintf("invalid imp.ext: %s", err)}) + + } + + var revxExt openrtb_ext.ExtImpRevX + if err := jsonutil.Unmarshal(bidderExt.Bidder, &revxExt); err != nil { + errors = append(errors, &errortypes.BadInput{Message: "bad revx bidder ext"}) + + } + + // Check if publisher name is present + if len(revxExt.PubName) == 0 { + return nil, []error{&errortypes.BadInput{Message: "Publisher name missing"}} + } + if len(requests) == 0 && len(errors) > 0 { + return nil, errors + } + + // Build dynamic endpoint + //var fendpoint = fmt.Sprintf(a.endPoint, strings.ToUpper(revxExt.PubName)) + headers := http.Header{} + headers.Add("Content-Type", "application/json;charset=utf-8") + headers.Add("Accept", "application/json") + + // Marshal the OpenRTB bid request into JSON + reqJson, err := jsonutil.Marshal(request) + if err != nil { + return nil, []error{&errortypes.BadInput{Message: fmt.Sprintf("Failed to marshal request: %s", err)}} + } + + return []*adapters.RequestData{{ + Method: "POST", + Uri: a.endPoint, + Body: reqJson, + Headers: headers, + ImpIDs: openrtb_ext.GetImpIDs(request.Imp), + }}, errors +} + +// MakeBids handles the OpenRTB bid response. +func (a *RevXAdapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { + if externalRequest == nil { + return nil, nil + } + + // Treat 204 and 400 as no-bid without error + if response.StatusCode == http.StatusNoContent || response.StatusCode == http.StatusBadRequest { + return nil, nil + } + + if response.StatusCode != http.StatusOK { + return nil, []error{&errortypes.BadServerResponse{ + Message: fmt.Sprintf("Unexpected http status code: %d", response.StatusCode), + }} + } + + var serverBidResponse openrtb2.BidResponse + if err := jsonutil.Unmarshal(response.Body, &serverBidResponse); err != nil { + return nil, []error{err} + } + + // Initialize a slice to hold valid bids + var typedBids []*adapters.TypedBid + + for _, sb := range serverBidResponse.SeatBid { + for i := range sb.Bid { + mediaType, err := getMediaTypeForImp(sb.Bid[i]) + if err != nil { + return nil, []error{err} + } + + typedBids = append(typedBids, &adapters.TypedBid{ + Bid: &sb.Bid[i], + BidType: mediaType, + }) + } + } + + // If no valid bids, return nil, nil + if len(typedBids) == 0 { + return nil, nil + } + + // Create and populate the BidderResponse only if there are valid bids + bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(typedBids)) + bidResponse.Bids = typedBids + bidResponse.Currency = serverBidResponse.Cur + + // Return the response with valid bids + return bidResponse, nil +} + +func getMediaTypeForImp(bid openrtb2.Bid) (openrtb_ext.BidType, error) { + // Check if MType is 0 (invalid or missing media type) + if bid.MType == 0 { + return "", &errortypes.BadServerResponse{ + Message: fmt.Sprintf("Unsupported mtype %d for bid %s", bid.MType, bid.ID), + } + } + switch bid.MType { + case openrtb2.MarkupBanner: + return openrtb_ext.BidTypeBanner, nil + case openrtb2.MarkupVideo: + return openrtb_ext.BidTypeVideo, nil + case openrtb2.MarkupNative: + return openrtb_ext.BidTypeNative, nil + default: + return "", &errortypes.BadServerResponse{ + Message: fmt.Sprintf("Unsupported mtype %d for bid %s", bid.MType, bid.ID), + } + } +} diff --git a/adapters/revx/revx_test.go b/adapters/revx/revx_test.go new file mode 100644 index 00000000000..35cd43dbf60 --- /dev/null +++ b/adapters/revx/revx_test.go @@ -0,0 +1,32 @@ +package revx_test + +import ( + "testing" + + "github.com/prebid/prebid-server/v3/adapters/adapterstest" + "github.com/prebid/prebid-server/v3/adapters/revx" + "github.com/prebid/prebid-server/v3/config" + "github.com/prebid/prebid-server/v3/openrtb_ext" +) + +func TestJsonSamples(t *testing.T) { + bidder, buildErr := revx.Builder(openrtb_ext.BidderRevX, config.Adapter{ + Endpoint: "prebid-use.atomex.net/ag=PUB123", + }, config.Server{ + ExternalUrl: "http://hosturl.com", + GvlID: 375, + DataCenter: "2", + }) + + if buildErr != nil { + + t.Logf("RevX Builder created successfully: %+v", bidder) + } + + adapterstest.RunJSONBidderTest(t, "revxtest", bidder) // Call it directly + + t.Logf("--- Finished TestJsonSamples for revxtest/exemplary/simple-app-banner.json ---") + + adapterstest.RunJSONBidderTest(t, "revxtest", bidder) + +} diff --git a/adapters/revx/revxtest/exemplary/simple-app-banner.json b/adapters/revx/revxtest/exemplary/simple-app-banner.json new file mode 100644 index 00000000000..f36257ec3ac --- /dev/null +++ b/adapters/revx/revxtest/exemplary/simple-app-banner.json @@ -0,0 +1,109 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "page": "https://good.site/url" + }, + "imp": [ + { + "id": "imp-id", + "banner": { + "format": [ + { + "w": 111, + "h": 111 + } + ] + }, + "ext": { + "bidder": { + "pubname": "PUB123" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "prebid-use.atomex.net/ag=PUB123", + + "body": { + "id": "test-request-id", + "site": { + "page": "https://good.site/url" + }, + "imp": [ + { + "id": "imp-id", + "banner": { + "format": [ + { + "w": 111, + "h": 111 + } + ] + }, + "ext": { + "bidder": { + "pubname": "PUB123" + } + } + } + ] + }, + "impIDs": [ + "imp-id" + ] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "interactiveoffers", + "bid": [ + { + "id": "randomid", + "impid": "imp-id", + "price": 0.5, + "adid": "12345678", + "adm": "some-test-ad", + "cid": "987", + "crid": "12345678", + "h": 111, + "w": 111, + "mtype": 1 + } + ] + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "randomid", + "impid": "imp-id", + "price": 0.5, + "adm": "some-test-ad", + "adid": "12345678", + "cid": "987", + "crid": "12345678", + "w": 111, + "h": 111, + "mtype": 1 + }, + "type": "banner" + } + ] + } + ] +} diff --git a/adapters/revx/revxtest/exemplary/simple-app-native.json b/adapters/revx/revxtest/exemplary/simple-app-native.json new file mode 100644 index 00000000000..81c77915a25 --- /dev/null +++ b/adapters/revx/revxtest/exemplary/simple-app-native.json @@ -0,0 +1,99 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "app": { + "publisher": { + "name": "PUB123" + } + }, + "imp": [ + { + "id": "imp-id", + "native": { + "request": "{\"native\":{\"ver\":\"1.2\",\"api\":[1],\"battr\":[1,3,9],\"assets\":[{\"id\":0,\"required\":1,\"title\":{\"len\":25}},{\"id\":1,\"required\":1,\"img\":{\"type\":3,\"wmin\":100,\"hmin\":50}},{\"id\":2,\"required\":0,\"data\":{\"type\":2,\"len\":200}},{\"id\":3,\"required\":0,\"data\":{\"type\":12}},{\"id\":4,\"required\":0,\"data\":{\"type\":1}}]}}" + }, + "ext": { + "bidder": { + "pubname": "PUB123" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "prebid-use.atomex.net/ag=PUB123", + "body": { + "id": "test-request-id", + "app": { + "publisher": { + "name": "PUB123" + } + }, + "imp": [ + { + "id": "imp-id", + "native": { + "request": "{\"native\":{\"ver\":\"1.2\",\"api\":[1],\"battr\":[1,3,9],\"assets\":[{\"id\":0,\"required\":1,\"title\":{\"len\":25}},{\"id\":1,\"required\":1,\"img\":{\"type\":3,\"wmin\":100,\"hmin\":50}},{\"id\":2,\"required\":0,\"data\":{\"type\":2,\"len\":200}},{\"id\":3,\"required\":0,\"data\":{\"type\":12}},{\"id\":4,\"required\":0,\"data\":{\"type\":1}}]}}" + }, + "ext": { + "bidder": { + "pubname": "PUB123" + } + } + } + ] + }, + "impIDs": [ + "imp-id" + ] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "interactiveoffers", + "bid": [ + { + "id": "randomid", + "impid": "imp-id", + "price": 0.5, + "adid": "12345678", + "adm": "{\"native\":{\"ver\":\"1.2\",\"assets\":[{\"id\":0,\"title\":{\"text\":\"Test Title\"}},{\"id\":1,\"img\":{\"url\":\"http://some.image.url\",\"w\":100,\"h\":50}},{\"id\":2,\"data\":{\"type\":2,\"value\":\"Test Body\"}},{\"id\":3,\"data\":{\"type\":12,\"value\":\"Test Sponsored\"}},{\"id\":4,\"data\":{\"type\":1,\"value\":\"Test Display URL\"}}],\"link\":{\"url\":\"http://click.url\"},\"imptrackers\":[\"http://impression.url\"]}}", + "cid": "987", + "crid": "12345678", + "mtype": 4 + + } + ] + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "randomid", + "impid": "imp-id", + "price": 0.5, + "adm": "{\"native\":{\"ver\":\"1.2\",\"assets\":[{\"id\":0,\"title\":{\"text\":\"Test Title\"}},{\"id\":1,\"img\":{\"url\":\"http://some.image.url\",\"w\":100,\"h\":50}},{\"id\":2,\"data\":{\"type\":2,\"value\":\"Test Body\"}},{\"id\":3,\"data\":{\"type\":12,\"value\":\"Test Sponsored\"}},{\"id\":4,\"data\":{\"type\":1,\"value\":\"Test Display URL\"}}],\"link\":{\"url\":\"http://click.url\"},\"imptrackers\":[\"http://impression.url\"]}}", + "adid": "12345678", + "cid": "987", + "crid": "12345678", + "mtype": 4 + }, + "type": "native" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/revx/revxtest/exemplary/simple-app-video.json b/adapters/revx/revxtest/exemplary/simple-app-video.json new file mode 100644 index 00000000000..6db4f7abcf9 --- /dev/null +++ b/adapters/revx/revxtest/exemplary/simple-app-video.json @@ -0,0 +1,122 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "app": { + "publisher": { + "name": "PUB123" + } + }, + "imp": [ + { + "id": "imp-id", + "video": { + "mimes": [ + "application/x-mpegURL", + "video/mp4" + ], + "protocols": [ + 2, + 5 + ], + "w": 640, + "h": 480, + "placement": 1 + }, + "ext": { + "bidder": { + "pubname": "PUB123" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "prebid-use.atomex.net/ag=PUB123", + "body": { + "id": "test-request-id", + "app": { + "publisher": { + "name": "PUB123" + } + }, + "imp": [ + { + "id": "imp-id", + "video": { + "mimes": [ + "application/x-mpegURL", + "video/mp4" + ], + "protocols": [ + 2, + 5 + ], + "w": 640, + "h": 480, + "placement": 1 + }, + "ext": { + "bidder": { + "pubname": "PUB123" + } + } + } + ] + }, + "impIDs": [ + "imp-id" + ] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "interactiveoffers", + "bid": [ + { + "id": "randomid", + "impid": "imp-id", + "price": 0.5, + "adid": "12345678", + "adm": "", + "cid": "987", + "crid": "12345678", + "w": 640, + "h": 480, + "mtype": 2 + } + ] + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "randomid", + "impid": "imp-id", + "price": 0.5, + "adm": "", + "adid": "12345678", + "cid": "987", + "crid": "12345678", + "w": 640, + "h": 480, + "mtype": 2 + }, + "type": "video" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/revx/revxtest/exemplary/simple-web-banner.json b/adapters/revx/revxtest/exemplary/simple-web-banner.json new file mode 100644 index 00000000000..58ea9fb30ba --- /dev/null +++ b/adapters/revx/revxtest/exemplary/simple-web-banner.json @@ -0,0 +1,108 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "page": "https://good.site/url" + }, + "imp": [ + { + "id": "imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "pubname": "PUB123" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "prebid-use.atomex.net/ag=PUB123", + "body": { + "id": "test-request-id", + "site": { + "page": "https://good.site/url" + }, + "imp": [ + { + "id": "imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "pubname": "PUB123" + } + } + } + ] + }, + "impIDs": [ + "imp-id" + ] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "interactiveoffers", + "bid": [ + { + "id": "randomid", + "impid": "imp-id", + "price": 0.5, + "adid": "12345678", + "adm": "
", + "cid": "987", + "crid": "12345678", + "h": 250, + "w": 300, + "mtype": 1 + } + ] + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "randomid", + "impid": "imp-id", + "price": 0.5, + "adm": "
", + "adid": "12345678", + "cid": "987", + "crid": "12345678", + "w": 300, + "h": 250, + "mtype": 1 + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/revx/revxtest/exemplary/simple-web-native.json b/adapters/revx/revxtest/exemplary/simple-web-native.json new file mode 100644 index 00000000000..7fce0930585 --- /dev/null +++ b/adapters/revx/revxtest/exemplary/simple-web-native.json @@ -0,0 +1,94 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "page": "https://good.site/url" + }, + "imp": [ + { + "id": "imp-id", + "native": { + "request": "{\"native\":{\"ver\":\"1.2\",\"api\":[1],\"battr\":[1,3,9],\"assets\":[{\"id\":0,\"required\":1,\"title\":{\"len\":25}},{\"id\":1,\"required\":1,\"img\":{\"type\":3,\"wmin\":100,\"hmin\":50}},{\"id\":2,\"required\":0,\"data\":{\"type\":2,\"len\":200}},{\"id\":3,\"required\":0,\"data\":{\"type\":12}},{\"id\":4,\"required\":0,\"data\":{\"type\":1}}]}}" + }, + "ext": { + "bidder": { + "pubname": "PUB123" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "prebid-use.atomex.net/ag=PUB123", + "body": { + "id": "test-request-id", + "site": { + "page": "https://good.site/url" + }, + "imp": [ + { + "id": "imp-id", + "native": { + "request": "{\"native\":{\"ver\":\"1.2\",\"api\":[1],\"battr\":[1,3,9],\"assets\":[{\"id\":0,\"required\":1,\"title\":{\"len\":25}},{\"id\":1,\"required\":1,\"img\":{\"type\":3,\"wmin\":100,\"hmin\":50}},{\"id\":2,\"required\":0,\"data\":{\"type\":2,\"len\":200}},{\"id\":3,\"required\":0,\"data\":{\"type\":12}},{\"id\":4,\"required\":0,\"data\":{\"type\":1}}]}}" + }, + "ext": { + "bidder": { + "pubname": "PUB123" + } + } + } + ] + }, + "impIDs": [ + "imp-id" + ] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "interactiveoffers", + "bid": [ + { + "id": "randomid", + "impid": "imp-id", + "price": 0.5, + "adid": "12345678", + "adm": "{\"native\":{\"ver\":\"1.2\",\"assets\":[{\"id\":0,\"title\":{\"text\":\"Test Title\"}},{\"id\":1,\"img\":{\"url\":\"http://some.image.url\",\"w\":100,\"h\":50}},{\"id\":2,\"data\":{\"type\":2,\"value\":\"Test Body\"}},{\"id\":3,\"data\":{\"type\":12,\"value\":\"Test Sponsored\"}},{\"id\":4,\"data\":{\"type\":1,\"value\":\"Test Display URL\"}}],\"link\":{\"url\":\"http://click.url\"},\"imptrackers\":[\"http://impression.url\"]}}", + "cid": "987", + "crid": "12345678", + "mtype": 4 + } + ] + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "randomid", + "impid": "imp-id", + "price": 0.5, + "adm": "{\"native\":{\"ver\":\"1.2\",\"assets\":[{\"id\":0,\"title\":{\"text\":\"Test Title\"}},{\"id\":1,\"img\":{\"url\":\"http://some.image.url\",\"w\":100,\"h\":50}},{\"id\":2,\"data\":{\"type\":2,\"value\":\"Test Body\"}},{\"id\":3,\"data\":{\"type\":12,\"value\":\"Test Sponsored\"}},{\"id\":4,\"data\":{\"type\":1,\"value\":\"Test Display URL\"}}],\"link\":{\"url\":\"http://click.url\"},\"imptrackers\":[\"http://impression.url\"]}}", + "adid": "12345678", + "cid": "987", + "crid": "12345678", + "mtype": 4 + }, + "type": "native" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/revx/revxtest/exemplary/simple-web-video.json b/adapters/revx/revxtest/exemplary/simple-web-video.json new file mode 100644 index 00000000000..0b397138693 --- /dev/null +++ b/adapters/revx/revxtest/exemplary/simple-web-video.json @@ -0,0 +1,118 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "page": "https://good.site/url" + }, + "imp": [ + { + "id": "imp-id", + "video": { + "mimes": [ + "application/x-mpegURL", + "video/mp4" + ], + "protocols": [ + 2, + 5 + ], + "w": 800, + "h": 600, + "placement": 1 + }, + "ext": { + "bidder": { + "pubname": "PUB123" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "prebid-use.atomex.net/ag=PUB123", + "body": { + "id": "test-request-id", + "site": { + "page": "https://good.site/url" + }, + "imp": [ + { + "id": "imp-id", + "video": { + "mimes": [ + "application/x-mpegURL", + "video/mp4" + ], + "protocols": [ + 2, + 5 + ], + "w": 800, + "h": 600, + "placement": 1 + }, + "ext": { + "bidder": { + "pubname": "PUB123" + } + } + } + ] + }, + "impIDs": [ + "imp-id" + ] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "interactiveoffers", + "bid": [ + { + "id": "randomid", + "impid": "imp-id", + "price": 0.5, + "adid": "12345678", + "adm": "", + "cid": "987", + "crid": "12345678", + "w": 800, + "h": 600, + "mtype": 2 + } + ] + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "randomid", + "impid": "imp-id", + "price": 0.5, + "adm": "", + "adid": "12345678", + "cid": "987", + "crid": "12345678", + "w": 800, + "h": 600, + "mtype": 2 + }, + "type": "video" + } + ] + } + ] +} diff --git a/adapters/revx/revxtest/supplemental/204.json b/adapters/revx/revxtest/supplemental/204.json new file mode 100644 index 00000000000..bbfab997069 --- /dev/null +++ b/adapters/revx/revxtest/supplemental/204.json @@ -0,0 +1,65 @@ +{ + "mockBidRequest": { + "app": { + "bundle": "com.example.app" + }, + "id": "req-id", + "device": { + "ifa": "9d8fe0a9-c0dd-4482-b16b-5709b00c608d", + "ip": "1.1.1.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" + }, + "imp": [ + { + "ext": { + "bidder": { + "pubname": "PUB123" + } + }, + "banner": { + "w": 111, + "h": 111 + }, + "id": "imp-id" + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "prebid-use.atomex.net/ag=PUB123", + "body": { + "app": { + "bundle": "com.example.app" + }, + "id": "req-id", + "device": { + "ifa": "9d8fe0a9-c0dd-4482-b16b-5709b00c608d", + "ip": "1.1.1.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" + }, + "imp": [ + { + "ext": { + "bidder": { + "pubname": "PUB123" + } + }, + "banner": { + "w": 111, + "h": 111 + }, + "id": "imp-id" + } + ] + }, + "impIDs": ["imp-id"] + }, + "mockResponse": { + "status": 204, + "body": {} + } + } + ], + "expectedBidResponses": [] +} diff --git a/adapters/revx/revxtest/supplemental/400.json b/adapters/revx/revxtest/supplemental/400.json new file mode 100644 index 00000000000..d44f79c901c --- /dev/null +++ b/adapters/revx/revxtest/supplemental/400.json @@ -0,0 +1,65 @@ +{ + "mockBidRequest": { + "app": { + "bundle": "com.example.app" + }, + "id": "req-id", + "device": { + "ifa": "9d8fe0a9-c0dd-4482-b16b-5709b00c608d", + "ip": "1.1.1.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" + }, + "imp": [ + { + "ext": { + "bidder": { + "pubname": "PUB123" + } + }, + "banner": { + "w": 111, + "h": 111 + }, + "id": "imp-id" + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "prebid-use.atomex.net/ag=PUB123", + "body": { + "app": { + "bundle": "com.example.app" + }, + "id": "req-id", + "device": { + "ifa": "9d8fe0a9-c0dd-4482-b16b-5709b00c608d", + "ip": "1.1.1.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" + }, + "imp": [ + { + "ext": { + "bidder": { + "pubname": "PUB123" + } + }, + "banner": { + "w": 111, + "h": 111 + }, + "id": "imp-id" + } + ] + }, + "impIDs": ["imp-id"] + }, + "mockResponse": { + "status": 400, + "body": "Invalid Request" + } + } + ], + "expectedBidResponses": [] +} diff --git a/adapters/revx/revxtest/supplemental/banner-format-coersion.json b/adapters/revx/revxtest/supplemental/banner-format-coersion.json new file mode 100644 index 00000000000..43c1e503250 --- /dev/null +++ b/adapters/revx/revxtest/supplemental/banner-format-coersion.json @@ -0,0 +1,81 @@ +{ + "mockBidRequest": { + "app": { + "bundle": "com.example.app" + }, + "id": "req-id", + "device": { + "ifa": "9d8fe0a9-c0dd-4482-b16b-5709b00c608d", + "ip": "1.1.1.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" + }, + "imp": [ + { + "id": "imp-id", + "banner": { + "format": [ + { + "w": 111, + "h": 111 + }, + { + "w": 111, + "h": 111 + } + ] + }, + "ext": { + "bidder": { + "pubname": "PUB123" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "prebid-use.atomex.net/ag=PUB123", + "body": { + "app": { + "bundle": "com.example.app" + }, + "id": "req-id", + "device": { + "ifa": "9d8fe0a9-c0dd-4482-b16b-5709b00c608d", + "ip": "1.1.1.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" + }, + "imp": [ + { + "id": "imp-id", + "banner": { + "format": [ + { + "w": 111, + "h": 111 + }, + { + "w": 111, + "h": 111 + } + ] + }, + "ext": { + "bidder": { + "pubname": "PUB123" + } + } + } + ] + }, + "impIDs": ["imp-id"] + }, + "mockResponse": { + "status": 204, + "body": {} + } + } + ], + "expectedBidResponses": [] +} diff --git a/adapters/revx/revxtest/supplemental/ext-unmarshal-err.json b/adapters/revx/revxtest/supplemental/ext-unmarshal-err.json new file mode 100644 index 00000000000..cd7d335a4da --- /dev/null +++ b/adapters/revx/revxtest/supplemental/ext-unmarshal-err.json @@ -0,0 +1,33 @@ +{ + "mockBidRequest": { + "id": "req-123", + "app": { + "bundle": "com.dummy.app" + }, + "imp": [ + { + "id": "imp-001", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "bidder": "- malformed bidder ext -" + } + } + ], + "device": { + "ip": "192.168.0.1", + "ifa": "abcd1234-5678-90ef-ghij-klmnopqrstuv", + "ua": "DummyUserAgent/1.0" + } + }, + "httpCalls": [], + "expectedBidResponses": [], + "expectedMakeRequestsErrors": [ + { + "value": "Publisher name missing", + "comparison": "literal" + } + ] +} diff --git a/adapters/revx/revxtest/supplemental/invalid-mtype.json b/adapters/revx/revxtest/supplemental/invalid-mtype.json new file mode 100644 index 00000000000..cfad8d4914c --- /dev/null +++ b/adapters/revx/revxtest/supplemental/invalid-mtype.json @@ -0,0 +1,94 @@ +{ + "mockBidRequest": { + "site": { + "page": "https://www.revx.io" + }, + "id": "req-id", + "device": { + "ip": "1.1.1.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" + }, + "imp": [ + { + "ext": { + "bidder": { + "pubname": "PUB123" + } + }, + "video": { + "w": 640, + "h": 360, + "mimes": ["video/mp4"] + }, + "id": "imp-id" + } + ] + }, + "httpCalls": [{ + "expectedRequest": { + "uri":"prebid-use.atomex.net/ag=PUB123", + "body": { + "site": { + "page": "https://www.revx.io" + }, + "id": "req-id", + "device": { + "ip": "1.1.1.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" + }, + "imp": [ + { + "ext": { + "bidder": { + "pubname": "PUB123" + } + }, + "video": { + "w": 640, + "h": 360, + "mimes": ["video/mp4"] + }, + "id": "imp-id" + } + ] + }, + "impIDs": ["imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "req-id", + "seatbid": [ + { + "bid": [ + { + "id": "1234", + "impid": "imp-id", + "price": 2.0, + "adm": "", + "crid": "123456789", + "adomain": ["example.com"], + "nurl": "https://tracking.url.com/event", + "mtype": 0, + "ext": { + "prebid": { + "meta": { + "networkName": "revx" + } + } + } + } + ] + } + ] + } + } + }], + "expectedBidResponses":[], + "expectedMakeBidsErrors":[ + { + "value":"Unsupported mtype 0 for bid 1234", + "comparison":"literal" + } + ] +} \ No newline at end of file diff --git a/adapters/revx/revxtest/supplemental/missing-plc-error.json b/adapters/revx/revxtest/supplemental/missing-plc-error.json new file mode 100644 index 00000000000..630f572a722 --- /dev/null +++ b/adapters/revx/revxtest/supplemental/missing-plc-error.json @@ -0,0 +1,34 @@ +{ + "mockBidRequest": { + "id": "req-id", + "app": { + "bundle": "com.example.app" + }, + "imp": [ + { + "id": "imp-id", + "banner": { + "w": 111, + "h": 111 + }, + "ext": { + "pubname": "" + } + } + + ], + "device": { + "ip": "1.1.1.1", + "ifa": "9d8fe0a9-c0dd-4482-b16b-5709b00c608d", + "ua": "Mozilla/5.0", + "os": "ios" + } + }, + "expectedMakeRequestsErrors": [ + { + "value": "Publisher name missing", + "comparison": "literal" + } + + ] +} diff --git a/adapters/revx/revxtest/supplemental/no-imp-error.json b/adapters/revx/revxtest/supplemental/no-imp-error.json new file mode 100644 index 00000000000..450171274b7 --- /dev/null +++ b/adapters/revx/revxtest/supplemental/no-imp-error.json @@ -0,0 +1,13 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [] + }, + "expectedMakeRequestsErrors": [ + { + "value": "No valid impressions for grid", + "comparison": "literal" + } + ], + "httpCalls":[] +} \ No newline at end of file diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go index 87821fd0c75..3993515df59 100755 --- a/exchange/adapter_builders.go +++ b/exchange/adapter_builders.go @@ -182,6 +182,7 @@ import ( "github.com/prebid/prebid-server/v3/adapters/relevantdigital" "github.com/prebid/prebid-server/v3/adapters/resetdigital" "github.com/prebid/prebid-server/v3/adapters/revcontent" + "github.com/prebid/prebid-server/v3/adapters/revx" "github.com/prebid/prebid-server/v3/adapters/richaudience" "github.com/prebid/prebid-server/v3/adapters/rise" "github.com/prebid/prebid-server/v3/adapters/roulax" @@ -434,6 +435,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder { openrtb_ext.BidderRelevantDigital: relevantdigital.Builder, openrtb_ext.BidderResetDigital: resetdigital.Builder, openrtb_ext.BidderRevcontent: revcontent.Builder, + openrtb_ext.BidderRevX: revx.Builder, openrtb_ext.BidderRichaudience: richaudience.Builder, openrtb_ext.BidderRise: rise.Builder, openrtb_ext.BidderRoulax: roulax.Builder, diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go index 67cf8e7c15e..7697ed1b379 100644 --- a/openrtb_ext/bidders.go +++ b/openrtb_ext/bidders.go @@ -261,6 +261,7 @@ var coreBidderNames []BidderName = []BidderName{ BidderZeroClickFraud, BidderZetaGlobalSsp, BidderZmaticoo, + BidderRevX, } func GetAliasBidderToParent() map[BidderName]BidderName { @@ -556,6 +557,7 @@ const ( BidderRelevantDigital BidderName = "relevantdigital" BidderResetDigital BidderName = "resetdigital" BidderRevcontent BidderName = "revcontent" + BidderRevX BidderName = "revx" BidderRichaudience BidderName = "richaudience" BidderRise BidderName = "rise" BidderRoulax BidderName = "roulax" diff --git a/openrtb_ext/imp_revx.go b/openrtb_ext/imp_revx.go new file mode 100644 index 00000000000..68a63b68ea8 --- /dev/null +++ b/openrtb_ext/imp_revx.go @@ -0,0 +1,5 @@ +package openrtb_ext + +type ExtImpRevX struct { + PubName string `json:"pubName"` // Publisher Name (used for dynamic URL building or analytics) +} diff --git a/static/bidder-info/revx.yaml b/static/bidder-info/revx.yaml new file mode 100644 index 00000000000..e6914160bb0 --- /dev/null +++ b/static/bidder-info/revx.yaml @@ -0,0 +1,24 @@ +# static/bidder-info/revx.yaml + +endpoint: "prebid-use.atomex.net?ag=%s" + +maintainer: + email: prebidsupport@revx.io + +gvlVendorID: 375 +gdpr: + enabled: true + consent_required: true + default_value: 0 # Default to 'no consent' if not provided + vendor_id: 100 # Vendor ID for your GDPR configuration +capabilities: + app: + mediaTypes: + - banner + - video + - native + site: + mediaTypes: + - banner + - video + - native diff --git a/static/bidder-params/revx.json b/static/bidder-params/revx.json new file mode 100644 index 00000000000..fdd6604c75d --- /dev/null +++ b/static/bidder-params/revx.json @@ -0,0 +1,15 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "RevX Adapter Params", + "description": "A schema which validates params accepted by the RevX adapter", + "type": "object", + "properties": { + "pubname": { + "type": "string", + "minLength": 1, + "description": "Required publisher identifier used for dynamic endpoint routing" + } + }, + "required": ["pubname"], + "additionalProperties": false +} From 690b4dc6bed1f1c8c58435a84b2b28c4523f25dc Mon Sep 17 00:00:00 2001 From: Nikitha Gaddam Date: Fri, 9 May 2025 11:49:05 +0530 Subject: [PATCH 02/13] fixing bug --- adapters/revx/revx.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/adapters/revx/revx.go b/adapters/revx/revx.go index 3c534eb7f05..19bfa9acc57 100644 --- a/adapters/revx/revx.go +++ b/adapters/revx/revx.go @@ -13,19 +13,19 @@ import ( ) // RevXAdapter struct -type RevXAdapter struct { +type adapter struct { endPoint string } // Builder builds a new instance of the RevX adapter. func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { - return &RevXAdapter{ + return &adapter{ endPoint: config.Endpoint, // Default endpoint }, nil } // MakeRequests handles the OpenRTB bid request and returns адаптер.RequestData -func (a *RevXAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { +func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { var requests []*adapters.RequestData var errors []error @@ -77,7 +77,7 @@ func (a *RevXAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapte } // MakeBids handles the OpenRTB bid response. -func (a *RevXAdapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { +func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { if externalRequest == nil { return nil, nil } From 92ee93d1b32655b30086ace738710c78326187f0 Mon Sep 17 00:00:00 2001 From: nikithacode Date: Tue, 10 Jun 2025 19:19:23 +0530 Subject: [PATCH 03/13] Update imp_revx.go --- openrtb_ext/imp_revx.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openrtb_ext/imp_revx.go b/openrtb_ext/imp_revx.go index 68a63b68ea8..e47612fb363 100644 --- a/openrtb_ext/imp_revx.go +++ b/openrtb_ext/imp_revx.go @@ -1,5 +1,5 @@ package openrtb_ext type ExtImpRevX struct { - PubName string `json:"pubName"` // Publisher Name (used for dynamic URL building or analytics) + PubName string `json:"pubName"` // Publisher Name (used for dynamic URL building) } From 59595e3e4176e384028c4ccfc6d2fd7f7ff03f7f Mon Sep 17 00:00:00 2001 From: Nikitha Gaddam Date: Thu, 3 Jul 2025 12:43:19 +0530 Subject: [PATCH 04/13] updated suggested changes --- adapters/revx/revx.go | 55 ++++++++++++++++-------------------- adapters/revx/revx_test.go | 5 ---- static/bidder-info/revx.yaml | 2 +- 3 files changed, 26 insertions(+), 36 deletions(-) diff --git a/adapters/revx/revx.go b/adapters/revx/revx.go index 19bfa9acc57..1160d4258ba 100644 --- a/adapters/revx/revx.go +++ b/adapters/revx/revx.go @@ -29,11 +29,6 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E var requests []*adapters.RequestData var errors []error - if len(request.Imp) == 0 { - return nil, []error{&errortypes.BadInput{ - Message: "No valid impressions for grid", - }} - } // Unmarshal imp.ext var bidderExt adapters.ExtImpBidder if err := jsonutil.Unmarshal(request.Imp[0].Ext, &bidderExt); err != nil { @@ -47,10 +42,6 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E } - // Check if publisher name is present - if len(revxExt.PubName) == 0 { - return nil, []error{&errortypes.BadInput{Message: "Publisher name missing"}} - } if len(requests) == 0 && len(errors) > 0 { return nil, errors } @@ -68,7 +59,7 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E } return []*adapters.RequestData{{ - Method: "POST", + Method: http.MethodPost, Uri: a.endPoint, Body: reqJson, Headers: headers, @@ -82,15 +73,13 @@ func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest return nil, nil } - // Treat 204 and 400 as no-bid without error - if response.StatusCode == http.StatusNoContent || response.StatusCode == http.StatusBadRequest { - return nil, nil - } - - if response.StatusCode != http.StatusOK { - return nil, []error{&errortypes.BadServerResponse{ - Message: fmt.Sprintf("Unexpected http status code: %d", response.StatusCode), - }} + // Check HTTP status before parsing response body + if err := CheckResponseStatusCodeForErrors(response); err != nil { + // Treat 204 and 400 as no-bid without logging error + if response.StatusCode == http.StatusNoContent || response.StatusCode == http.StatusBadRequest { + return nil, nil + } + return nil, []error{err} } var serverBidResponse openrtb2.BidResponse @@ -98,9 +87,7 @@ func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest return nil, []error{err} } - // Initialize a slice to hold valid bids var typedBids []*adapters.TypedBid - for _, sb := range serverBidResponse.SeatBid { for i := range sb.Bid { mediaType, err := getMediaTypeForImp(sb.Bid[i]) @@ -115,27 +102,18 @@ func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest } } - // If no valid bids, return nil, nil if len(typedBids) == 0 { return nil, nil } - // Create and populate the BidderResponse only if there are valid bids bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(typedBids)) bidResponse.Bids = typedBids bidResponse.Currency = serverBidResponse.Cur - // Return the response with valid bids return bidResponse, nil } func getMediaTypeForImp(bid openrtb2.Bid) (openrtb_ext.BidType, error) { - // Check if MType is 0 (invalid or missing media type) - if bid.MType == 0 { - return "", &errortypes.BadServerResponse{ - Message: fmt.Sprintf("Unsupported mtype %d for bid %s", bid.MType, bid.ID), - } - } switch bid.MType { case openrtb2.MarkupBanner: return openrtb_ext.BidTypeBanner, nil @@ -149,3 +127,20 @@ func getMediaTypeForImp(bid openrtb2.Bid) (openrtb_ext.BidType, error) { } } } + +// CheckResponseStatusCodeForErrors checks the HTTP response status code for errors. +func CheckResponseStatusCodeForErrors(response *adapters.ResponseData) error { + if response.StatusCode == http.StatusBadRequest { + return &errortypes.BadInput{ + Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode), + } + } + + if response.StatusCode != http.StatusOK { + return &errortypes.BadServerResponse{ + Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode), + } + } + + return nil +} diff --git a/adapters/revx/revx_test.go b/adapters/revx/revx_test.go index 35cd43dbf60..68275877cea 100644 --- a/adapters/revx/revx_test.go +++ b/adapters/revx/revx_test.go @@ -23,10 +23,5 @@ func TestJsonSamples(t *testing.T) { t.Logf("RevX Builder created successfully: %+v", bidder) } - adapterstest.RunJSONBidderTest(t, "revxtest", bidder) // Call it directly - - t.Logf("--- Finished TestJsonSamples for revxtest/exemplary/simple-app-banner.json ---") - adapterstest.RunJSONBidderTest(t, "revxtest", bidder) - } diff --git a/static/bidder-info/revx.yaml b/static/bidder-info/revx.yaml index e6914160bb0..f19e33179b2 100644 --- a/static/bidder-info/revx.yaml +++ b/static/bidder-info/revx.yaml @@ -1,6 +1,6 @@ # static/bidder-info/revx.yaml -endpoint: "prebid-use.atomex.net?ag=%s" +endpoint: "https://prebid-use.atomex.net" maintainer: email: prebidsupport@revx.io From 55b484eb8743c6d24edeb30dac56d2218dc29e7a Mon Sep 17 00:00:00 2001 From: Nikitha Gaddam Date: Thu, 3 Jul 2025 13:06:56 +0530 Subject: [PATCH 05/13] build fix --- adapters/revx/revx.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/adapters/revx/revx.go b/adapters/revx/revx.go index 1160d4258ba..1d611366aaf 100644 --- a/adapters/revx/revx.go +++ b/adapters/revx/revx.go @@ -29,17 +29,26 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E var requests []*adapters.RequestData var errors []error + if len(request.Imp) == 0 { + errors = append(errors, &errortypes.BadInput{Message: "No valid impressions for grid"}) + return nil, errors + } // Unmarshal imp.ext var bidderExt adapters.ExtImpBidder if err := jsonutil.Unmarshal(request.Imp[0].Ext, &bidderExt); err != nil { errors = append(errors, &errortypes.BadInput{Message: fmt.Sprintf("invalid imp.ext: %s", err)}) - + return nil, errors } var revxExt openrtb_ext.ExtImpRevX if err := jsonutil.Unmarshal(bidderExt.Bidder, &revxExt); err != nil { - errors = append(errors, &errortypes.BadInput{Message: "bad revx bidder ext"}) + errors = append(errors, &errortypes.BadInput{Message: "Publisher name missing"}) + return nil, errors + } + // Check if publisher name is present + if len(revxExt.PubName) == 0 { + return nil, []error{&errortypes.BadInput{Message: "Publisher name missing"}} } if len(requests) == 0 && len(errors) > 0 { From a0caa1aab104ce376c7c5dea0890103429bb0248 Mon Sep 17 00:00:00 2001 From: Nikitha Gaddam Date: Thu, 10 Jul 2025 11:07:05 +0530 Subject: [PATCH 06/13] revised review --- adapters/revx/revx.go | 54 ++++++++++++------------------------------- 1 file changed, 15 insertions(+), 39 deletions(-) diff --git a/adapters/revx/revx.go b/adapters/revx/revx.go index 1d611366aaf..d902b245c75 100644 --- a/adapters/revx/revx.go +++ b/adapters/revx/revx.go @@ -26,16 +26,17 @@ func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server co // MakeRequests handles the OpenRTB bid request and returns адаптер.RequestData func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { - var requests []*adapters.RequestData var errors []error - + // Defensive check: even if reviewer says avoid it, it's safe and prevents panics if len(request.Imp) == 0 { - errors = append(errors, &errortypes.BadInput{Message: "No valid impressions for grid"}) - return nil, errors + return nil, []error{&errortypes.BadInput{Message: "No valid impressions for grid"}} } - // Unmarshal imp.ext + + imp := request.Imp[0] + + // Parse imp.ext var bidderExt adapters.ExtImpBidder - if err := jsonutil.Unmarshal(request.Imp[0].Ext, &bidderExt); err != nil { + if err := jsonutil.Unmarshal(imp.Ext, &bidderExt); err != nil { errors = append(errors, &errortypes.BadInput{Message: fmt.Sprintf("invalid imp.ext: %s", err)}) return nil, errors } @@ -46,34 +47,26 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E return nil, errors } - // Check if publisher name is present - if len(revxExt.PubName) == 0 { - return nil, []error{&errortypes.BadInput{Message: "Publisher name missing"}} - } - - if len(requests) == 0 && len(errors) > 0 { - return nil, errors - } - - // Build dynamic endpoint - //var fendpoint = fmt.Sprintf(a.endPoint, strings.ToUpper(revxExt.PubName)) + // Build headers headers := http.Header{} headers.Add("Content-Type", "application/json;charset=utf-8") headers.Add("Accept", "application/json") - // Marshal the OpenRTB bid request into JSON + // Marshal request reqJson, err := jsonutil.Marshal(request) if err != nil { - return nil, []error{&errortypes.BadInput{Message: fmt.Sprintf("Failed to marshal request: %s", err)}} + return nil, []error{&errortypes.BadInput{Message: fmt.Sprintf("Failed to marshal request: %s", err)}} // skip append } - return []*adapters.RequestData{{ + requestData := &adapters.RequestData{ Method: http.MethodPost, Uri: a.endPoint, Body: reqJson, Headers: headers, ImpIDs: openrtb_ext.GetImpIDs(request.Imp), - }}, errors + } + + return []*adapters.RequestData{requestData}, errors } // MakeBids handles the OpenRTB bid response. @@ -83,7 +76,7 @@ func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest } // Check HTTP status before parsing response body - if err := CheckResponseStatusCodeForErrors(response); err != nil { + if err := adapters.CheckResponseStatusCodeForErrors(response); err != nil { // Treat 204 and 400 as no-bid without logging error if response.StatusCode == http.StatusNoContent || response.StatusCode == http.StatusBadRequest { return nil, nil @@ -136,20 +129,3 @@ func getMediaTypeForImp(bid openrtb2.Bid) (openrtb_ext.BidType, error) { } } } - -// CheckResponseStatusCodeForErrors checks the HTTP response status code for errors. -func CheckResponseStatusCodeForErrors(response *adapters.ResponseData) error { - if response.StatusCode == http.StatusBadRequest { - return &errortypes.BadInput{ - Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode), - } - } - - if response.StatusCode != http.StatusOK { - return &errortypes.BadServerResponse{ - Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode), - } - } - - return nil -} From 7fcf91d32c78e6a814b2171de9261cf8a1cfa159 Mon Sep 17 00:00:00 2001 From: Nikitha Gaddam Date: Tue, 15 Jul 2025 17:52:41 +0530 Subject: [PATCH 07/13] RevX Adapter: Handle 400 BadRequest properly in MakeBids --- adapters/revx/revx.go | 19 ++++++++++++++----- adapters/revx/revxtest/supplemental/400.json | 8 +++++++- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/adapters/revx/revx.go b/adapters/revx/revx.go index d902b245c75..a32679dfa71 100644 --- a/adapters/revx/revx.go +++ b/adapters/revx/revx.go @@ -75,15 +75,24 @@ func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest return nil, nil } - // Check HTTP status before parsing response body + // Handle specific status codes first + if response.StatusCode == http.StatusNoContent { + return nil, nil + } + + if response.StatusCode == http.StatusBadRequest { + // ✅ Return error to log 400 metrics + return nil, []error{&errortypes.BadServerResponse{ + Message: fmt.Sprintf("Received 400 Bad Request from endpoint: %s", a.endPoint), + }} + } + + // For all other status codes if err := adapters.CheckResponseStatusCodeForErrors(response); err != nil { - // Treat 204 and 400 as no-bid without logging error - if response.StatusCode == http.StatusNoContent || response.StatusCode == http.StatusBadRequest { - return nil, nil - } return nil, []error{err} } + // Proceed with normal parsing var serverBidResponse openrtb2.BidResponse if err := jsonutil.Unmarshal(response.Body, &serverBidResponse); err != nil { return nil, []error{err} diff --git a/adapters/revx/revxtest/supplemental/400.json b/adapters/revx/revxtest/supplemental/400.json index d44f79c901c..f3a98176023 100644 --- a/adapters/revx/revxtest/supplemental/400.json +++ b/adapters/revx/revxtest/supplemental/400.json @@ -61,5 +61,11 @@ } } ], - "expectedBidResponses": [] + "expectedBidResponses": [], + "expectedMakeBidsErrors": [ + { + "value": "Received 400 Bad Request from endpoint", + "comparison": "startswith" + } + ] } From b2971346d9a23caea09d91f8801c89898d4dea77 Mon Sep 17 00:00:00 2001 From: Asif Abdu Rahiman Date: Tue, 19 Aug 2025 21:01:00 +0530 Subject: [PATCH 08/13] Added required changes --- adapters/revx/revx.go | 12 ++++-------- .../revx/revxtest/supplemental/no-imp-error.json | 13 ------------- 2 files changed, 4 insertions(+), 21 deletions(-) delete mode 100644 adapters/revx/revxtest/supplemental/no-imp-error.json diff --git a/adapters/revx/revx.go b/adapters/revx/revx.go index a32679dfa71..75a0671f339 100644 --- a/adapters/revx/revx.go +++ b/adapters/revx/revx.go @@ -27,11 +27,6 @@ func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server co // MakeRequests handles the OpenRTB bid request and returns адаптер.RequestData func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { var errors []error - // Defensive check: even if reviewer says avoid it, it's safe and prevents panics - if len(request.Imp) == 0 { - return nil, []error{&errortypes.BadInput{Message: "No valid impressions for grid"}} - } - imp := request.Imp[0] // Parse imp.ext @@ -99,13 +94,14 @@ func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest } var typedBids []*adapters.TypedBid + var errs []error for _, sb := range serverBidResponse.SeatBid { for i := range sb.Bid { mediaType, err := getMediaTypeForImp(sb.Bid[i]) if err != nil { - return nil, []error{err} + errs = append(errs, err) + continue } - typedBids = append(typedBids, &adapters.TypedBid{ Bid: &sb.Bid[i], BidType: mediaType, @@ -114,7 +110,7 @@ func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest } if len(typedBids) == 0 { - return nil, nil + return nil, errs } bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(typedBids)) diff --git a/adapters/revx/revxtest/supplemental/no-imp-error.json b/adapters/revx/revxtest/supplemental/no-imp-error.json deleted file mode 100644 index 450171274b7..00000000000 --- a/adapters/revx/revxtest/supplemental/no-imp-error.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "mockBidRequest": { - "id": "test-request-id", - "imp": [] - }, - "expectedMakeRequestsErrors": [ - { - "value": "No valid impressions for grid", - "comparison": "literal" - } - ], - "httpCalls":[] -} \ No newline at end of file From 168eabd7f8bf5f54b615adb210038ebbbb4aa76e Mon Sep 17 00:00:00 2001 From: Asif Abdu Rahiman Date: Mon, 15 Sep 2025 15:59:42 +0530 Subject: [PATCH 09/13] Added requested suppliumental test files --- adapters/revx/revx.go | 16 ++++- .../{204.json => 204Response.json} | 0 .../{400.json => 400Response.json} | 4 +- .../revxtest/supplemental/500Response.json | 71 ++++++++++++++++++ .../supplemental/external_request_null.json | 10 +++ ...arshal-err.json => imp_ext_unmarshal.json} | 8 +-- .../response_unmarshal_error.json | 72 +++++++++++++++++++ 7 files changed, 173 insertions(+), 8 deletions(-) rename adapters/revx/revxtest/supplemental/{204.json => 204Response.json} (100%) rename adapters/revx/revxtest/supplemental/{400.json => 400Response.json} (93%) create mode 100644 adapters/revx/revxtest/supplemental/500Response.json create mode 100644 adapters/revx/revxtest/supplemental/external_request_null.json rename adapters/revx/revxtest/supplemental/{ext-unmarshal-err.json => imp_ext_unmarshal.json} (80%) create mode 100644 adapters/revx/revxtest/supplemental/response_unmarshal_error.json diff --git a/adapters/revx/revx.go b/adapters/revx/revx.go index 75a0671f339..aa748460936 100644 --- a/adapters/revx/revx.go +++ b/adapters/revx/revx.go @@ -27,6 +27,21 @@ func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server co // MakeRequests handles the OpenRTB bid request and returns адаптер.RequestData func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { var errors []error + if request == nil { + errors = append(errors, &errortypes.BadInput{ + Message: "request cannot be nil", + }) + return nil, errors + } + + // Validate impression array + if len(request.Imp) == 0 { + errors = append(errors, &errortypes.BadInput{ + Message: "no impression objects provided in request", + }) + return nil, errors + } + imp := request.Imp[0] // Parse imp.ext @@ -76,7 +91,6 @@ func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest } if response.StatusCode == http.StatusBadRequest { - // ✅ Return error to log 400 metrics return nil, []error{&errortypes.BadServerResponse{ Message: fmt.Sprintf("Received 400 Bad Request from endpoint: %s", a.endPoint), }} diff --git a/adapters/revx/revxtest/supplemental/204.json b/adapters/revx/revxtest/supplemental/204Response.json similarity index 100% rename from adapters/revx/revxtest/supplemental/204.json rename to adapters/revx/revxtest/supplemental/204Response.json diff --git a/adapters/revx/revxtest/supplemental/400.json b/adapters/revx/revxtest/supplemental/400Response.json similarity index 93% rename from adapters/revx/revxtest/supplemental/400.json rename to adapters/revx/revxtest/supplemental/400Response.json index f3a98176023..b57bd227e6c 100644 --- a/adapters/revx/revxtest/supplemental/400.json +++ b/adapters/revx/revxtest/supplemental/400Response.json @@ -64,8 +64,8 @@ "expectedBidResponses": [], "expectedMakeBidsErrors": [ { - "value": "Received 400 Bad Request from endpoint", - "comparison": "startswith" + "value": "Received 400 Bad Request from endpoint: prebid-use.atomex.net/ag=PUB123", + "comparison": "literal" } ] } diff --git a/adapters/revx/revxtest/supplemental/500Response.json b/adapters/revx/revxtest/supplemental/500Response.json new file mode 100644 index 00000000000..64ed16db8df --- /dev/null +++ b/adapters/revx/revxtest/supplemental/500Response.json @@ -0,0 +1,71 @@ +{ + "mockBidRequest": { + "app": { + "bundle": "com.example.app" + }, + "id": "req-id", + "device": { + "ifa": "9d8fe0a9-c0dd-4482-b16b-5709b00c608d", + "ip": "1.1.1.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" + }, + "imp": [ + { + "ext": { + "bidder": { + "pubname": "PUB123" + } + }, + "banner": { + "w": 111, + "h": 111 + }, + "id": "imp-id" + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "prebid-use.atomex.net/ag=PUB123", + "body": { + "app": { + "bundle": "com.example.app" + }, + "id": "req-id", + "device": { + "ifa": "9d8fe0a9-c0dd-4482-b16b-5709b00c608d", + "ip": "1.1.1.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" + }, + "imp": [ + { + "ext": { + "bidder": { + "pubname": "PUB123" + } + }, + "banner": { + "w": 111, + "h": 111 + }, + "id": "imp-id" + } + ] + }, + "impIDs": ["imp-id"] + }, + "mockResponse": { + "status": 500, + "body": "Invalid Request" + } + } + ], + "expectedBidResponses": [], + "expectedMakeBidsErrors": [ + { + "value": "Unexpected status code: 500. Run with request.debug = 1 for more info", + "comparison": "literal" + } + ] +} diff --git a/adapters/revx/revxtest/supplemental/external_request_null.json b/adapters/revx/revxtest/supplemental/external_request_null.json new file mode 100644 index 00000000000..3575ccaed81 --- /dev/null +++ b/adapters/revx/revxtest/supplemental/external_request_null.json @@ -0,0 +1,10 @@ +{ + "mockBidRequest": null, + "httpCalls": [], + "expectedMakeRequestsErrors": [ + { + "value": "no impression objects provided in request", + "comparison": "literal" + } + ] +} \ No newline at end of file diff --git a/adapters/revx/revxtest/supplemental/ext-unmarshal-err.json b/adapters/revx/revxtest/supplemental/imp_ext_unmarshal.json similarity index 80% rename from adapters/revx/revxtest/supplemental/ext-unmarshal-err.json rename to adapters/revx/revxtest/supplemental/imp_ext_unmarshal.json index cd7d335a4da..4771cf4f595 100644 --- a/adapters/revx/revxtest/supplemental/ext-unmarshal-err.json +++ b/adapters/revx/revxtest/supplemental/imp_ext_unmarshal.json @@ -11,9 +11,7 @@ "w": 300, "h": 250 }, - "ext": { - "bidder": "- malformed bidder ext -" - } + "ext": "- malformed bidder ext -" } ], "device": { @@ -26,8 +24,8 @@ "expectedBidResponses": [], "expectedMakeRequestsErrors": [ { - "value": "Publisher name missing", + "value": "invalid imp.ext: expect { or n, but found \"", "comparison": "literal" } ] -} +} \ No newline at end of file diff --git a/adapters/revx/revxtest/supplemental/response_unmarshal_error.json b/adapters/revx/revxtest/supplemental/response_unmarshal_error.json new file mode 100644 index 00000000000..9cf5b5322ca --- /dev/null +++ b/adapters/revx/revxtest/supplemental/response_unmarshal_error.json @@ -0,0 +1,72 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "page": "https://good.site/url" + }, + "imp": [ + { + "id": "imp-id", + "banner": { + "format": [ + { + "w": 111, + "h": 111 + } + ] + }, + "ext": { + "bidder": { + "pubname": "PUB123" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "prebid-use.atomex.net/ag=PUB123", + + "body": { + "id": "test-request-id", + "site": { + "page": "https://good.site/url" + }, + "imp": [ + { + "id": "imp-id", + "banner": { + "format": [ + { + "w": 111, + "h": 111 + } + ] + }, + "ext": { + "bidder": { + "pubname": "PUB123" + } + } + } + ] + }, + "impIDs": [ + "imp-id" + ] + }, + "mockResponse": { + "status": 200, + "body": "incorrect response body" + } + } + ], + "expectedBidResponses": [], + "expectedMakeBidsErrors": [ + { + "value": "expect { or n, but found \"", + "comparison": "literal" + } + ] +} \ No newline at end of file From 50c53920df9307acdd54f9fa045e3356c0dea1e1 Mon Sep 17 00:00:00 2001 From: Asif Abdu Rahiman Date: Thu, 25 Sep 2025 13:56:10 +0530 Subject: [PATCH 10/13] Added review comments --- adapters/revx/revx.go | 29 ------ .../supplemental/external_request_null.json | 10 -- .../supplemental/imp_ext_unmarshal.json | 31 ------ .../supplemental/invalid-mtype copy.json | 94 +++++++++++++++++++ .../supplemental/missing-plc-error.json | 34 ------- static/bidder-info/revx.yaml | 7 -- 6 files changed, 94 insertions(+), 111 deletions(-) delete mode 100644 adapters/revx/revxtest/supplemental/external_request_null.json delete mode 100644 adapters/revx/revxtest/supplemental/imp_ext_unmarshal.json create mode 100644 adapters/revx/revxtest/supplemental/invalid-mtype copy.json delete mode 100644 adapters/revx/revxtest/supplemental/missing-plc-error.json diff --git a/adapters/revx/revx.go b/adapters/revx/revx.go index aa748460936..eb0886499d4 100644 --- a/adapters/revx/revx.go +++ b/adapters/revx/revx.go @@ -27,35 +27,6 @@ func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server co // MakeRequests handles the OpenRTB bid request and returns адаптер.RequestData func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { var errors []error - if request == nil { - errors = append(errors, &errortypes.BadInput{ - Message: "request cannot be nil", - }) - return nil, errors - } - - // Validate impression array - if len(request.Imp) == 0 { - errors = append(errors, &errortypes.BadInput{ - Message: "no impression objects provided in request", - }) - return nil, errors - } - - imp := request.Imp[0] - - // Parse imp.ext - var bidderExt adapters.ExtImpBidder - if err := jsonutil.Unmarshal(imp.Ext, &bidderExt); err != nil { - errors = append(errors, &errortypes.BadInput{Message: fmt.Sprintf("invalid imp.ext: %s", err)}) - return nil, errors - } - - var revxExt openrtb_ext.ExtImpRevX - if err := jsonutil.Unmarshal(bidderExt.Bidder, &revxExt); err != nil { - errors = append(errors, &errortypes.BadInput{Message: "Publisher name missing"}) - return nil, errors - } // Build headers headers := http.Header{} diff --git a/adapters/revx/revxtest/supplemental/external_request_null.json b/adapters/revx/revxtest/supplemental/external_request_null.json deleted file mode 100644 index 3575ccaed81..00000000000 --- a/adapters/revx/revxtest/supplemental/external_request_null.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "mockBidRequest": null, - "httpCalls": [], - "expectedMakeRequestsErrors": [ - { - "value": "no impression objects provided in request", - "comparison": "literal" - } - ] -} \ No newline at end of file diff --git a/adapters/revx/revxtest/supplemental/imp_ext_unmarshal.json b/adapters/revx/revxtest/supplemental/imp_ext_unmarshal.json deleted file mode 100644 index 4771cf4f595..00000000000 --- a/adapters/revx/revxtest/supplemental/imp_ext_unmarshal.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "mockBidRequest": { - "id": "req-123", - "app": { - "bundle": "com.dummy.app" - }, - "imp": [ - { - "id": "imp-001", - "banner": { - "w": 300, - "h": 250 - }, - "ext": "- malformed bidder ext -" - } - ], - "device": { - "ip": "192.168.0.1", - "ifa": "abcd1234-5678-90ef-ghij-klmnopqrstuv", - "ua": "DummyUserAgent/1.0" - } - }, - "httpCalls": [], - "expectedBidResponses": [], - "expectedMakeRequestsErrors": [ - { - "value": "invalid imp.ext: expect { or n, but found \"", - "comparison": "literal" - } - ] -} \ No newline at end of file diff --git a/adapters/revx/revxtest/supplemental/invalid-mtype copy.json b/adapters/revx/revxtest/supplemental/invalid-mtype copy.json new file mode 100644 index 00000000000..cfad8d4914c --- /dev/null +++ b/adapters/revx/revxtest/supplemental/invalid-mtype copy.json @@ -0,0 +1,94 @@ +{ + "mockBidRequest": { + "site": { + "page": "https://www.revx.io" + }, + "id": "req-id", + "device": { + "ip": "1.1.1.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" + }, + "imp": [ + { + "ext": { + "bidder": { + "pubname": "PUB123" + } + }, + "video": { + "w": 640, + "h": 360, + "mimes": ["video/mp4"] + }, + "id": "imp-id" + } + ] + }, + "httpCalls": [{ + "expectedRequest": { + "uri":"prebid-use.atomex.net/ag=PUB123", + "body": { + "site": { + "page": "https://www.revx.io" + }, + "id": "req-id", + "device": { + "ip": "1.1.1.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" + }, + "imp": [ + { + "ext": { + "bidder": { + "pubname": "PUB123" + } + }, + "video": { + "w": 640, + "h": 360, + "mimes": ["video/mp4"] + }, + "id": "imp-id" + } + ] + }, + "impIDs": ["imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "req-id", + "seatbid": [ + { + "bid": [ + { + "id": "1234", + "impid": "imp-id", + "price": 2.0, + "adm": "", + "crid": "123456789", + "adomain": ["example.com"], + "nurl": "https://tracking.url.com/event", + "mtype": 0, + "ext": { + "prebid": { + "meta": { + "networkName": "revx" + } + } + } + } + ] + } + ] + } + } + }], + "expectedBidResponses":[], + "expectedMakeBidsErrors":[ + { + "value":"Unsupported mtype 0 for bid 1234", + "comparison":"literal" + } + ] +} \ No newline at end of file diff --git a/adapters/revx/revxtest/supplemental/missing-plc-error.json b/adapters/revx/revxtest/supplemental/missing-plc-error.json deleted file mode 100644 index 630f572a722..00000000000 --- a/adapters/revx/revxtest/supplemental/missing-plc-error.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "mockBidRequest": { - "id": "req-id", - "app": { - "bundle": "com.example.app" - }, - "imp": [ - { - "id": "imp-id", - "banner": { - "w": 111, - "h": 111 - }, - "ext": { - "pubname": "" - } - } - - ], - "device": { - "ip": "1.1.1.1", - "ifa": "9d8fe0a9-c0dd-4482-b16b-5709b00c608d", - "ua": "Mozilla/5.0", - "os": "ios" - } - }, - "expectedMakeRequestsErrors": [ - { - "value": "Publisher name missing", - "comparison": "literal" - } - - ] -} diff --git a/static/bidder-info/revx.yaml b/static/bidder-info/revx.yaml index f19e33179b2..e023964f443 100644 --- a/static/bidder-info/revx.yaml +++ b/static/bidder-info/revx.yaml @@ -1,16 +1,9 @@ -# static/bidder-info/revx.yaml - endpoint: "https://prebid-use.atomex.net" maintainer: email: prebidsupport@revx.io gvlVendorID: 375 -gdpr: - enabled: true - consent_required: true - default_value: 0 # Default to 'no consent' if not provided - vendor_id: 100 # Vendor ID for your GDPR configuration capabilities: app: mediaTypes: From cfa88b30ab74846d9e491dbb468f41482ba9ebec Mon Sep 17 00:00:00 2001 From: Asif Abdu Rahiman Date: Wed, 29 Oct 2025 23:54:50 +0530 Subject: [PATCH 11/13] Added review comments --- adapters/revx/revx_external_null_test.go | 35 +++++++ .../supplemental/banner-format-coersion.json | 81 ---------------- .../supplemental/invalid-mtype copy.json | 94 ------------------- 3 files changed, 35 insertions(+), 175 deletions(-) create mode 100644 adapters/revx/revx_external_null_test.go delete mode 100644 adapters/revx/revxtest/supplemental/banner-format-coersion.json delete mode 100644 adapters/revx/revxtest/supplemental/invalid-mtype copy.json diff --git a/adapters/revx/revx_external_null_test.go b/adapters/revx/revx_external_null_test.go new file mode 100644 index 00000000000..0b3f5ed32f3 --- /dev/null +++ b/adapters/revx/revx_external_null_test.go @@ -0,0 +1,35 @@ +package revx_test + +import ( + "testing" + + "github.com/prebid/openrtb/v20/openrtb2" + "github.com/prebid/prebid-server/v3/adapters" + "github.com/prebid/prebid-server/v3/adapters/revx" + "github.com/prebid/prebid-server/v3/config" + "github.com/prebid/prebid-server/v3/openrtb_ext" + "github.com/stretchr/testify/assert" +) + +func TestMakeBids_NilExternalRequest(t *testing.T) { + // Arrange + bidder, buildErr := revx.Builder(openrtb_ext.BidderRevX, config.Adapter{ + Endpoint: "prebid-use.atomex.net/ag=PUB123", + }, config.Server{ + ExternalUrl: "http://hosturl.com", + GvlID: 375, + DataCenter: "2", + }) + + var internalReq *openrtb2.BidRequest + var response *adapters.ResponseData + if buildErr != nil { + t.Logf("RevX Builder created successfully: %+v", bidder) + } + // Act + bidderResponse, errs := bidder.MakeBids(internalReq, nil, response) + + // Assert + assert.Nil(t, bidderResponse, "Expected bidderResponse to be nil when externalRequest is nil") + assert.Nil(t, errs, "Expected errors to be nil when externalRequest is nil") +} diff --git a/adapters/revx/revxtest/supplemental/banner-format-coersion.json b/adapters/revx/revxtest/supplemental/banner-format-coersion.json deleted file mode 100644 index 43c1e503250..00000000000 --- a/adapters/revx/revxtest/supplemental/banner-format-coersion.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "mockBidRequest": { - "app": { - "bundle": "com.example.app" - }, - "id": "req-id", - "device": { - "ifa": "9d8fe0a9-c0dd-4482-b16b-5709b00c608d", - "ip": "1.1.1.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" - }, - "imp": [ - { - "id": "imp-id", - "banner": { - "format": [ - { - "w": 111, - "h": 111 - }, - { - "w": 111, - "h": 111 - } - ] - }, - "ext": { - "bidder": { - "pubname": "PUB123" - } - } - } - ] - }, - "httpCalls": [ - { - "expectedRequest": { - "uri": "prebid-use.atomex.net/ag=PUB123", - "body": { - "app": { - "bundle": "com.example.app" - }, - "id": "req-id", - "device": { - "ifa": "9d8fe0a9-c0dd-4482-b16b-5709b00c608d", - "ip": "1.1.1.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" - }, - "imp": [ - { - "id": "imp-id", - "banner": { - "format": [ - { - "w": 111, - "h": 111 - }, - { - "w": 111, - "h": 111 - } - ] - }, - "ext": { - "bidder": { - "pubname": "PUB123" - } - } - } - ] - }, - "impIDs": ["imp-id"] - }, - "mockResponse": { - "status": 204, - "body": {} - } - } - ], - "expectedBidResponses": [] -} diff --git a/adapters/revx/revxtest/supplemental/invalid-mtype copy.json b/adapters/revx/revxtest/supplemental/invalid-mtype copy.json deleted file mode 100644 index cfad8d4914c..00000000000 --- a/adapters/revx/revxtest/supplemental/invalid-mtype copy.json +++ /dev/null @@ -1,94 +0,0 @@ -{ - "mockBidRequest": { - "site": { - "page": "https://www.revx.io" - }, - "id": "req-id", - "device": { - "ip": "1.1.1.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" - }, - "imp": [ - { - "ext": { - "bidder": { - "pubname": "PUB123" - } - }, - "video": { - "w": 640, - "h": 360, - "mimes": ["video/mp4"] - }, - "id": "imp-id" - } - ] - }, - "httpCalls": [{ - "expectedRequest": { - "uri":"prebid-use.atomex.net/ag=PUB123", - "body": { - "site": { - "page": "https://www.revx.io" - }, - "id": "req-id", - "device": { - "ip": "1.1.1.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" - }, - "imp": [ - { - "ext": { - "bidder": { - "pubname": "PUB123" - } - }, - "video": { - "w": 640, - "h": 360, - "mimes": ["video/mp4"] - }, - "id": "imp-id" - } - ] - }, - "impIDs": ["imp-id"] - }, - "mockResponse": { - "status": 200, - "body": { - "id": "req-id", - "seatbid": [ - { - "bid": [ - { - "id": "1234", - "impid": "imp-id", - "price": 2.0, - "adm": "", - "crid": "123456789", - "adomain": ["example.com"], - "nurl": "https://tracking.url.com/event", - "mtype": 0, - "ext": { - "prebid": { - "meta": { - "networkName": "revx" - } - } - } - } - ] - } - ] - } - } - }], - "expectedBidResponses":[], - "expectedMakeBidsErrors":[ - { - "value":"Unsupported mtype 0 for bid 1234", - "comparison":"literal" - } - ] -} \ No newline at end of file From 5e42423ac416c4792b7e4d0867b1647047d3e05b Mon Sep 17 00:00:00 2001 From: Asif Abdu Rahiman Date: Wed, 21 Jan 2026 15:01:12 +0530 Subject: [PATCH 12/13] Added name of aggregator and removed required param check --- adapters/revx/params_test.go | 43 ---------------------------------- static/bidder-info/revx.yaml | 2 +- static/bidder-params/revx.json | 10 +------- 3 files changed, 2 insertions(+), 53 deletions(-) delete mode 100644 adapters/revx/params_test.go diff --git a/adapters/revx/params_test.go b/adapters/revx/params_test.go deleted file mode 100644 index d81c85f382a..00000000000 --- a/adapters/revx/params_test.go +++ /dev/null @@ -1,43 +0,0 @@ -package revx - -import ( - "encoding/json" - "testing" - - "github.com/prebid/prebid-server/v3/openrtb_ext" -) - -func TestValidParams(t *testing.T) { - validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") - if err != nil { - t.Fatalf("Failed to load JSON schemas: %v", err) - } - - for _, validParam := range validParams { - if err := validator.Validate(openrtb_ext.BidderRevX, json.RawMessage(validParam)); err != nil { - t.Errorf("Schema rejected valid RevX params: %s\nError: %s", validParam, err) - } - } -} - -func TestInvalidParams(t *testing.T) { - validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") - if err != nil { - t.Fatalf("Failed to load JSON schemas: %v", err) - } - - for _, invalidParam := range invalidParams { - if err := validator.Validate(openrtb_ext.BidderRevX, json.RawMessage(invalidParam)); err == nil { - t.Errorf("Schema accepted invalid RevX params: %s", invalidParam) - } - } -} - -var validParams = []string{ - `{"pubname": "publisher123"}`, -} - -var invalidParams = []string{ - `{}`, - `{ "pubname": ""}`, -} diff --git a/static/bidder-info/revx.yaml b/static/bidder-info/revx.yaml index e023964f443..ca773180b39 100644 --- a/static/bidder-info/revx.yaml +++ b/static/bidder-info/revx.yaml @@ -1,4 +1,4 @@ -endpoint: "https://prebid-use.atomex.net" +endpoint: "https://prebid-use.atomex.net?ag=PREBID" maintainer: email: prebidsupport@revx.io diff --git a/static/bidder-params/revx.json b/static/bidder-params/revx.json index fdd6604c75d..7ed0ec5ea3f 100644 --- a/static/bidder-params/revx.json +++ b/static/bidder-params/revx.json @@ -3,13 +3,5 @@ "title": "RevX Adapter Params", "description": "A schema which validates params accepted by the RevX adapter", "type": "object", - "properties": { - "pubname": { - "type": "string", - "minLength": 1, - "description": "Required publisher identifier used for dynamic endpoint routing" - } - }, - "required": ["pubname"], - "additionalProperties": false + "properties": {} } From a684190478cd8affce6d311509369953de11ab94 Mon Sep 17 00:00:00 2001 From: Asif Abdu Rahiman Date: Tue, 3 Feb 2026 22:16:36 +0530 Subject: [PATCH 13/13] Updated as per review comments --- adapters/revx/revx.go | 10 ++-------- adapters/revx/revxtest/supplemental/400Response.json | 2 +- openrtb_ext/bidders.go | 2 +- openrtb_ext/imp_revx.go | 5 ----- static/bidder-info/revx.yaml | 4 +--- 5 files changed, 5 insertions(+), 18 deletions(-) delete mode 100644 openrtb_ext/imp_revx.go diff --git a/adapters/revx/revx.go b/adapters/revx/revx.go index eb0886499d4..e18c23b5602 100644 --- a/adapters/revx/revx.go +++ b/adapters/revx/revx.go @@ -57,16 +57,10 @@ func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest } // Handle specific status codes first - if response.StatusCode == http.StatusNoContent { + if adapters.IsResponseStatusCodeNoContent(response) { return nil, nil } - if response.StatusCode == http.StatusBadRequest { - return nil, []error{&errortypes.BadServerResponse{ - Message: fmt.Sprintf("Received 400 Bad Request from endpoint: %s", a.endPoint), - }} - } - // For all other status codes if err := adapters.CheckResponseStatusCodeForErrors(response); err != nil { return nil, []error{err} @@ -102,7 +96,7 @@ func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest bidResponse.Bids = typedBids bidResponse.Currency = serverBidResponse.Cur - return bidResponse, nil + return bidResponse, errs } func getMediaTypeForImp(bid openrtb2.Bid) (openrtb_ext.BidType, error) { diff --git a/adapters/revx/revxtest/supplemental/400Response.json b/adapters/revx/revxtest/supplemental/400Response.json index b57bd227e6c..2d3785503e7 100644 --- a/adapters/revx/revxtest/supplemental/400Response.json +++ b/adapters/revx/revxtest/supplemental/400Response.json @@ -64,7 +64,7 @@ "expectedBidResponses": [], "expectedMakeBidsErrors": [ { - "value": "Received 400 Bad Request from endpoint: prebid-use.atomex.net/ag=PUB123", + "value": "Unexpected status code: 400. Run with request.debug = 1 for more info", "comparison": "literal" } ] diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go index 7697ed1b379..efc734ea29c 100644 --- a/openrtb_ext/bidders.go +++ b/openrtb_ext/bidders.go @@ -200,6 +200,7 @@ var coreBidderNames []BidderName = []BidderName{ BidderRelevantDigital, BidderResetDigital, BidderRevcontent, + BidderRevX, BidderRichaudience, BidderRise, BidderRoulax, @@ -261,7 +262,6 @@ var coreBidderNames []BidderName = []BidderName{ BidderZeroClickFraud, BidderZetaGlobalSsp, BidderZmaticoo, - BidderRevX, } func GetAliasBidderToParent() map[BidderName]BidderName { diff --git a/openrtb_ext/imp_revx.go b/openrtb_ext/imp_revx.go deleted file mode 100644 index e47612fb363..00000000000 --- a/openrtb_ext/imp_revx.go +++ /dev/null @@ -1,5 +0,0 @@ -package openrtb_ext - -type ExtImpRevX struct { - PubName string `json:"pubName"` // Publisher Name (used for dynamic URL building) -} diff --git a/static/bidder-info/revx.yaml b/static/bidder-info/revx.yaml index ca773180b39..cf745dd1b9f 100644 --- a/static/bidder-info/revx.yaml +++ b/static/bidder-info/revx.yaml @@ -1,8 +1,6 @@ endpoint: "https://prebid-use.atomex.net?ag=PREBID" - maintainer: email: prebidsupport@revx.io - gvlVendorID: 375 capabilities: app: @@ -14,4 +12,4 @@ capabilities: mediaTypes: - banner - video - - native + - native \ No newline at end of file