@webex/http-core 3.0.0-bnr.4 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/.eslintrc.js +6 -0
  2. package/babel.config.js +3 -0
  3. package/dist/http-error-subtypes.js.map +1 -1
  4. package/dist/http-error.js +21 -22
  5. package/dist/http-error.js.map +1 -1
  6. package/dist/index.js +58 -13
  7. package/dist/index.js.map +1 -1
  8. package/dist/interceptors/http-status.js +4 -3
  9. package/dist/interceptors/http-status.js.map +1 -1
  10. package/dist/lib/detect.js.map +1 -1
  11. package/dist/lib/interceptor.js +6 -4
  12. package/dist/lib/interceptor.js.map +1 -1
  13. package/dist/lib/xhr.js +7 -3
  14. package/dist/lib/xhr.js.map +1 -1
  15. package/dist/progress-event.js +6 -2
  16. package/dist/progress-event.js.map +1 -1
  17. package/dist/request/index.js +3 -30
  18. package/dist/request/index.js.map +1 -1
  19. package/dist/request/request.js.map +1 -1
  20. package/dist/request/request.shim.js +13 -11
  21. package/dist/request/request.shim.js.map +1 -1
  22. package/dist/request/utils.js +91 -0
  23. package/dist/request/utils.js.map +1 -0
  24. package/jest.config.js +3 -0
  25. package/package.json +31 -13
  26. package/process +1 -0
  27. package/src/index.js +55 -0
  28. package/src/lib/xhr.js +5 -1
  29. package/src/request/index.js +4 -36
  30. package/src/request/request.shim.js +5 -2
  31. package/src/request/utils.ts +78 -0
  32. package/test/integration/spec/request.js +2 -1
  33. package/test/unit/spec/index.js +58 -0
  34. package/test/unit/spec/request/request.shim.js +28 -0
  35. package/test/unit/spec/request/utils.js +77 -0
  36. package/dist/types/http-error-subtypes.d.ts +0 -8
  37. package/dist/types/http-error.d.ts +0 -41
  38. package/dist/types/index.d.ts +0 -7
  39. package/dist/types/interceptors/http-status.d.ts +0 -17
  40. package/dist/types/lib/detect.d.ts +0 -6
  41. package/dist/types/lib/interceptor.d.ts +0 -51
  42. package/dist/types/lib/xhr.d.ts +0 -6
  43. package/dist/types/progress-event.d.ts +0 -18
  44. package/dist/types/request/index.d.ts +0 -5
  45. package/dist/types/request/request.d.ts +0 -6
  46. package/dist/types/request/request.shim.d.ts +0 -6
@@ -0,0 +1,78 @@
1
+ /* eslint-disable import/prefer-default-export */
2
+ import {EventEmitter} from 'events';
3
+ import Interceptor from '../lib/interceptor';
4
+
5
+ /**
6
+ * @param {Object} options
7
+ * @param {Array<Object>} interceptors
8
+ * @param {string} key
9
+ * @param {Object | undefined} res
10
+ * @private
11
+ * @returns {Promise}
12
+ */
13
+ export function intercept(
14
+ options: object,
15
+ interceptors: Array<Interceptor>,
16
+ key: string,
17
+ res: object = undefined
18
+ ): Promise<any> {
19
+ const successKey = `on${key}`;
20
+ const errorKey = `on${key}Error`;
21
+
22
+ return interceptors.reduce(
23
+ (promise, interceptor) =>
24
+ promise.then(
25
+ (result) => {
26
+ interceptor.logOptions(options);
27
+ if (interceptor[successKey]) {
28
+ return interceptor[successKey](options, result);
29
+ }
30
+
31
+ return Promise.resolve(result);
32
+ },
33
+ (reason) => {
34
+ interceptor.logOptions(options);
35
+ if (interceptor[errorKey]) {
36
+ return interceptor[errorKey](options, reason);
37
+ }
38
+
39
+ return Promise.reject(reason);
40
+ }
41
+ ),
42
+ Promise.resolve(res)
43
+ );
44
+ }
45
+
46
+ /**
47
+ * Prepare options for a fetch.
48
+ * @param {object} options
49
+ * @returns {Promise}
50
+ */
51
+ export async function prepareFetchOptions(options: any): Promise<any> {
52
+ if (options.url) {
53
+ options.uri = options.url;
54
+ options.url = null;
55
+ }
56
+
57
+ options.headers = options.headers || {};
58
+
59
+ if (options.json) {
60
+ // don't override existing accept header declared by user
61
+ options.headers.accept = options.headers.accept || options.headers.Accept || 'application/json';
62
+
63
+ // don't override existing content-type header declared by user
64
+ if (options.method !== 'GET' && options.method !== 'HEAD') {
65
+ options.headers['content-type'] =
66
+ options.headers['content-type'] || options.headers['Content-Type'] || 'application/json';
67
+ options.body = JSON.stringify(options.json === true ? options.body : options.json);
68
+ }
69
+ } else if (options.json !== undefined) {
70
+ Reflect.deleteProperty(options, 'json');
71
+ }
72
+
73
+ options.download = new EventEmitter();
74
+ options.upload = new EventEmitter();
75
+ options.keepalive = true;
76
+
77
+ return intercept(options, options.interceptors, 'Request').then(() => options);
78
+ }
@@ -78,7 +78,8 @@ describe('http-core', function () {
78
78
  }));
