From 0b0bf7bd3b0c245147f1e7868f9f2cdb09b5fff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Ge=C3=9Fner?= Date: Fri, 13 Dec 2024 01:05:51 +0100 Subject: [PATCH 01/12] Import initial version of FeedAd PBS adapter --- adapters/feedad/feedad.go | 105 +++++++++ adapters/feedad/feedad_test.go | 25 +++ .../feedadtest/exemplary/banner-app.json | 161 ++++++++++++++ .../feedadtest/exemplary/banner-web.json | 207 ++++++++++++++++++ adapters/feedad/params_test.go | 122 +++++++++++ exchange/adapter_builders.go | 2 + openrtb_ext/bidders.go | 2 + openrtb_ext/imp_feedad.go | 17 ++ static/bidder-info/feedad.yaml | 17 ++ static/bidder-params/feedad.json | 65 ++++++ 10 files changed, 723 insertions(+) create mode 100644 adapters/feedad/feedad.go create mode 100644 adapters/feedad/feedad_test.go create mode 100644 adapters/feedad/feedadtest/exemplary/banner-app.json create mode 100644 adapters/feedad/feedadtest/exemplary/banner-web.json create mode 100644 adapters/feedad/params_test.go create mode 100644 openrtb_ext/imp_feedad.go create mode 100644 static/bidder-info/feedad.yaml create mode 100644 static/bidder-params/feedad.json diff --git a/adapters/feedad/feedad.go b/adapters/feedad/feedad.go new file mode 100644 index 00000000000..dab008bca49 --- /dev/null +++ b/adapters/feedad/feedad.go @@ -0,0 +1,105 @@ +package feedad + +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" +) + +const feedAdAdapterVersion = "1.0.0" + +func getHeaders(request *openrtb2.BidRequest) http.Header { + headers := http.Header{} + headers.Add("Accept", "application/json") + headers.Add("Content-Type", "application/json;charset=utf-8") + headers.Add("X-FA-PBS-Adapter-Version", feedAdAdapterVersion) + headers.Add("X-Openrtb-Version", "2.5") + + if request.Device != nil { + 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) + } + } + + return headers +} + +type adapter struct { + endpoint string +} + +func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *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: "Unexpected status code: 400. Bad request from publisher. Run with request.debug = 1 for more info.", + } + 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 + err := jsonutil.Unmarshal(responseData.Body, &response) + if err != nil { + return nil, []error{err} + } + + bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(internalRequest.Imp)) + bidResponse.Currency = response.Cur + + for _, seatBid := range response.SeatBid { + for i := range seatBid.Bid { + bidResponse.Bids = append( + bidResponse.Bids, + &adapters.TypedBid{ + Bid: &seatBid.Bid[i], + BidType: openrtb_ext.BidTypeBanner, + }, + ) + } + } + + return bidResponse, nil +} + +func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { + requestBody, err := jsonutil.Marshal(request) + if err != nil { + return nil, []error{err} + } + + requestData := &adapters.RequestData{ + Method: "POST", + Uri: a.endpoint, + Body: requestBody, + Headers: getHeaders(request), + ImpIDs: openrtb_ext.GetImpIDs(request.Imp), + } + return []*adapters.RequestData{requestData}, nil +} + +func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { + bidder := &adapter{ + endpoint: config.Endpoint, + } + return bidder, nil +} diff --git a/adapters/feedad/feedad_test.go b/adapters/feedad/feedad_test.go new file mode 100644 index 00000000000..4c2d9031d80 --- /dev/null +++ b/adapters/feedad/feedad_test.go @@ -0,0 +1,25 @@ +package feedad + +import ( + "testing" + + "github.com/prebid/prebid-server/v3/adapters/adapterstest" + "github.com/prebid/prebid-server/v3/config" + "github.com/prebid/prebid-server/v3/openrtb_ext" +) + +func TestJsonSamples(t *testing.T) { + bidder, buildErr := Builder( + openrtb_ext.BidderFeedAd, + config.Adapter{ + Endpoint: "https://ortb.feedad.com/1/prebid/requests", + }, + config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}, + ) + + if buildErr != nil { + t.Fatalf("Builder returned unexpected error: %v", buildErr) + } + + adapterstest.RunJSONBidderTest(t, "feedadtest", bidder) +} diff --git a/adapters/feedad/feedadtest/exemplary/banner-app.json b/adapters/feedad/feedadtest/exemplary/banner-app.json new file mode 100644 index 00000000000..85c63f7412c --- /dev/null +++ b/adapters/feedad/feedadtest/exemplary/banner-app.json @@ -0,0 +1,161 @@ +{ + "mockBidRequest": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "tmax": 1000, + "user": { + "buyeruid": "awesome-user" + }, + "app": { + "publisher": { + "id": "123456789" + }, + "cat": [ + "IAB22-1" + ], + "bundle": "com.app.awesome", + "name": "Awesome App", + "domain": "awesomeapp.com", + "id": "123456789" + }, + "imp": [ + { + "id": "1", + "tagid": "ogTAGID", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "clientToken": "some-client-token", + "placementId": "some-placement-id" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json;charset=utf-8" + ], + "X-Fa-Pbs-Adapter-Version": [ + "1.0.0" + ], + "X-Forwarded-For": [ + "123.123.123.123" + ], + "X-Openrtb-Version": [ + "2.5" + ] + }, + "uri": "https://ortb.feedad.com/1/prebid/requests", + "body": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "imp": [ + { + "id": "1", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "clientToken": "some-client-token", + "placementId": "some-placement-id" + } + }, + "tagid": "ogTAGID" + } + ], + "app": { + "id": "123456789", + "name": "Awesome App", + "bundle": "com.app.awesome", + "domain": "awesomeapp.com", + "cat": [ + "IAB22-1" + ], + "publisher": { + "id": "123456789" + } + }, + "user": { + "buyeruid": "awesome-user" + }, + "tmax": 1000 + }, + "impIDs": [ + "1" + ] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "awesome-resp-id", + "seatbid": [ + { + "bid": [ + { + "id": "a3ae1b4e2fc24a4fb45540082e98e161", + "impid": "1", + "price": 3.5, + "adm": "awesome-markup", + "adomain": [ + "awesome.com" + ], + "crid": "20", + "w": 320, + "h": 50, + "mtype": 1 + } + ], + "type": "banner", + "seat": "escalax" + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "bids": [ + { + "bid": { + "id": "a3ae1b4e2fc24a4fb45540082e98e161", + "impid": "1", + "price": 3.5, + "adm": "awesome-markup", + "adomain": [ + "awesome.com" + ], + "crid": "20", + "w": 320, + "h": 50, + "mtype": 1 + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/feedad/feedadtest/exemplary/banner-web.json b/adapters/feedad/feedadtest/exemplary/banner-web.json new file mode 100644 index 00000000000..d89a253906e --- /dev/null +++ b/adapters/feedad/feedadtest/exemplary/banner-web.json @@ -0,0 +1,207 @@ +{ + "mockBidRequest": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "tmax": 1000, + "user": { + "buyeruid": "awesome-user" + }, + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + }, + "imp": [ + { + "id": "some-impression-id1", + "tagid": "ogTAGID", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "clientToken": "some-client-token", + "placementId": "some-placement-id" + } + } + }, + { + "id": "some-impression-id2", + "tagid": "ogTAGID", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "clientToken": "some-client-token", + "placementId": "some-placement-id" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json;charset=utf-8" + ], + "X-Fa-Pbs-Adapter-Version": [ + "1.0.0" + ], + "X-Forwarded-For": [ + "123.123.123.123" + ], + "X-Openrtb-Version": [ + "2.5" + ] + }, + "uri": "https://ortb.feedad.com/1/prebid/requests", + "body": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "imp": [ + { + "id": "some-impression-id1", + "tagid": "ogTAGID", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "clientToken": "some-client-token", + "placementId": "some-placement-id" + } + } + }, + { + "id": "some-impression-id2", + "tagid": "ogTAGID", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "clientToken": "some-client-token", + "placementId": "some-placement-id" + } + } + } + ], + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + }, + "user": { + "buyeruid": "awesome-user" + }, + "tmax": 1000 + }, + "impIDs": [ + "some-impression-id1", + "some-impression-id2" + ] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "awesome-resp-id", + "seatbid": [ + { + "bid": [ + { + "id": "a3ae1b4e2fc24a4fb45540082e98e161", + "impid": "some-impression-id1", + "price": 3.5, + "adm": "awesome-markup", + "adomain": [ + "awesome.com" + ], + "crid": "20", + "w": 320, + "h": 50, + "mtype": 1 + }, + { + "id": "a3ae1b4e2fc24a4fb45540082e98e162", + "impid": "some-impression-id2", + "price": 3.5, + "adm": "awesome-markup", + "adomain": [ + "awesome.com" + ], + "crid": "20", + "w": 320, + "h": 50, + "mtype": 1 + } + ], + "type": "banner", + "seat": "escalax" + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "bids": [ + { + "bid": { + "id": "a3ae1b4e2fc24a4fb45540082e98e161", + "impid": "some-impression-id1", + "price": 3.5, + "adm": "awesome-markup", + "crid": "20", + "adomain": [ + "awesome.com" + ], + "w": 320, + "h": 50, + "mtype": 1 + }, + "type": "banner" + }, + { + "bid": { + "id": "a3ae1b4e2fc24a4fb45540082e98e162", + "impid": "some-impression-id2", + "price": 3.5, + "adm": "awesome-markup", + "crid": "20", + "adomain": [ + "awesome.com" + ], + "w": 320, + "h": 50, + "mtype": 1 + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/feedad/params_test.go b/adapters/feedad/params_test.go new file mode 100644 index 00000000000..4f95bc075b6 --- /dev/null +++ b/adapters/feedad/params_test.go @@ -0,0 +1,122 @@ +package feedad + +import ( + "encoding/json" + "testing" + + "github.com/prebid/prebid-server/v3/openrtb_ext" +) + +func mustMarshal(t *testing.T, v interface{}) []byte { + data, err := json.Marshal(v) + if err != nil { + t.Errorf("mustMarshal: %s", err) + } + return data +} + +func provideCompleteParams() *openrtb_ext.ExtImpFeedAd { + return &openrtb_ext.ExtImpFeedAd{ + ClientToken: "some-clienttoken", + Decoration: "some-decoration", + PlacementId: "some-placementid", + SdkOptions: &openrtb_ext.ExtImpFeedAdSdkOptions{ + AdvertisingId: "some-advertisingid", + AppName: "some-appname", + BundleId: "some-bundleid", + HybridApp: true, + HybridPlatform: "android", + LimitAdTracking: true, + }, + } +} + +func TestParams(t *testing.T) { + type testCase struct { + _id string + _shouldPass bool + data []byte + } + + tests := make([]*testCase, 0) + + // empty-params + test := &testCase{ + _id: "empty-params", + _shouldPass: false, + data: []byte("{}"), + } + tests = append(tests, test) + + // pass-complete + params := provideCompleteParams() + + test = &testCase{ + _id: "pass-complete", + _shouldPass: true, + data: mustMarshal(t, params), + } + tests = append(tests, test) + + // pass-minimal + params = provideCompleteParams() + params.Decoration = "" + params.SdkOptions = nil + + test = &testCase{ + _id: "pass-minimal", + _shouldPass: true, + data: mustMarshal(t, params), + } + tests = append(tests, test) + + // fail-missing-clienttoken + params = provideCompleteParams() + params.ClientToken = "" + + test = &testCase{ + _id: "fail-missing-clienttoken", + _shouldPass: false, + data: mustMarshal(t, params), + } + tests = append(tests, test) + + // fail-missing-placementid + params = provideCompleteParams() + params.PlacementId = "" + + test = &testCase{ + _id: "fail-missing-placementid", + _shouldPass: false, + data: mustMarshal(t, params), + } + tests = append(tests, test) + + // pass-empty-sdkoptions + params = provideCompleteParams() + params.SdkOptions = &openrtb_ext.ExtImpFeedAdSdkOptions{} + + test = &testCase{ + _id: "pass-empty-sdkoptions", + _shouldPass: true, + data: mustMarshal(t, params), + } + tests = append(tests, test) + + // Run tests + validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") + if err != nil { + t.Fatalf("Failed to fetch the json-schemas: %v", err) + } + + for _, test := range tests { + t.Run(test._id, func(t *testing.T) { + err := validator.Validate(openrtb_ext.BidderFeedAd, test.data) + if err == nil && !test._shouldPass { + t.Error("did not fail") + } else if err != nil && test._shouldPass { + t.Errorf("did fail: %s", err) + } + }) + } +} diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go index d1d6a87fb29..da414557409 100755 --- a/exchange/adapter_builders.go +++ b/exchange/adapter_builders.go @@ -95,6 +95,7 @@ import ( "github.com/prebid/prebid-server/v3/adapters/eplanning" "github.com/prebid/prebid-server/v3/adapters/epom" "github.com/prebid/prebid-server/v3/adapters/escalax" + "github.com/prebid/prebid-server/v3/adapters/feedad" "github.com/prebid/prebid-server/v3/adapters/flipp" "github.com/prebid/prebid-server/v3/adapters/freewheelssp" "github.com/prebid/prebid-server/v3/adapters/frvradn" @@ -328,6 +329,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder { openrtb_ext.BidderEpom: epom.Builder, openrtb_ext.BidderEscalax: escalax.Builder, openrtb_ext.BidderEVolution: evolution.Builder, + openrtb_ext.BidderFeedAd: feedad.Builder, openrtb_ext.BidderFlipp: flipp.Builder, openrtb_ext.BidderFreewheelSSP: freewheelssp.Builder, openrtb_ext.BidderFRVRAdNetwork: frvradn.Builder, diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go index 3f6b0a67037..c203ad5adc6 100644 --- a/openrtb_ext/bidders.go +++ b/openrtb_ext/bidders.go @@ -112,6 +112,7 @@ var coreBidderNames []BidderName = []BidderName{ BidderEpom, BidderEscalax, BidderEVolution, + BidderFeedAd, BidderFlipp, BidderFreewheelSSP, BidderFRVRAdNetwork, @@ -451,6 +452,7 @@ const ( BidderEpom BidderName = "epom" BidderEscalax BidderName = "escalax" BidderEVolution BidderName = "e_volution" + BidderFeedAd BidderName = "feedad" BidderFlipp BidderName = "flipp" BidderFreewheelSSP BidderName = "freewheelssp" BidderFRVRAdNetwork BidderName = "frvradn" diff --git a/openrtb_ext/imp_feedad.go b/openrtb_ext/imp_feedad.go new file mode 100644 index 00000000000..4364fd7b9a9 --- /dev/null +++ b/openrtb_ext/imp_feedad.go @@ -0,0 +1,17 @@ +package openrtb_ext + +type ExtImpFeedAd struct { + ClientToken string `json:"clientToken"` + Decoration string `json:"decoration"` + PlacementId string `json:"placementId"` + SdkOptions *ExtImpFeedAdSdkOptions `json:"sdkOptions"` +} + +type ExtImpFeedAdSdkOptions struct { + AdvertisingId string `json:"advertising_id"` + AppName string `json:"app_name"` + BundleId string `json:"bundle_id"` + HybridApp bool `json:"hybrid_app"` + HybridPlatform string `json:"hybrid_platform"` + LimitAdTracking bool `json:"limit_ad_tracking"` +} diff --git a/static/bidder-info/feedad.yaml b/static/bidder-info/feedad.yaml new file mode 100644 index 00000000000..da62b75f774 --- /dev/null +++ b/static/bidder-info/feedad.yaml @@ -0,0 +1,17 @@ +endpoint: "https://ortb.feedad.com/1/prebid/requests" +endpointCompression: gzip +maintainer: + email: support@feedad.com +gvlVendorID: 781 +modifyingVastXmlAllowed: true +capabilities: + app: + mediaTypes: + - banner + site: + mediaTypes: + - banner +userSync: + iframe: + url: https://ortb.feedad.com/1/usersyncs/supply?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect={{.RedirectURL}} + userMacro: $UID diff --git a/static/bidder-params/feedad.json b/static/bidder-params/feedad.json new file mode 100644 index 00000000000..84f5394b4b2 --- /dev/null +++ b/static/bidder-params/feedad.json @@ -0,0 +1,65 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "FeedAd Adapter Params", + "description": "A schema which validates params accepted by the FeedAd adapter", + "properties": { + "clientToken": { + "description": "Your FeedAd client token. Check your FeedAd admin panel.", + "minLength": 1, + "type": "string" + }, + "decoration": { + "description": "A decoration to apply to the ad slot. See our documentation at https://docs.feedad.com/web/feed_ad/#decorations", + "type": "string" + }, + "placementId": { + "description": "A FeedAd placement ID of your choice", + "minLength": 1, + "pattern": "^(([a-z0-9])+[-_]?)+$", + "type": "string" + }, + "sdkOptions": { + "description": "Optional: Only required if you are using Prebid.JS in an app environment (aka hybrid app). See our documentation at https://docs.feedad.com/web/configuration/#hybrid-app-config-parameters", + "properties": { + "advertising_id": { + "type": "string", + "description": "Optional: The advertising id of the device or user (e.g. Apple IDFA, Google Advertising Client Id). We highly recommend setting this parameter to maximize your fill rate." + }, + "app_name": { + "type": "string", + "description": "The name of your app. This name will identify your app within the FeedAd admin dashboard." + }, + "bundle_id": { + "type": "string", + "description": "The unique package name or bundle id of your app." + }, + "hybrid_app": { + "type": "boolean", + "description": "Boolean indicating that the SDK is loaded within a hybrid app." + }, + "hybrid_platform": { + "description": "String identifying the device platform.", + "enum": [ + "", + "android", + "ios", + "windows" + ] + }, + "limit_ad_tracking": { + "type": "boolean", + "description": "Whether the app's user has limited ad tracking enabled." + } + }, + "type": [ + "object", + "null" + ] + } + }, + "required": [ + "clientToken", + "placementId" + ], + "type": "object" +} \ No newline at end of file From 67f84c836949d1bb68725788d81699ca2a3d1f46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Ge=C3=9Fner?= Date: Fri, 13 Dec 2024 16:37:10 +0100 Subject: [PATCH 02/12] static.bidder-info: feedad.yaml: Added GPP macros to user sync URL --- static/bidder-info/feedad.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/bidder-info/feedad.yaml b/static/bidder-info/feedad.yaml index da62b75f774..a1f55ccaf1a 100644 --- a/static/bidder-info/feedad.yaml +++ b/static/bidder-info/feedad.yaml @@ -13,5 +13,5 @@ capabilities: - banner userSync: iframe: - url: https://ortb.feedad.com/1/usersyncs/supply?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect={{.RedirectURL}} + url: https://ortb.feedad.com/1/usersyncs/supply?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}&us_privacy={{.USPrivacy}}&redirect={{.RedirectURL}} userMacro: $UID From 29a94e9f237a42947539796b6246fedf9d4124c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Ge=C3=9Fner?= Date: Tue, 17 Dec 2024 11:50:01 +0100 Subject: [PATCH 03/12] adapters.feedad.feedadtest.exemplary: s/banner-web.json/banner-site.json/ --- .../feedadtest/exemplary/{banner-web.json => banner-site.json} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename adapters/feedad/feedadtest/exemplary/{banner-web.json => banner-site.json} (100%) diff --git a/adapters/feedad/feedadtest/exemplary/banner-web.json b/adapters/feedad/feedadtest/exemplary/banner-site.json similarity index 100% rename from adapters/feedad/feedadtest/exemplary/banner-web.json rename to adapters/feedad/feedadtest/exemplary/banner-site.json From 842aee57c1df1f122e8093d6b39df5adc8043777 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Ge=C3=9Fner?= Date: Tue, 17 Dec 2024 12:59:24 +0100 Subject: [PATCH 04/12] adapters.feedad: params_test.go: Updated tests to match Prebid template --- adapters/feedad/params_test.go | 136 +++++++++------------------------ 1 file changed, 35 insertions(+), 101 deletions(-) diff --git a/adapters/feedad/params_test.go b/adapters/feedad/params_test.go index 4f95bc075b6..75f5d6098bb 100644 --- a/adapters/feedad/params_test.go +++ b/adapters/feedad/params_test.go @@ -7,116 +7,50 @@ import ( "github.com/prebid/prebid-server/v3/openrtb_ext" ) -func mustMarshal(t *testing.T, v interface{}) []byte { - data, err := json.Marshal(v) +func TestValidParams(t *testing.T) { + validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") if err != nil { - t.Errorf("mustMarshal: %s", err) + t.Fatalf("Failed to fetch the json schema: %v", err) } - return data -} -func provideCompleteParams() *openrtb_ext.ExtImpFeedAd { - return &openrtb_ext.ExtImpFeedAd{ - ClientToken: "some-clienttoken", - Decoration: "some-decoration", - PlacementId: "some-placementid", - SdkOptions: &openrtb_ext.ExtImpFeedAdSdkOptions{ - AdvertisingId: "some-advertisingid", - AppName: "some-appname", - BundleId: "some-bundleid", - HybridApp: true, - HybridPlatform: "android", - LimitAdTracking: true, - }, + for _, p := range validParams { + if err := validator.Validate(openrtb_ext.BidderFeedAd, json.RawMessage(p)); err != nil { + t.Errorf("Schema rejected valid params: %s", p) + } } } -func TestParams(t *testing.T) { - type testCase struct { - _id string - _shouldPass bool - data []byte - } - - tests := make([]*testCase, 0) - - // empty-params - test := &testCase{ - _id: "empty-params", - _shouldPass: false, - data: []byte("{}"), - } - tests = append(tests, test) - - // pass-complete - params := provideCompleteParams() - - test = &testCase{ - _id: "pass-complete", - _shouldPass: true, - data: mustMarshal(t, params), - } - tests = append(tests, test) - - // pass-minimal - params = provideCompleteParams() - params.Decoration = "" - params.SdkOptions = nil - - test = &testCase{ - _id: "pass-minimal", - _shouldPass: true, - data: mustMarshal(t, params), - } - tests = append(tests, test) - - // fail-missing-clienttoken - params = provideCompleteParams() - params.ClientToken = "" - - test = &testCase{ - _id: "fail-missing-clienttoken", - _shouldPass: false, - data: mustMarshal(t, params), - } - tests = append(tests, test) - - // fail-missing-placementid - params = provideCompleteParams() - params.PlacementId = "" - - test = &testCase{ - _id: "fail-missing-placementid", - _shouldPass: false, - data: mustMarshal(t, params), - } - tests = append(tests, test) - - // pass-empty-sdkoptions - params = provideCompleteParams() - params.SdkOptions = &openrtb_ext.ExtImpFeedAdSdkOptions{} - - test = &testCase{ - _id: "pass-empty-sdkoptions", - _shouldPass: true, - data: mustMarshal(t, params), - } - tests = append(tests, test) - - // Run tests +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) + t.Fatalf("Failed to fetch the json schema: %v", err) } - for _, test := range tests { - t.Run(test._id, func(t *testing.T) { - err := validator.Validate(openrtb_ext.BidderFeedAd, test.data) - if err == nil && !test._shouldPass { - t.Error("did not fail") - } else if err != nil && test._shouldPass { - t.Errorf("did fail: %s", err) - } - }) + for _, p := range invalidParams { + if err := validator.Validate(openrtb_ext.BidderFeedAd, json.RawMessage(p)); err == nil { + t.Errorf("Schema allowed invalid params: %s", p) + } } } + +var validParams = []string{ + `{"clientToken":"some-clienttoken","placementId":"some-placementid"}`, + `{"clientToken":"some-clienttoken","placementId":"some-placementid","sdkOptions":{}}`, + `{"clientToken":"some-clienttoken","placementId":"some-placementid","sdkOptions":{"hybrid_platform":"ios"}}`, + `{"clientToken":"some-clienttoken","placementId":"some-placementid","sdkOptions":{"hybrid_platform":"windows"}}`, + `{"clientToken":"some-clienttoken","decoration":"some-decoration","placementId":"some-placementid","sdkOptions":{"advertising_id":"","app_name":"","bundle_id":"","hybrid_app":false,"hybrid_platform":"","limit_ad_tracking":false}}`, + `{"clientToken":"some-clienttoken","decoration":"some-decoration","placementId":"some-placementid","sdkOptions":{"advertising_id":"some-advertisingid","app_name":"some-appname","bundle_id":"some-bundleid","hybrid_app":true,"hybrid_platform":"android","limit_ad_tracking":true}}`, +} + +var invalidParams = []string{ + `{}`, + `{"clientToken":"","placementId":"some-placementid"}`, + `{"clientToken":"some-clienttoken","placementId":""}`, + `{"clientToken":"some-clienttoken","placementId":"some-placementid","sdkOptions":"complete-garbage"}`, + `{"clientToken":"some-clienttoken","placementId":"some-placementid","sdkOptions":{"advertising_id":{}}}`, + `{"clientToken":"some-clienttoken","placementId":"some-placementid","sdkOptions":{"advertising_id":{}}}`, + `{"clientToken":"some-clienttoken","placementId":"some-placementid","sdkOptions":{"app_name":{}}}`, + `{"clientToken":"some-clienttoken","placementId":"some-placementid","sdkOptions":{"bundle_id":{}}}`, + `{"clientToken":"some-clienttoken","placementId":"some-placementid","sdkOptions":{"hybrid_platform":{}}}`, + `{"clientToken":"some-clienttoken","placementId":"some-placementid","sdkOptions":{"limit_ad_tracking":{}}}`, +} From 56414de3945d5b71c661a18b82006e23529f7895 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Ge=C3=9Fner?= Date: Wed, 29 Jan 2025 12:00:23 +0100 Subject: [PATCH 05/12] adapters.feedad: Added more test cases for param placementId --- adapters/feedad/params_test.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/adapters/feedad/params_test.go b/adapters/feedad/params_test.go index 75f5d6098bb..a77ad9ae46e 100644 --- a/adapters/feedad/params_test.go +++ b/adapters/feedad/params_test.go @@ -35,6 +35,19 @@ func TestInvalidParams(t *testing.T) { var validParams = []string{ `{"clientToken":"some-clienttoken","placementId":"some-placementid"}`, + `{"clientToken":"some-clienttoken","placementId":"some_placementid"}`, + `{"clientToken":"some-clienttoken","placementId":"some-"}`, + `{"clientToken":"some-clienttoken","placementId":"some-"}`, + `{"clientToken":"some-clienttoken","placementId":"42-"}`, + `{"clientToken":"some-clienttoken","placementId":"42_"}`, + `{"clientToken":"some-clienttoken","placementId":"some-placementid-42"}`, + `{"clientToken":"some-clienttoken","placementId":"some_placementid_42"}`, + `{"clientToken":"some-clienttoken","placementId":"some_placementid-42"}`, + `{"clientToken":"some-clienttoken","placementId":"some-placementid_42"}`, + `{"clientToken":"some-clienttoken","placementId":"42-some-placementid"}`, + `{"clientToken":"some-clienttoken","placementId":"42_some_placementid"}`, + `{"clientToken":"some-clienttoken","placementId":"42_some-placementid"}`, + `{"clientToken":"some-clienttoken","placementId":"42-some_placementid"}`, `{"clientToken":"some-clienttoken","placementId":"some-placementid","sdkOptions":{}}`, `{"clientToken":"some-clienttoken","placementId":"some-placementid","sdkOptions":{"hybrid_platform":"ios"}}`, `{"clientToken":"some-clienttoken","placementId":"some-placementid","sdkOptions":{"hybrid_platform":"windows"}}`, @@ -46,6 +59,16 @@ var invalidParams = []string{ `{}`, `{"clientToken":"","placementId":"some-placementid"}`, `{"clientToken":"some-clienttoken","placementId":""}`, + `{"clientToken":"some-clienttoken","placementId":"-"}`, + `{"clientToken":"some-clienttoken","placementId":"_"}`, + `{"clientToken":"some-clienttoken","placementId":" "}`, + `{"clientToken":"some-clienttoken","placementId":"complete garbage"}`, + `{"clientToken":"some-clienttoken","placementId":"Complete-Garbage"}`, + `{"clientToken":"some-clienttoken","placementId":"Complete*Garbage"}`, + `{"clientToken":"some-clienttoken","placementId":"-42"}`, + `{"clientToken":"some-clienttoken","placementId":"_42"}`, + `{"clientToken":"some-clienttoken","placementId":"-complete"}`, + `{"clientToken":"some-clienttoken","placementId":"_garbage"}`, `{"clientToken":"some-clienttoken","placementId":"some-placementid","sdkOptions":"complete-garbage"}`, `{"clientToken":"some-clienttoken","placementId":"some-placementid","sdkOptions":{"advertising_id":{}}}`, `{"clientToken":"some-clienttoken","placementId":"some-placementid","sdkOptions":{"advertising_id":{}}}`, From 8a62f12caec804f2de97dd65e7313a0382b92c0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Ge=C3=9Fner?= Date: Wed, 29 Jan 2025 12:21:46 +0100 Subject: [PATCH 06/12] adapters.feedad: TestJsonSamples: Swapped to fake endpoint --- adapters/feedad/feedad_test.go | 2 +- adapters/feedad/feedadtest/exemplary/banner-app.json | 2 +- adapters/feedad/feedadtest/exemplary/banner-site.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/adapters/feedad/feedad_test.go b/adapters/feedad/feedad_test.go index 4c2d9031d80..28993850df0 100644 --- a/adapters/feedad/feedad_test.go +++ b/adapters/feedad/feedad_test.go @@ -12,7 +12,7 @@ func TestJsonSamples(t *testing.T) { bidder, buildErr := Builder( openrtb_ext.BidderFeedAd, config.Adapter{ - Endpoint: "https://ortb.feedad.com/1/prebid/requests", + Endpoint: "https://example.com/1/prebid/requests", }, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}, ) diff --git a/adapters/feedad/feedadtest/exemplary/banner-app.json b/adapters/feedad/feedadtest/exemplary/banner-app.json index 85c63f7412c..e28a6a32def 100644 --- a/adapters/feedad/feedadtest/exemplary/banner-app.json +++ b/adapters/feedad/feedadtest/exemplary/banner-app.json @@ -60,7 +60,7 @@ "2.5" ] }, - "uri": "https://ortb.feedad.com/1/prebid/requests", + "uri": "https://example.com/1/prebid/requests", "body": { "id": "some-request-id", "device": { diff --git a/adapters/feedad/feedadtest/exemplary/banner-site.json b/adapters/feedad/feedadtest/exemplary/banner-site.json index d89a253906e..38745dbaff6 100644 --- a/adapters/feedad/feedadtest/exemplary/banner-site.json +++ b/adapters/feedad/feedadtest/exemplary/banner-site.json @@ -68,7 +68,7 @@ "2.5" ] }, - "uri": "https://ortb.feedad.com/1/prebid/requests", + "uri": "https://example.com/1/prebid/requests", "body": { "id": "some-request-id", "device": { From f41630f3eecf266e14213d82894251c3304bc4ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Ge=C3=9Fner?= Date: Wed, 29 Jan 2025 12:25:23 +0100 Subject: [PATCH 07/12] adapters.feedad.feedadtest.exemplary: banner-site.json: Removed field device.ip, added field device.ipv6 --- adapters/feedad/feedadtest/exemplary/banner-site.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/adapters/feedad/feedadtest/exemplary/banner-site.json b/adapters/feedad/feedadtest/exemplary/banner-site.json index 38745dbaff6..7f1d7b484df 100644 --- a/adapters/feedad/feedadtest/exemplary/banner-site.json +++ b/adapters/feedad/feedadtest/exemplary/banner-site.json @@ -3,7 +3,7 @@ "id": "some-request-id", "device": { "ua": "test-user-agent", - "ip": "123.123.123.123", + "ipv6": "2001:db8:3333:4444:5555:6666:7777:8888", "language": "en", "dnt": 0 }, @@ -62,7 +62,7 @@ "1.0.0" ], "X-Forwarded-For": [ - "123.123.123.123" + "2001:db8:3333:4444:5555:6666:7777:8888" ], "X-Openrtb-Version": [ "2.5" @@ -73,7 +73,7 @@ "id": "some-request-id", "device": { "ua": "test-user-agent", - "ip": "123.123.123.123", + "ipv6": "2001:db8:3333:4444:5555:6666:7777:8888", "language": "en", "dnt": 0 }, From 3c9cd9e9ef994ba59b6d339300313bda8732d54e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Ge=C3=9Fner?= Date: Wed, 29 Jan 2025 13:48:06 +0100 Subject: [PATCH 08/12] adapters.feedad.feedadtest: Added supplemental dir with banner-site-no-device.json test case --- .../supplemental/banner-site-no-device.json | 192 ++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 adapters/feedad/feedadtest/supplemental/banner-site-no-device.json diff --git a/adapters/feedad/feedadtest/supplemental/banner-site-no-device.json b/adapters/feedad/feedadtest/supplemental/banner-site-no-device.json new file mode 100644 index 00000000000..6217bda6236 --- /dev/null +++ b/adapters/feedad/feedadtest/supplemental/banner-site-no-device.json @@ -0,0 +1,192 @@ +{ + "mockBidRequest": { + "id": "some-request-id", + "tmax": 1000, + "user": { + "buyeruid": "awesome-user" + }, + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + }, + "imp": [ + { + "id": "some-impression-id1", + "tagid": "ogTAGID", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "clientToken": "some-client-token", + "placementId": "some-placement-id" + } + } + }, + { + "id": "some-impression-id2", + "tagid": "ogTAGID", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "clientToken": "some-client-token", + "placementId": "some-placement-id" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json;charset=utf-8" + ], + "X-Fa-Pbs-Adapter-Version": [ + "1.0.0" + ], + "X-Openrtb-Version": [ + "2.5" + ] + }, + "uri": "https://example.com/1/prebid/requests", + "body": { + "id": "some-request-id", + "imp": [ + { + "id": "some-impression-id1", + "tagid": "ogTAGID", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "clientToken": "some-client-token", + "placementId": "some-placement-id" + } + } + }, + { + "id": "some-impression-id2", + "tagid": "ogTAGID", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "clientToken": "some-client-token", + "placementId": "some-placement-id" + } + } + } + ], + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + }, + "user": { + "buyeruid": "awesome-user" + }, + "tmax": 1000 + }, + "impIDs": [ + "some-impression-id1", + "some-impression-id2" + ] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "awesome-resp-id", + "seatbid": [ + { + "bid": [ + { + "id": "a3ae1b4e2fc24a4fb45540082e98e161", + "impid": "some-impression-id1", + "price": 3.5, + "adm": "awesome-markup", + "adomain": [ + "awesome.com" + ], + "crid": "20", + "w": 320, + "h": 50, + "mtype": 1 + }, + { + "id": "a3ae1b4e2fc24a4fb45540082e98e162", + "impid": "some-impression-id2", + "price": 3.5, + "adm": "awesome-markup", + "adomain": [ + "awesome.com" + ], + "crid": "20", + "w": 320, + "h": 50, + "mtype": 1 + } + ], + "type": "banner", + "seat": "escalax" + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "bids": [ + { + "bid": { + "id": "a3ae1b4e2fc24a4fb45540082e98e161", + "impid": "some-impression-id1", + "price": 3.5, + "adm": "awesome-markup", + "crid": "20", + "adomain": [ + "awesome.com" + ], + "w": 320, + "h": 50, + "mtype": 1 + }, + "type": "banner" + }, + { + "bid": { + "id": "a3ae1b4e2fc24a4fb45540082e98e162", + "impid": "some-impression-id2", + "price": 3.5, + "adm": "awesome-markup", + "crid": "20", + "adomain": [ + "awesome.com" + ], + "w": 320, + "h": 50, + "mtype": 1 + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file From 8e1dcfe329441ef3a6c6bfe5bed57f3c6f84227d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Ge=C3=9Fner?= Date: Wed, 29 Jan 2025 14:45:41 +0100 Subject: [PATCH 09/12] adapters.feedad: adapter.MakeBids: Updated to use adapters.{IsResponseStatusCodeNoContent,CheckResponseStatusCodeForErrors}() --- adapters/feedad/feedad.go | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/adapters/feedad/feedad.go b/adapters/feedad/feedad.go index dab008bca49..1ca4b802cba 100644 --- a/adapters/feedad/feedad.go +++ b/adapters/feedad/feedad.go @@ -1,13 +1,11 @@ package feedad 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" ) @@ -39,21 +37,11 @@ type adapter struct { } func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *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: "Unexpected status code: 400. Bad request from publisher. Run with request.debug = 1 for more info.", - } - 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} } From 409293109ac052e925464f4f8b70f8a3fd82c326 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Ge=C3=9Fner?= Date: Wed, 29 Jan 2025 14:53:07 +0100 Subject: [PATCH 10/12] adapters.feedad.feedadtest.supplemental: Added test cases for 204, 400 and 500 responses --- .../banner-site-204-response.json | 118 +++++++++++++++++ .../banner-site-400-response.json | 124 ++++++++++++++++++ .../banner-site-500-response.json | 124 ++++++++++++++++++ 3 files changed, 366 insertions(+) create mode 100644 adapters/feedad/feedadtest/supplemental/banner-site-204-response.json create mode 100644 adapters/feedad/feedadtest/supplemental/banner-site-400-response.json create mode 100644 adapters/feedad/feedadtest/supplemental/banner-site-500-response.json diff --git a/adapters/feedad/feedadtest/supplemental/banner-site-204-response.json b/adapters/feedad/feedadtest/supplemental/banner-site-204-response.json new file mode 100644 index 00000000000..b151a06e6ec --- /dev/null +++ b/adapters/feedad/feedadtest/supplemental/banner-site-204-response.json @@ -0,0 +1,118 @@ +{ + "mockBidRequest": { + "id": "some-request-id", + "tmax": 1000, + "user": { + "buyeruid": "awesome-user" + }, + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + }, + "imp": [ + { + "id": "some-impression-id1", + "tagid": "ogTAGID", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "clientToken": "some-client-token", + "placementId": "some-placement-id" + } + } + }, + { + "id": "some-impression-id2", + "tagid": "ogTAGID", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "clientToken": "some-client-token", + "placementId": "some-placement-id" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json;charset=utf-8" + ], + "X-Fa-Pbs-Adapter-Version": [ + "1.0.0" + ], + "X-Openrtb-Version": [ + "2.5" + ] + }, + "uri": "https://example.com/1/prebid/requests", + "body": { + "id": "some-request-id", + "imp": [ + { + "id": "some-impression-id1", + "tagid": "ogTAGID", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "clientToken": "some-client-token", + "placementId": "some-placement-id" + } + } + }, + { + "id": "some-impression-id2", + "tagid": "ogTAGID", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "clientToken": "some-client-token", + "placementId": "some-placement-id" + } + } + } + ], + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + }, + "user": { + "buyeruid": "awesome-user" + }, + "tmax": 1000 + }, + "impIDs": [ + "some-impression-id1", + "some-impression-id2" + ] + }, + "mockResponse": { + "status": 204, + "body": {} + } + } + ], + "expectedBidResponses": [] +} \ No newline at end of file diff --git a/adapters/feedad/feedadtest/supplemental/banner-site-400-response.json b/adapters/feedad/feedadtest/supplemental/banner-site-400-response.json new file mode 100644 index 00000000000..0b4ad339f57 --- /dev/null +++ b/adapters/feedad/feedadtest/supplemental/banner-site-400-response.json @@ -0,0 +1,124 @@ +{ + "mockBidRequest": { + "id": "some-request-id", + "tmax": 1000, + "user": { + "buyeruid": "awesome-user" + }, + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + }, + "imp": [ + { + "id": "some-impression-id1", + "tagid": "ogTAGID", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "clientToken": "some-client-token", + "placementId": "some-placement-id" + } + } + }, + { + "id": "some-impression-id2", + "tagid": "ogTAGID", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "clientToken": "some-client-token", + "placementId": "some-placement-id" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json;charset=utf-8" + ], + "X-Fa-Pbs-Adapter-Version": [ + "1.0.0" + ], + "X-Openrtb-Version": [ + "2.5" + ] + }, + "uri": "https://example.com/1/prebid/requests", + "body": { + "id": "some-request-id", + "imp": [ + { + "id": "some-impression-id1", + "tagid": "ogTAGID", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "clientToken": "some-client-token", + "placementId": "some-placement-id" + } + } + }, + { + "id": "some-impression-id2", + "tagid": "ogTAGID", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "clientToken": "some-client-token", + "placementId": "some-placement-id" + } + } + } + ], + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + }, + "user": { + "buyeruid": "awesome-user" + }, + "tmax": 1000 + }, + "impIDs": [ + "some-impression-id1", + "some-impression-id2" + ] + }, + "mockResponse": { + "status": 400, + "body": {} + } + } + ], + "expectedBidResponses": [], + "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/feedad/feedadtest/supplemental/banner-site-500-response.json b/adapters/feedad/feedadtest/supplemental/banner-site-500-response.json new file mode 100644 index 00000000000..11bb7587ba5 --- /dev/null +++ b/adapters/feedad/feedadtest/supplemental/banner-site-500-response.json @@ -0,0 +1,124 @@ +{ + "mockBidRequest": { + "id": "some-request-id", + "tmax": 1000, + "user": { + "buyeruid": "awesome-user" + }, + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + }, + "imp": [ + { + "id": "some-impression-id1", + "tagid": "ogTAGID", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "clientToken": "some-client-token", + "placementId": "some-placement-id" + } + } + }, + { + "id": "some-impression-id2", + "tagid": "ogTAGID", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "clientToken": "some-client-token", + "placementId": "some-placement-id" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json;charset=utf-8" + ], + "X-Fa-Pbs-Adapter-Version": [ + "1.0.0" + ], + "X-Openrtb-Version": [ + "2.5" + ] + }, + "uri": "https://example.com/1/prebid/requests", + "body": { + "id": "some-request-id", + "imp": [ + { + "id": "some-impression-id1", + "tagid": "ogTAGID", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "clientToken": "some-client-token", + "placementId": "some-placement-id" + } + } + }, + { + "id": "some-impression-id2", + "tagid": "ogTAGID", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "clientToken": "some-client-token", + "placementId": "some-placement-id" + } + } + } + ], + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + }, + "user": { + "buyeruid": "awesome-user" + }, + "tmax": 1000 + }, + "impIDs": [ + "some-impression-id1", + "some-impression-id2" + ] + }, + "mockResponse": { + "status": 500, + "body": {} + } + } + ], + "expectedBidResponses": [], + "expectedMakeBidsErrors": [ + { + "value": "Unexpected status code: 500. Run with request.debug = 1 for more info", + "comparison": "literal" + } + ] +} \ No newline at end of file From acb6af15ba4d9ff384cbfaaadf7b02f0669d0824 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Ge=C3=9Fner?= Date: Wed, 29 Jan 2025 14:57:14 +0100 Subject: [PATCH 11/12] adapters.feedad.feedadtest.supplemental: Added test case for malformed response --- .../banner-site-malformed-response.json | 124 ++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 adapters/feedad/feedadtest/supplemental/banner-site-malformed-response.json diff --git a/adapters/feedad/feedadtest/supplemental/banner-site-malformed-response.json b/adapters/feedad/feedadtest/supplemental/banner-site-malformed-response.json new file mode 100644 index 00000000000..f4d9107d65d --- /dev/null +++ b/adapters/feedad/feedadtest/supplemental/banner-site-malformed-response.json @@ -0,0 +1,124 @@ +{ + "mockBidRequest": { + "id": "some-request-id", + "tmax": 1000, + "user": { + "buyeruid": "awesome-user" + }, + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + }, + "imp": [ + { + "id": "some-impression-id1", + "tagid": "ogTAGID", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "clientToken": "some-client-token", + "placementId": "some-placement-id" + } + } + }, + { + "id": "some-impression-id2", + "tagid": "ogTAGID", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "clientToken": "some-client-token", + "placementId": "some-placement-id" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json;charset=utf-8" + ], + "X-Fa-Pbs-Adapter-Version": [ + "1.0.0" + ], + "X-Openrtb-Version": [ + "2.5" + ] + }, + "uri": "https://example.com/1/prebid/requests", + "body": { + "id": "some-request-id", + "imp": [ + { + "id": "some-impression-id1", + "tagid": "ogTAGID", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "clientToken": "some-client-token", + "placementId": "some-placement-id" + } + } + }, + { + "id": "some-impression-id2", + "tagid": "ogTAGID", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "clientToken": "some-client-token", + "placementId": "some-placement-id" + } + } + } + ], + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + }, + "user": { + "buyeruid": "awesome-user" + }, + "tmax": 1000 + }, + "impIDs": [ + "some-impression-id1", + "some-impression-id2" + ] + }, + "mockResponse": { + "status": 200, + "body": "complete-garbage" + } + } + ], + "expectedBidResponses": [], + "expectedMakeBidsErrors": [ + { + "value": "expect { or n, but found \"", + "comparison": "literal" + } + ] +} \ No newline at end of file From 770ffd84150ab5e30cd8ba79742517edf43b053d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Ge=C3=9Fner?= Date: Wed, 29 Jan 2025 14:58:02 +0100 Subject: [PATCH 12/12] adapters.feedad: MakeRequests: Use http.MethodPost --- adapters/feedad/feedad.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adapters/feedad/feedad.go b/adapters/feedad/feedad.go index 1ca4b802cba..804027ee112 100644 --- a/adapters/feedad/feedad.go +++ b/adapters/feedad/feedad.go @@ -76,7 +76,7 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E } requestData := &adapters.RequestData{ - Method: "POST", + Method: http.MethodPost, Uri: a.endpoint, Body: requestBody, Headers: getHeaders(request),