-
Notifications
You must be signed in to change notification settings - Fork 44
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: Use fetch instead of XHR for Alias Requests (#915)
- Loading branch information
Showing
13 changed files
with
874 additions
and
114 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import { IAliasRequest, IAliasCallback } from "./identity.interfaces"; | ||
import { MParticleWebSDK } from "./sdkRuntimeModels"; | ||
import Constants from './constants'; | ||
import { FetchUploader, XHRUploader } from './uploaders'; | ||
import { HTTP_ACCEPTED, HTTP_OK } from "./constants"; | ||
|
||
|
||
const { HTTPCodes, Messages } = Constants; | ||
|
||
interface IAliasResponseBody { | ||
message?: string | ||
} | ||
|
||
export async function sendAliasRequest (mpInstance: MParticleWebSDK, aliasRequest: IAliasRequest, aliasCallback: IAliasCallback) { | ||
const { verbose, error } = mpInstance.Logger; | ||
const { invokeAliasCallback } = mpInstance._Helpers; | ||
const { aliasUrl } = mpInstance._Store.SDKConfig; | ||
const { devToken: apiKey } = mpInstance._Store; | ||
|
||
verbose(Messages.InformationMessages.SendAliasHttp); | ||
|
||
// https://go.mparticle.com/work/SQDSDKS-6750 | ||
const uploadUrl = `https://${aliasUrl}${apiKey}/Alias`; | ||
const uploader = window.fetch | ||
? new FetchUploader(uploadUrl) | ||
: new XHRUploader(uploadUrl); | ||
|
||
|
||
// https://go.mparticle.com/work/SQDSDKS-6568 | ||
const uploadPayload = { | ||
method: 'post', | ||
headers: { | ||
Accept: 'text/plain;charset=UTF-8', | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify(aliasRequest), | ||
}; | ||
|
||
try { | ||
const response = await uploader.upload(uploadPayload); | ||
|
||
let message: string; | ||
let aliasResponseBody: IAliasResponseBody; | ||
|
||
// FetchUploader returns the response as a JSON object that we have to await | ||
if (response.json) { | ||
// HTTP responses of 202, 200, and 403 do not have a response. response.json will always exist on a fetch, but can only be await-ed when the response is not empty, otherwise it will throw an error. | ||
try { | ||
aliasResponseBody = await response.json(); | ||
} catch (e) { | ||
verbose('The request has no response body'); | ||
} | ||
} else { | ||
// https://go.mparticle.com/work/SQDSDKS-6568 | ||
// XHRUploader returns the response as a string that we need to parse | ||
const xhrResponse = response as unknown as XMLHttpRequest; | ||
// debugger; | ||
aliasResponseBody = xhrResponse.responseText | ||
? JSON.parse(xhrResponse.responseText) | ||
: ''; | ||
} | ||
|
||
let errorMessage: string; | ||
|
||
switch (response.status) { | ||
case HTTP_OK: | ||
case HTTP_ACCEPTED: | ||
// https://go.mparticle.com/work/SQDSDKS-6670 | ||
message = | ||
'Successfully sent forwarding stats to mParticle Servers'; | ||
break; | ||
default: | ||
// 400 has an error message, but 403 doesn't | ||
if (aliasResponseBody?.message) { | ||
errorMessage = aliasResponseBody.message; | ||
} | ||
message = | ||
'Issue with sending Alias Request to mParticle Servers, received HTTP Code of ' + | ||
response.status; | ||
} | ||
|
||
verbose(message); | ||
invokeAliasCallback(aliasCallback, response.status, errorMessage); | ||
} catch (e) { | ||
const err = e as Error; | ||
error('Error sending alias request to mParticle servers. ' + err); | ||
invokeAliasCallback(aliasCallback, HTTPCodes.noHttpCoverage, (err.message)); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
import sinon from 'sinon'; | ||
import fetchMock from 'fetch-mock/esm/client'; | ||
import { urls, apiKey, MPConfig, testMPID } from './config/constants'; | ||
import { MParticleWebSDK } from '../../src/sdkRuntimeModels'; | ||
import { expect } from 'chai'; | ||
import { sendAliasRequest } from '../../src/aliasRequestApiClient'; | ||
import { IAliasCallback, IAliasRequest } from '../../src/identity.interfaces'; | ||
import { HTTP_ACCEPTED, HTTP_BAD_REQUEST, HTTP_FORBIDDEN, HTTP_OK } from '../../src/constants'; | ||
|
||
declare global { | ||
interface Window { | ||
mParticle: MParticleWebSDK; | ||
fetchMock: any; | ||
} | ||
} | ||
|
||
let mockServer; | ||
const mParticle = window.mParticle; | ||
|
||
declare global { | ||
interface Window { | ||
mParticle: MParticleWebSDK; | ||
fetchMock: any; | ||
} | ||
} | ||
|
||
const aliasUrl = 'https://jssdks.mparticle.com/v1/identity/test_key/Alias'; | ||
|
||
describe('Alias Request Api Client', function() { | ||
beforeEach(function() { | ||
fetchMock.post(urls.events, 200); | ||
mockServer = sinon.createFakeServer(); | ||
mockServer.respondImmediately = true; | ||
|
||
mockServer.respondWith(urls.identify, [ | ||
200, | ||
{}, | ||
JSON.stringify({ mpid: testMPID, is_logged_in: false }), | ||
]); | ||
mParticle.init(apiKey, window.mParticle.config); | ||
}); | ||
|
||
afterEach(function() { | ||
mockServer.restore(); | ||
fetchMock.restore(); | ||
mParticle._resetForTests(MPConfig); | ||
}); | ||
|
||
it('should have just an httpCode on the result passed to the callback on a 200', async () => { | ||
const mpInstance: MParticleWebSDK = mParticle.getInstance(); | ||
const aliasRequest: IAliasRequest = { | ||
destinationMpid: '123', | ||
sourceMpid: '456', | ||
startTime: 10001230123, | ||
endTime: 10001231123 | ||
}; | ||
|
||
const aliasCallback = sinon.spy() | ||
fetchMock.post(aliasUrl, HTTP_OK); | ||
|
||
await sendAliasRequest(mpInstance, aliasRequest, aliasCallback); | ||
expect(aliasCallback.calledOnce).to.eq(true); | ||
const callbackArgs = aliasCallback.getCall(0).args | ||
expect(callbackArgs[0]).to.deep.equal({httpCode: HTTP_OK}); | ||
}); | ||
|
||
it('should have just an httpCode on the result passed to the callback on a 202', async () => { | ||
const mpInstance: MParticleWebSDK = mParticle.getInstance(); | ||
const aliasRequest: IAliasRequest = { | ||
destinationMpid: '123', | ||
sourceMpid: '456', | ||
startTime: 10001230123, | ||
endTime: 10001231123 | ||
}; | ||
|
||
const aliasCallback = sinon.spy() | ||
fetchMock.post(aliasUrl, HTTP_ACCEPTED); | ||
|
||
await sendAliasRequest(mpInstance, aliasRequest, aliasCallback); | ||
expect(aliasCallback.calledOnce).to.eq(true); | ||
const callbackArgs = aliasCallback.getCall(0).args | ||
expect(callbackArgs[0]).to.deep.equal({httpCode: HTTP_ACCEPTED}); | ||
}); | ||
|
||
it('should have just an httpCode on the result passed to the callback on a 400', async () => { | ||
const mpInstance: MParticleWebSDK = mParticle.getInstance(); | ||
const aliasRequest: IAliasRequest = { | ||
destinationMpid: '123', | ||
sourceMpid: '456', | ||
startTime: 10001230123, | ||
endTime: 10001231123 | ||
}; | ||
|
||
const aliasCallback = sinon.spy() | ||
fetchMock.post(aliasUrl, HTTP_BAD_REQUEST); | ||
|
||
await sendAliasRequest(mpInstance, aliasRequest, aliasCallback); | ||
expect(aliasCallback.calledOnce).to.eq(true); | ||
const callbackArgs = aliasCallback.getCall(0).args | ||
expect(callbackArgs[0]).to.deep.equal({httpCode: HTTP_BAD_REQUEST}); | ||
}); | ||
|
||
it('should have an httpCode and an error message passed to the callback on a 403', async () => { | ||
const mpInstance: MParticleWebSDK = mParticle.getInstance(); | ||
const aliasRequest: IAliasRequest = { | ||
destinationMpid: '123', | ||
sourceMpid: '456', | ||
startTime: 10001230123, | ||
endTime: 10001231123 | ||
}; | ||
|
||
const aliasCallback = sinon.spy() | ||
fetchMock.post(aliasUrl, { | ||
status: HTTP_FORBIDDEN, | ||
body: JSON.stringify({message: 'error'}), | ||
}); | ||
|
||
await sendAliasRequest(mpInstance, aliasRequest, aliasCallback); | ||
expect(aliasCallback.calledOnce).to.eq(true); | ||
const callbackArgs = aliasCallback.getCall(0).args | ||
expect(callbackArgs[0]).to.deep.equal({httpCode: HTTP_FORBIDDEN, message: 'error'}); | ||
}); | ||
}); |
Oops, something went wrong.