diff --git a/modules/yaleoBidAdapter.ts b/modules/yaleoBidAdapter.ts index e70682fc2dd..dcae1d5fd60 100755 --- a/modules/yaleoBidAdapter.ts +++ b/modules/yaleoBidAdapter.ts @@ -1,7 +1,9 @@ import { ortbConverter } from '../libraries/ortbConverter/converter.js'; import { pbsExtensions } from '../libraries/pbsExtensions/pbsExtensions.js'; import { BidderSpec, registerBidder } from '../src/adapters/bidderFactory.js'; +import { config } from '../src/config.js'; import { BANNER } from '../src/mediaTypes.js'; +import { logWarn } from '../src/utils.js'; interface YaleoBidParams { /** @@ -19,15 +21,30 @@ interface YaleoBidParams { maxCpm?: number; } +interface YaleoConfig { + /** + * Overrides the bidder endpoint URL. Must be one of the approved HTTPS Yaleo + * endpoints; any other value is ignored. Defaults to the production endpoint. + */ + endpoint?: string; +} + declare module '../src/adUnits' { interface BidderParams { [BIDDER_CODE]: YaleoBidParams; } } +declare module '../src/config' { + interface Config { + [BIDDER_CODE]?: YaleoConfig; + } +} + const BIDDER_CODE = 'yaleo'; const AUDIENZZ_VENDOR_ID = 783; -const PREBID_URL = 'https://bidder.yaleo.com/prebid'; +const DEFAULT_ENDPOINT = 'https://bidder.yaleo.com/prebid'; +const ALLOWED_ENDPOINTS = new Set([DEFAULT_ENDPOINT, 'https://dev-bidder.yaleo.com/prebid']); const DEFAULT_TTL = 300; const converter = ortbConverter({ @@ -38,6 +55,18 @@ const converter = ortbConverter({ processors: pbsExtensions, }); +const resolveEndpoint = (): string => { + const customEndpoint = config.getConfig(BIDDER_CODE)?.endpoint; + if (!customEndpoint) { + return DEFAULT_ENDPOINT; + } + if (!ALLOWED_ENDPOINTS.has(customEndpoint)) { + logWarn(`${BIDDER_CODE}: ignoring unapproved endpoint override "${customEndpoint}"`); + return DEFAULT_ENDPOINT; + } + return customEndpoint; +}; + const isBidRequestValid: BidderSpec['isBidRequestValid'] = (request) => { if (!request.params || typeof request.params.placementId !== 'string') { return false; @@ -53,7 +82,7 @@ const buildRequests: BidderSpec['buildRequests'] = (validBid }); return { - url: PREBID_URL, + url: resolveEndpoint(), method: 'POST', data: ortbRequest, }; diff --git a/test/spec/modules/yaleoBidAdapter_spec.js b/test/spec/modules/yaleoBidAdapter_spec.js index 5bbba97109c..46bfeb2ee29 100644 --- a/test/spec/modules/yaleoBidAdapter_spec.js +++ b/test/spec/modules/yaleoBidAdapter_spec.js @@ -1,4 +1,5 @@ import { cloneDeep } from "lodash"; +import { config } from "src/config.js"; import { spec } from "../../../modules/yaleoBidAdapter.ts"; const bannerBidRequestBase = { @@ -120,6 +121,10 @@ describe('Yaleo bid adapter', () => { }); describe('buildRequests', () => { + afterEach(() => { + config.resetConfig(); + }); + it('creates a valid banner bid request', () => { const bidderRequest = { bids: [bannerBidRequest], @@ -141,6 +146,70 @@ describe('Yaleo bid adapter', () => { expect(request.data.site.page).to.be.equal('http://example.com'); }); + it('uses the production endpoint by default', () => { + const bidderRequest = { + bids: [bannerBidRequest], + auctionId: bannerBidRequest.auctionId, + bidderRequestId: bannerBidRequest.bidderRequestId, + }; + + const request = spec.buildRequests([bannerBidRequest], bidderRequest); + + expect(request.url).to.equal('https://bidder.yaleo.com/prebid'); + }); + + it('overrides the endpoint via yaleo.endpoint config for an approved Yaleo host', () => { + config.setConfig({ yaleo: { endpoint: 'https://dev-bidder.yaleo.com/prebid' } }); + const bidderRequest = { + bids: [bannerBidRequest], + auctionId: bannerBidRequest.auctionId, + bidderRequestId: bannerBidRequest.bidderRequestId, + }; + + const request = spec.buildRequests([bannerBidRequest], bidderRequest); + + expect(request.url).to.equal('https://dev-bidder.yaleo.com/prebid'); + }); + + it('ignores an endpoint override that is not a Yaleo host', () => { + config.setConfig({ yaleo: { endpoint: 'https://bidder.example.com/prebid' } }); + const bidderRequest = { + bids: [bannerBidRequest], + auctionId: bannerBidRequest.auctionId, + bidderRequestId: bannerBidRequest.bidderRequestId, + }; + + const request = spec.buildRequests([bannerBidRequest], bidderRequest); + + expect(request.url).to.equal('https://bidder.yaleo.com/prebid'); + }); + + it('ignores a non-HTTPS endpoint override', () => { + config.setConfig({ yaleo: { endpoint: 'http://bidder.yaleo.com/prebid' } }); + const bidderRequest = { + bids: [bannerBidRequest], + auctionId: bannerBidRequest.auctionId, + bidderRequestId: bannerBidRequest.bidderRequestId, + }; + + const request = spec.buildRequests([bannerBidRequest], bidderRequest); + + expect(request.url).to.equal('https://bidder.yaleo.com/prebid'); + }); + + it('ignores an unapproved Yaleo subdomain override', () => { + config.setConfig({ yaleo: { endpoint: 'https://anything.yaleo.com/prebid' } }); + const bidderRequest = { + bids: [bannerBidRequest], + auctionId: bannerBidRequest.auctionId, + bidderRequestId: bannerBidRequest.bidderRequestId, + }; + + const request = spec.buildRequests([bannerBidRequest], bidderRequest); + + expect(request.url).to.equal('https://bidder.yaleo.com/prebid'); + }); + it('checks that all params are passed to the request', () => { bannerBidRequest.params = { placementId: '12345',