79
79
  });
80
80
 
81
- it('makes CORS compatible calls', () =>
81
+ // SPARK-413317
82
+ it.skip('makes CORS compatible calls', () =>
82
83
  request({
83
84
  uri: 'https://ds.ciscospark.com/v1/region/',
84
85
  }).then((res) => {
@@ -0,0 +1,58 @@
1
+ import {assert} from '@webex/test-helper-chai';
2
+ import sinon from 'sinon';
3
+
4
+ import * as utils from '@webex/http-core/src/request/utils';
5
+ import WebexTrackingIdInterceptor from '@webex/webex-core/src/interceptors/webex-tracking-id';
6
+ import UserAgentInterceptor from '@webex/webex-core/src/interceptors/webex-user-agent';
7
+ import {protoprepareFetchOptions, setTimingsAndFetch} from '@webex/http-core/src/index';
8
+
9
+ describe('http-core index tests', () => {
10
+ describe('#protoprepareFetchOptions()', () => {
11
+ it('uses default options and adds expected options', async () => {
12
+ const defaultOptions = {
13
+ interceptors: [WebexTrackingIdInterceptor.create(), UserAgentInterceptor.create()],
14
+ };
15
+ const options = {};
16
+
17
+ const prepareFetchOptions = protoprepareFetchOptions(defaultOptions);
18
+
19
+ await prepareFetchOptions(options);
20
+
21
+ assert.deepEqual(options, {
22
+ headers: {
23
+ trackingid: 'undefined_1',
24
+ 'spark-user-agent': 'webex-js-sdk/development (node)',
25
+ },
26
+ keepalive: true,
27
+ });
28
+
29
+ assert.equal(typeof options.logger, 'object');
30
+ assert.equal(typeof options.upload, 'object');
31
+ assert.equal(typeof options.download, 'object');
32
+ assert.isArray(options.interceptors);
33
+ });
34
+ });
35
+
36
+ describe('#setTimingsAndFetch()', () => {
37
+ const now = Date.now();
38
+ let stubbedFetch;
39
+
40
+ beforeEach(() => {
41
+ global.fetch = sinon.stub();
42
+ });
43
+
44
+ it('calls fetch with expected options', async () => {
45
+ sinon.useFakeTimers(now);
46
+ const options = {uri: 'foo'};
47
+
48
+ const newOptions = setTimingsAndFetch(options);
49
+
50
+ sinon.assert.calledOnce(global.fetch);
51
+ sinon.assert.calledWith(global.fetch, 'foo', {
52
+ uri: 'foo',
53
+ $timings: {requestStart: now, networkStart: now},
54
+ });
55
+ sinon.restore();
56
+ });
57
+ });
58
+ });
@@ -0,0 +1,28 @@
1
+ import {assert} from '@webex/test-helper-chai';
2
+ import window from 'global/window';
3
+ import request from '@webex/http-core/src/request/request.shim';
4
+ import {EventEmitter} from 'events';
5
+
6
+ describe('Request shim', () => {
7
+ describe('#setAuth()', () => {
8
+ beforeAll(() => {
9
+ global.Blob = function (content, options) {
10
+ return { content, options };
11
+ };
12
+ });
13
+ it('sets auth header', () => {
14
+
15
+ class DummyXMLHttpRequest {
16
+ upload = new EventEmitter();
17
+ }
18
+
19
+ window.XMLHttpRequest = DummyXMLHttpRequest;
20
+
21
+ const options = {upload: new EventEmitter(), headers: [], method: 'post', ...options, auth: {user: 'test', pass: 'pw'}, logger: {warn: () => {}}};
22
+
23
+ request(options);
24
+
25
+ assert.equal(options.headers.Authorization, 'Basic dGVzdDpwdw==');
26
+ });
27
+ });
28
+ });
@@ -0,0 +1,77 @@
1
+ import {assert} from '@webex/test-helper-chai';
2
+ import sinon from 'sinon';
3
+
4
+ import * as utils from '@webex/http-core/src/request/utils';
5
+ import WebexTrackingIdInterceptor from '@webex/webex-core/src/interceptors/webex-tracking-id';
6
+ import UserAgentInterceptor from '@webex/webex-core/src/interceptors/webex-user-agent';
7
+
8
+ describe('Request utils', () => {
9
+ describe('#intercept()', () => {
10
+ it('updates options from interceptors', async () => {
11
+ const options = {};
12
+ const interceptors = [WebexTrackingIdInterceptor.create(), UserAgentInterceptor.create()];
13
+
14
+ return utils.intercept(options, interceptors, 'Request').then(() => {
15
+ assert.equal(Object.keys(options.headers).length, 2);
16
+ assert.equal(options.headers.trackingid, 'undefined_1');
17
+ assert.equal(options.headers['spark-user-agent'], 'webex-js-sdk/development (node)');
18
+ });
19
+ });
20
+ });
21
+
22
+ describe('#prepareFetchOptions()', () => {
23
+ it('updates options as expected', async () => {
24
+ const options = {
25
+ json: true,
26
+ body: {foo: 'bar'},
27
+ headers: {},
28
+ interceptors: [WebexTrackingIdInterceptor.create(), UserAgentInterceptor.create()],
29
+ };
30
+
31
+ return utils.prepareFetchOptions(options).then(() => {
32
+ assert.deepEqual(options.headers, {
33
+ accept: 'application/json',
34
+ 'content-type': 'application/json',
35
+ trackingid: 'undefined_1',
36
+ 'spark-user-agent': 'webex-js-sdk/development (node)',
37
+ });
38
+
39
+ assert.equal(options.body, '{"foo":"bar"}');
40
+
41
+ assert.equal(options.download != undefined, true);
42
+ assert.equal(options.upload != undefined, true);
43
+ assert.equal(options.keepalive, true);
44
+ });
45
+ });
46
+
47
+ it('updates options as expected when accept and content-type exist', async () => {
48
+ const options = {
49
+ json: true,
50
+ body: {foo: 'bar'},
51
+ headers: {accept: 'foo', 'content-type': 'bar'},
52
+ interceptors: [WebexTrackingIdInterceptor.create(), UserAgentInterceptor.create()],
53
+ };
54
+
55
+ return utils.prepareFetchOptions(options).then(() => {
56
+ assert.deepEqual(options.headers, {
57
+ accept: 'foo',
58
+ 'content-type': 'bar',
59
+ trackingid: 'undefined_1',
60
+ 'spark-user-agent': 'webex-js-sdk/development (node)',
61
+ });
62
+ });
63
+ });
64
+
65
+ it('updates body as expected when json = some object', async () => {
66
+ const options = {
67
+ json: {bar: 'baz'},
68
+ headers: {accept: 'foo', 'content-type': 'bar'},
69
+ interceptors: [WebexTrackingIdInterceptor.create(), UserAgentInterceptor.create()],
70
+ };
71
+
72
+ return utils.prepareFetchOptions(options).then(() => {
73
+ assert.equal(options.body, '{"bar":"baz"}');
74
+ });
75
+ });
76
+ });
77
+ });
@@ -1,8 +0,0 @@
1
- /*!
2
- * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
- */
4
- /**
5
- * @param {Error} Base
6
- * @returns {undefined}
7
- */
8
- export default function makeSubTypes(Base: Error): undefined;
@@ -1,41 +0,0 @@
1
- /**
2
- * Base HttpError class. Unlikely to be thrown directly, but handy for general
3
- * type comparison.
4
- */
5
- declare class HttpError {
6
- /**
7
- * @example Extend via
8
- * MyError extends HttpError {
9
- * static errorKeys = HttpError.errorKeys.concat([
10
- * `key1`,
11
- * `key2`
12
- * ])
13
- * }
14
- *
15
- * @type {Array}
16
- */
17
- static errorKeys: any[];
18
- /**
19
- * Default error string if no error can be extracted from the http response
20
- * @type {string}
21
- */
22
- static defaultMessage: string;
23
- /**
24
- * Parses HttpResponse objects for useful information (status, headers, etc)
25
- * as well as attempting to extract a useful error message.
26
- * @param {HttpResponse} res
27
- * @returns {string}
28
- */
29
- parse(res: HttpResponse): string;
30
- /**
31
- * Recursively parses an error body looking for a likely error candidate
32
- * @param {object} body
33
- * @returns {string}
34
- */
35
- parseObject(body: object): string;
36
- }
37
- declare namespace HttpError {
38
- export { makeSubTypes };
39
- }
40
- export default HttpError;
41
- import makeSubTypes from "./http-error-subtypes";
@@ -1,7 +0,0 @@
1
- export const defaults: import("lodash").CurriedFunction1<any, Promise<any>>;
2
- export const request: Promise<any>;
3
- export { default as ProgressEvent } from "./progress-event";
4
- export { default as Interceptor } from "./lib/interceptor";
5
- export { default as HttpError } from "./http-error";
6
- export { default as HttpStatusInterceptor } from "./interceptors/http-status";
7
- export { default as detect } from "./lib/detect";
@@ -1,17 +0,0 @@
1
- /**
2
- * @class
3
- */
4
- export default class HttpStatusInterceptor extends Interceptor {
5
- /**
6
- * @param {Object} options
7
- * @returns {HttpStatusInterceptor}
8
- */
9
- static create(options: any): HttpStatusInterceptor;
10
- /**
11
- * @param {Object} webex
12
- * @param {Object} options
13
- * @returns {HttpStatusInterceptor}
14
- */
15
- constructor(webex: any, options: any);
16
- }
17
- import Interceptor from "../lib/interceptor";
@@ -1,6 +0,0 @@
1
- /**
2
- * Determine mimeType for the specified buffer;
3
- * @param {Buffer|Uint8Array|ArrayBuffer} buffer
4
- * @returns {Promise<string>}
5
- */
6
- export default function detect(buffer: Buffer | Uint8Array | ArrayBuffer): Promise<string>;
@@ -1,51 +0,0 @@
1
- /**
2
- * @class
3
- */
4
- export default class Interceptor {
5
- /**
6
- * @abstract
7
- * @returns {Interceptor}
8
- */
9
- static create(): Interceptor;
10
- /**
11
- * @constructor
12
- * @param {Object} attrs
13
- * @returns {UrlInterceptor}
14
- */
15
- constructor(attrs: any);
16
- /**
17
- * Logs the options of a request. This should be utilized
18
- * during the intercepting process, but can be used at any
19
- * time otherwise.
20
- * @param {object} options
21
- * @returns {void}
22
- */
23
- logOptions(options?: object): void;
24
- /**
25
- * Transform request options before sending them
26
- * @param {Object} options
27
- * @returns {Promise<Object>}
28
- */
29
- onRequest(options: any): Promise<any>;
30
- /**
31
- * Handle request failures
32
- * @param {Object} options
33
- * @param {Error} reason
34
- * @returns {RejectedPromise<Error>}
35
- */
36
- onRequestError(options: any, reason: Error): RejectedPromise<Error>;
37
- /**
38
- * Transform response before returning it
39
- * @param {Object} options
40
- * @param {HttpResponse} response
41
- * @returns {Promise<HttpResponse>}
42
- */
43
- onResponse(options: any, response: HttpResponse): Promise<HttpResponse>;
44
- /**
45
- * Handle response errors
46
- * @param {Object} options
47
- * @param {WebexHttpError} reason
48
- * @returns {Promise<WebexHttpError>}
49
- */
50
- onResponseError(options: any, reason: WebexHttpError): Promise<WebexHttpError>;
51
- }
@@ -1,6 +0,0 @@
1
- export default createXHR;
2
- declare function createXHR(uri: any, options: any, callback: any): any;
3
- declare namespace createXHR {
4
- const XMLHttpRequest: any;
5
- const XDomainRequest: any;
6
- }
@@ -1,18 +0,0 @@
1
- /**
2
- * Object of the same shape as web browser ProgressEvents
3
- * @class ProgressEvent
4
- * @param {integer} loaded
5
- * @param {integer} total
6
- * @returns {ProgressEvent}
7
- */
8
- export default function ProgressEvent(loaded: integer, total: integer): ProgressEvent;
9
- export default class ProgressEvent {
10
- /**
11
- * Object of the same shape as web browser ProgressEvents
12
- * @class ProgressEvent
13
- * @param {integer} loaded
14
- * @param {integer} total
15
- * @returns {ProgressEvent}
16
- */
17
- constructor(loaded: integer, total: integer);
18
- }
@@ -1,5 +0,0 @@
1
- /**
2
- * @param {Object} options
3
- * @returns {Promise}
4
- */
5
- export default function request(options: any): Promise<any>;
@@ -1,6 +0,0 @@
1
- /**
2
- * @name request
3
- * @param {Object} options
4
- * @returns {Promise}
5
- */
6
- export default function _request(options: any): Promise<any>;
@@ -1,6 +0,0 @@
1
- /**
2
- * @name request
3
- * @param {Object} options
4
- * @returns {Promise}
5
- */
6
- export default function _request(options: any): Promise<any>;