diff --git a/modules/adbutlerBidAdapter.js b/modules/adbutlerBidAdapter.js
index f633eba98a3..44a2ef49f51 100644
--- a/modules/adbutlerBidAdapter.js
+++ b/modules/adbutlerBidAdapter.js
@@ -74,6 +74,7 @@ export const spec = {
var width;
var height;
+ serverResponse = serverResponse.body;
if (serverResponse && serverResponse.status === 'SUCCESS' && bidObj) {
CPM = serverResponse.cpm;
minCPM = utils.getBidIdParameter('minCPM', bidObj.params);
diff --git a/modules/appnexusAstBidAdapter.js b/modules/appnexusAstBidAdapter.js
index c4e2686db15..9a2cea8a229 100644
--- a/modules/appnexusAstBidAdapter.js
+++ b/modules/appnexusAstBidAdapter.js
@@ -87,6 +87,7 @@ export const spec = {
* @return {Bid[]} An array of bids which were nested inside the server.
*/
interpretResponse: function(serverResponse, {bidderRequest}) {
+ serverResponse = serverResponse.body;
const bids = [];
if (!serverResponse || serverResponse.error) {
let errorMessage = `in response for ${bidderRequest.bidderCode} adapter`;
diff --git a/modules/beachfrontBidAdapter.js b/modules/beachfrontBidAdapter.js
index 2729dcdd324..d4fcc3e3578 100644
--- a/modules/beachfrontBidAdapter.js
+++ b/modules/beachfrontBidAdapter.js
@@ -23,6 +23,7 @@ export const spec = {
},
interpretResponse(response, { bidRequest }) {
+ response = response.body;
if (!response || !response.url || !response.bidPrice) {
utils.logWarn(`No valid bids from ${spec.code} bidder`);
return [];
diff --git a/modules/jcmBidAdapter.js b/modules/jcmBidAdapter.js
index 3e0e46b8b77..4c9792a00f2 100644
--- a/modules/jcmBidAdapter.js
+++ b/modules/jcmBidAdapter.js
@@ -44,6 +44,7 @@ export const spec = {
interpretResponse: function(serverResponse) {
const bidResponses = [];
+ serverResponse = serverResponse.body;
// loop through serverResponses
if (serverResponse) {
if (serverResponse.bids) {
diff --git a/modules/platformioBidAdapter.js b/modules/platformioBidAdapter.js
index c33551ed396..2fb23ab92b3 100644
--- a/modules/platformioBidAdapter.js
+++ b/modules/platformioBidAdapter.js
@@ -24,7 +24,7 @@ export const spec = {
};
},
interpretResponse: (response, request) => (
- bidResponseAvailable(request, response)
+ bidResponseAvailable(request, response.body)
),
};
function bidResponseAvailable(bidRequest, bidResponse) {
diff --git a/modules/pulsepointLiteBidAdapter.js b/modules/pulsepointLiteBidAdapter.js
index 00b5c014e98..99a83871dd8 100644
--- a/modules/pulsepointLiteBidAdapter.js
+++ b/modules/pulsepointLiteBidAdapter.js
@@ -69,6 +69,7 @@ export const spec = {
function bidResponseAvailable(bidRequest, bidResponse) {
const idToImpMap = {};
const idToBidMap = {};
+ bidResponse = bidResponse.body
// extract the request bids and the response bids, keyed by impr-id
const ortbRequest = parse(bidRequest.data);
ortbRequest.imp.forEach(imp => {
diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js
index 69981ba2b56..866e02bc258 100644
--- a/modules/rubiconBidAdapter.js
+++ b/modules/rubiconBidAdapter.js
@@ -230,6 +230,7 @@ export const spec = {
* @return {Bid[]} An array of bids which
*/
interpretResponse: function(responseObj, {bidRequest}) {
+ responseObj = responseObj.body
let ads = responseObj.ads;
// check overall response
diff --git a/src/adapters/bidderFactory.js b/src/adapters/bidderFactory.js
index 12b7b931a9b..87dfd372b9c 100644
--- a/src/adapters/bidderFactory.js
+++ b/src/adapters/bidderFactory.js
@@ -44,7 +44,7 @@ import { logWarn, logError, parseQueryStringParameters, delayExecution } from 's
* @property {function(BidRequest[], bidderRequest): ServerRequest|ServerRequest[]} buildRequests Build the request to the Server
* which requests Bids for the given array of Requests. Each BidRequest in the argument array is guaranteed to have
* passed the isBidRequestValid() test.
- * @property {function(*, BidRequest): Bid[]} interpretResponse Given a successful response from the Server,
+ * @property {function(ServerResponse, BidRequest): Bid[]} interpretResponse Given a successful response from the Server,
* interpret it and return the Bid objects. This function will be run inside a try/catch.
* If it throws any errors, your bids will be discarded.
* @property {function(SyncOptions, Array): UserSync[]} [getUserSyncs] Given an array of all the responses
@@ -72,6 +72,15 @@ import { logWarn, logError, parseQueryStringParameters, delayExecution } from 's
* JSON-serialized into the Request body.
*/
+/**
+ * @typedef {object} ServerResponse
+ *
+ * @property {*} body The response body. If this is legal JSON, then it will be parsed. Otherwise it'll be a
+ * string with the body's content.
+ * @property {{get: function(string): string} headers The response headers.
+ * Call this like `ServerResponse.headers.get("Content-Type")`
+ */
+
/**
* @typedef {object} Bid
*
@@ -263,10 +272,16 @@ export function newBidder(spec) {
// If the server responds successfully, use the adapter code to unpack the Bids from it.
// If the adapter code fails, no bids should be added. After all the bids have been added, make
// sure to call the `onResponse` function so that we're one step closer to calling fillNoBids().
- function onSuccess(response) {
+ function onSuccess(response, responseObj) {
try {
response = JSON.parse(response);
} catch (e) { /* response might not be JSON... that's ok. */ }
+
+ // Make response headers available for #1742. These are lazy-loaded because most adapters won't need them.
+ response = {
+ body: response,
+ headers: headerParser(responseObj)
+ };
responses.push(response);
let bids;
@@ -296,6 +311,12 @@ export function newBidder(spec) {
logWarn(`Bidder ${spec.code} made bid for unknown request ID: ${bid.requestId}. Ignoring.`);
}
}
+
+ function headerParser(xmlHttpResponse) {
+ return {
+ get: responseObj.getResponseHeader.bind(responseObj)
+ };
+ }
}
// If the server responds with an error, there's not much we can do. Log it, and make sure to
diff --git a/test/spec/modules/adbutlerBidAdapter_spec.js b/test/spec/modules/adbutlerBidAdapter_spec.js
index 352358be8d0..de40f72073b 100644
--- a/test/spec/modules/adbutlerBidAdapter_spec.js
+++ b/test/spec/modules/adbutlerBidAdapter_spec.js
@@ -121,17 +121,19 @@ describe('AdButler adapter', () => {
describe('bid responses', () => {
it('should return complete bid response', () => {
let serverResponse = {
- status: 'SUCCESS',
- account_id: 167283,
- zone_id: 210093,
- cpm: 1.5,
- width: 300,
- height: 250,
- place: 0,
- ad_code: '
',
- tracking_pixels: [
- 'http://tracking.pixel.com/params=info'
- ]
+ body: {
+ status: 'SUCCESS',
+ account_id: 167283,
+ zone_id: 210093,
+ cpm: 1.5,
+ width: 300,
+ height: 250,
+ place: 0,
+ ad_code: '
',
+ tracking_pixels: [
+ 'http://tracking.pixel.com/params=info'
+ ]
+ }
},
bids = spec.interpretResponse(serverResponse, {'bidRequest': bidRequests[0]});
diff --git a/test/spec/modules/appnexusAstBidAdapter_spec.js b/test/spec/modules/appnexusAstBidAdapter_spec.js
index d07ee6df543..d76cc08810f 100644
--- a/test/spec/modules/appnexusAstBidAdapter_spec.js
+++ b/test/spec/modules/appnexusAstBidAdapter_spec.js
@@ -306,7 +306,7 @@ describe('AppNexusAdapter', () => {
];
let bidderRequest;
- let result = spec.interpretResponse(response, {bidderRequest});
+ let result = spec.interpretResponse({ body: response }, {bidderRequest});
expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0]));
});
@@ -322,7 +322,7 @@ describe('AppNexusAdapter', () => {
};
let bidderRequest;
- let result = spec.interpretResponse(response, {bidderRequest});
+ let result = spec.interpretResponse({ body: response }, {bidderRequest});
expect(result.length).to.equal(0);
});
@@ -343,7 +343,7 @@ describe('AppNexusAdapter', () => {
};
let bidderRequest;
- let result = spec.interpretResponse(response, {bidderRequest});
+ let result = spec.interpretResponse({ body: response }, {bidderRequest});
expect(result[0]).to.have.property('vastUrl');
expect(result[0]).to.have.property('descriptionUrl');
expect(result[0]).to.have.property('mediaType', 'video');
@@ -376,7 +376,7 @@ describe('AppNexusAdapter', () => {
};
let bidderRequest;
- let result = spec.interpretResponse(response1, {bidderRequest});
+ let result = spec.interpretResponse({ body: response1 }, {bidderRequest});
expect(result[0].native.title).to.equal('Native Creative');
expect(result[0].native.body).to.equal('Cool description great stuff');
expect(result[0].native.cta).to.equal('Do it');
diff --git a/test/spec/modules/beachfrontBidAdapter_spec.js b/test/spec/modules/beachfrontBidAdapter_spec.js
index 43df639613f..92e16573972 100644
--- a/test/spec/modules/beachfrontBidAdapter_spec.js
+++ b/test/spec/modules/beachfrontBidAdapter_spec.js
@@ -104,7 +104,7 @@ describe('BeachfrontAdapter', () => {
describe('spec.interpretResponse', () => {
it('should return no bids if the response is not valid', () => {
- const bidResponse = spec.interpretResponse(null, { bidRequest });
+ const bidResponse = spec.interpretResponse({ body: null }, { bidRequest });
expect(bidResponse.length).to.equal(0);
});
@@ -112,7 +112,7 @@ describe('BeachfrontAdapter', () => {
const serverResponse = {
bidPrice: 5.00
};
- const bidResponse = spec.interpretResponse(serverResponse, { bidRequest });
+ const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest });
expect(bidResponse.length).to.equal(0);
});
@@ -120,7 +120,7 @@ describe('BeachfrontAdapter', () => {
const serverResponse = {
url: 'http://reachms.bfmio.com/getmu?aid=bid:19c4a196-fb21-4c81-9a1a-ecc5437a39da'
};
- const bidResponse = spec.interpretResponse(serverResponse, { bidRequest });
+ const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest });
expect(bidResponse.length).to.equal(0);
});
@@ -130,7 +130,7 @@ describe('BeachfrontAdapter', () => {
url: 'http://reachms.bfmio.com/getmu?aid=bid:19c4a196-fb21-4c81-9a1a-ecc5437a39da',
cmpId: '123abc'
};
- const bidResponse = spec.interpretResponse(serverResponse, { bidRequest });
+ const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest });
expect(bidResponse).to.deep.equal({
requestId: bidRequest.bidId,
bidderCode: spec.code,
diff --git a/test/spec/modules/jcmBidAdapter_spec.js b/test/spec/modules/jcmBidAdapter_spec.js
index a063d6b9805..95356a9658e 100644
--- a/test/spec/modules/jcmBidAdapter_spec.js
+++ b/test/spec/modules/jcmBidAdapter_spec.js
@@ -94,7 +94,7 @@ describe('jcmAdapter', () => {
}
];
- let result = spec.interpretResponse(serverResponse);
+ let result = spec.interpretResponse({ body: serverResponse });
expect(Object.keys(result[0]).length).to.equal(Object.keys(expectedResponse[0]).length);
expect(Object.keys(result[0]).requestId).to.equal(Object.keys(expectedResponse[0]).requestId);
expect(Object.keys(result[0]).bidderCode).to.equal(Object.keys(expectedResponse[0]).bidderCode);
@@ -112,7 +112,7 @@ describe('jcmAdapter', () => {
it('handles nobid responses', () => {
let serverResponse = {'bids': []};
- let result = spec.interpretResponse(serverResponse);
+ let result = spec.interpretResponse({ body: serverResponse });
expect(result.length).to.equal(0);
});
});
diff --git a/test/spec/modules/platformioBidAdapter_spec.js b/test/spec/modules/platformioBidAdapter_spec.js
index 1b07b4049d4..86bf52cac72 100644
--- a/test/spec/modules/platformioBidAdapter_spec.js
+++ b/test/spec/modules/platformioBidAdapter_spec.js
@@ -63,7 +63,7 @@ describe('Platformio Adapter Tests', () => {
}]
}]
};
- const bids = spec.interpretResponse(ortbResponse, request);
+ const bids = spec.interpretResponse({ body: ortbResponse }, request);
expect(bids).to.have.lengthOf(1);
// verify first bid
const bid = bids[0];
@@ -78,7 +78,7 @@ describe('Platformio Adapter Tests', () => {
it('Verify full passback', () => {
const request = spec.buildRequests(slotConfigs);
- const bids = spec.interpretResponse(null, request)
+ const bids = spec.interpretResponse({ body: null }, request)
expect(bids).to.have.lengthOf(0);
});
diff --git a/test/spec/modules/pulsepointLiteBidAdapter_spec.js b/test/spec/modules/pulsepointLiteBidAdapter_spec.js
index 96f5c7a8d1f..9731164cd50 100644
--- a/test/spec/modules/pulsepointLiteBidAdapter_spec.js
+++ b/test/spec/modules/pulsepointLiteBidAdapter_spec.js
@@ -89,7 +89,7 @@ describe('PulsePoint Lite Adapter Tests', () => {
}]
}]
};
- const bids = spec.interpretResponse(ortbResponse, request);
+ const bids = spec.interpretResponse({ body: ortbResponse }, request);
expect(bids).to.have.lengthOf(1);
// verify first bid
const bid = bids[0];
@@ -104,7 +104,7 @@ describe('PulsePoint Lite Adapter Tests', () => {
it('Verify full passback', () => {
const request = spec.buildRequests(slotConfigs);
- const bids = spec.interpretResponse(null, request)
+ const bids = spec.interpretResponse({ body: null }, request)
expect(bids).to.have.lengthOf(0);
});
@@ -171,7 +171,7 @@ describe('PulsePoint Lite Adapter Tests', () => {
}]
}]
};
- const bids = spec.interpretResponse(ortbResponse, request);
+ const bids = spec.interpretResponse({ body: ortbResponse }, request);
// verify bid
const bid = bids[0];
expect(bid.cpm).to.equal(1.25);
diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js
index 620fc56e516..6c08c66f485 100644
--- a/test/spec/modules/rubiconBidAdapter_spec.js
+++ b/test/spec/modules/rubiconBidAdapter_spec.js
@@ -604,7 +604,7 @@ describe('the rubicon adapter', () => {
]
};
- let bids = spec.interpretResponse(response, {
+ let bids = spec.interpretResponse({ body: response }, {
bidRequest: bidderRequest.bids[0]
});
@@ -654,7 +654,7 @@ describe('the rubicon adapter', () => {
}]
};
- let bids = spec.interpretResponse(response, {
+ let bids = spec.interpretResponse({ body: response }, {
bidRequest: bidderRequest.bids[0]
});
@@ -677,7 +677,7 @@ describe('the rubicon adapter', () => {
'ads': []
};
- let bids = spec.interpretResponse(response, {
+ let bids = spec.interpretResponse({ body: response }, {
bidRequest: bidderRequest.bids[0]
});
@@ -701,7 +701,7 @@ describe('the rubicon adapter', () => {
}]
};
- let bids = spec.interpretResponse(response, {
+ let bids = spec.interpretResponse({ body: response }, {
bidRequest: bidderRequest.bids[0]
});
@@ -711,7 +711,7 @@ describe('the rubicon adapter', () => {
it('should handle an error because of malformed json response', () => {
let response = '{test{';
- let bids = spec.interpretResponse(response, {
+ let bids = spec.interpretResponse({ body: response }, {
bidRequest: bidderRequest.bids[0]
});
@@ -752,7 +752,7 @@ describe('the rubicon adapter', () => {
'account_id': 7780
};
- let bids = spec.interpretResponse(response, {
+ let bids = spec.interpretResponse({ body: response }, {
bidRequest: bidderRequest.bids[0]
});
diff --git a/test/spec/unit/core/bidderFactory_spec.js b/test/spec/unit/core/bidderFactory_spec.js
index e91ddcf39a4..3260b66da28 100644
--- a/test/spec/unit/core/bidderFactory_spec.js
+++ b/test/spec/unit/core/bidderFactory_spec.js
@@ -265,7 +265,9 @@ describe('bidders created by newBidder', () => {
beforeEach(() => {
ajaxStub = sinon.stub(ajax, 'ajax', function(url, callbacks) {
- callbacks.success('response body');
+ const fakeResponse = sinon.stub();
+ fakeResponse.returns('headerContent');
+ callbacks.success('response body', { getResponseHeader: fakeResponse });
});
userSyncStub = sinon.stub(userSync, 'registerSync')
});
@@ -275,7 +277,7 @@ describe('bidders created by newBidder', () => {
userSyncStub.restore();
});
- it('should call spec.interpretResponse() with the response body content', () => {
+ it('should call spec.interpretResponse() with the response content', () => {
const bidder = newBidder(spec);
spec.isBidRequestValid.returns(true);
@@ -289,7 +291,9 @@ describe('bidders created by newBidder', () => {
bidder.callBids(MOCK_BIDS_REQUEST);
expect(spec.interpretResponse.calledOnce).to.equal(true);
- expect(spec.interpretResponse.firstCall.args[0]).to.equal('response body');
+ const response = spec.interpretResponse.firstCall.args[0]
+ expect(response.body).to.equal('response body')
+ expect(response.headers.get('some-header')).to.equal('headerContent');
expect(spec.interpretResponse.firstCall.args[1]).to.deep.equal({
method: 'POST',
url: 'test.url.com',
@@ -364,7 +368,10 @@ describe('bidders created by newBidder', () => {
bidder.callBids(MOCK_BIDS_REQUEST);
expect(spec.getUserSyncs.calledOnce).to.equal(true);
- expect(spec.getUserSyncs.firstCall.args[1]).to.deep.equal(['response body']);
+ expect(spec.getUserSyncs.firstCall.args[1].length).to.equal(1);
+ expect(spec.getUserSyncs.firstCall.args[1][0].body).to.equal('response body');
+ expect(spec.getUserSyncs.firstCall.args[1][0].headers).to.have.property('get');
+ expect(spec.getUserSyncs.firstCall.args[1][0].headers.get).to.be.a('function');
});
it('should register usersync pixels', () => {