From 155e5bf54e122fc75814b27674fbfe520e9b879c Mon Sep 17 00:00:00 2001 From: Stratoula Kalafateli Date: Thu, 12 May 2022 12:16:52 +0300 Subject: [PATCH 1/9] [Unified search] Decrease plugin's size (#131784) * [Unified search] Decrease plugin's size * Load scss from a single file where possible * Apply PR comment Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- src/plugins/unified_search/public/index.scss | 6 +----- src/plugins/unified_search/public/plugin.ts | 2 ++ .../public/query_string_input/_index.scss | 1 - .../public/query_string_input/query_bar.scss | 13 ++++++++++++ .../query_string_input/query_bar_top_row.tsx | 1 + ...query_bar.scss => query_string_input.scss} | 20 +++---------------- .../query_string_input/query_string_input.tsx | 1 + .../public/saved_query_management/_index.scss | 1 - ....scss => saved_query_management_list.scss} | 0 .../saved_query_management_list.tsx | 1 + .../public/search_bar/index.tsx | 1 - .../public/typeahead/_index.scss | 1 - 12 files changed, 22 insertions(+), 26 deletions(-) mode change 100755 => 100644 src/plugins/unified_search/public/index.scss delete mode 100644 src/plugins/unified_search/public/query_string_input/_index.scss create mode 100644 src/plugins/unified_search/public/query_string_input/query_bar.scss rename src/plugins/unified_search/public/query_string_input/{_query_bar.scss => query_string_input.scss} (79%) delete mode 100644 src/plugins/unified_search/public/saved_query_management/_index.scss rename src/plugins/unified_search/public/saved_query_management/{_saved_query_management_list.scss => saved_query_management_list.scss} (100%) delete mode 100644 src/plugins/unified_search/public/typeahead/_index.scss diff --git a/src/plugins/unified_search/public/index.scss b/src/plugins/unified_search/public/index.scss old mode 100755 new mode 100644 index 72e1c0c313f74..d19013fb408a3 --- a/src/plugins/unified_search/public/index.scss +++ b/src/plugins/unified_search/public/index.scss @@ -1,5 +1 @@ -@import './typeahead/index'; - -@import './saved_query_management/index'; - -@import './query_string_input/index'; +@import './typeahead/suggestion'; \ No newline at end of file diff --git a/src/plugins/unified_search/public/plugin.ts b/src/plugins/unified_search/public/plugin.ts index 08f07e507d96b..59c327449d354 100755 --- a/src/plugins/unified_search/public/plugin.ts +++ b/src/plugins/unified_search/public/plugin.ts @@ -23,6 +23,8 @@ import type { import { createFilterAction } from './actions/apply_filter_action'; import { ACTION_GLOBAL_APPLY_FILTER } from './actions'; +import './index.scss'; + export class UnifiedSearchPublicPlugin implements Plugin { diff --git a/src/plugins/unified_search/public/query_string_input/_index.scss b/src/plugins/unified_search/public/query_string_input/_index.scss deleted file mode 100644 index 1d955920b8e13..0000000000000 --- a/src/plugins/unified_search/public/query_string_input/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './query_bar'; diff --git a/src/plugins/unified_search/public/query_string_input/query_bar.scss b/src/plugins/unified_search/public/query_string_input/query_bar.scss new file mode 100644 index 0000000000000..89cca695ee154 --- /dev/null +++ b/src/plugins/unified_search/public/query_string_input/query_bar.scss @@ -0,0 +1,13 @@ +.kbnQueryBar__datePickerWrapper { + .euiDatePopoverButton-isInvalid { + background-image: euiFormControlGradient($euiColorDanger); + + // @todo Remove when EUI issue is resolved. + // @see https://github.com/elastic/eui/issues/4612 + &:focus { + color: $euiTextColor; + background-color: $euiFormBackgroundColor; + background-image: euiFormControlGradient($euiColorPrimary); + } + } +} diff --git a/src/plugins/unified_search/public/query_string_input/query_bar_top_row.tsx b/src/plugins/unified_search/public/query_string_input/query_bar_top_row.tsx index 0bff12ac78798..5427c61b485df 100644 --- a/src/plugins/unified_search/public/query_string_input/query_bar_top_row.tsx +++ b/src/plugins/unified_search/public/query_string_input/query_bar_top_row.tsx @@ -43,6 +43,7 @@ import { shallowEqual } from '../utils/shallow_equal'; import { AddFilterPopover } from './add_filter_popover'; import { DataViewPicker, DataViewPickerProps } from '../dataview_picker'; import { FilterButtonGroup } from '../filter_bar/filter_button_group/filter_button_group'; +import './query_bar.scss'; const SuperDatePicker = React.memo( EuiSuperDatePicker as any diff --git a/src/plugins/unified_search/public/query_string_input/_query_bar.scss b/src/plugins/unified_search/public/query_string_input/query_string_input.scss similarity index 79% rename from src/plugins/unified_search/public/query_string_input/_query_bar.scss rename to src/plugins/unified_search/public/query_string_input/query_string_input.scss index 7b9a735d1556f..f0a682564fa0e 100644 --- a/src/plugins/unified_search/public/query_string_input/_query_bar.scss +++ b/src/plugins/unified_search/public/query_string_input/query_string_input.scss @@ -4,7 +4,7 @@ height: $euiFormControlHeight; display: flex; - > [aria-expanded='true'] { + >[aria-expanded='true'] { // Using filter allows it to adhere the children's bounds filter: drop-shadow(0 5.7px 12px rgba($euiShadowColor, shadowOpacity(.05))); } @@ -52,7 +52,7 @@ @include euiFormControlWithIcon($isIconOptional: true); - ~ .euiFormControlLayoutIcons { + ~.euiFormControlLayoutIcons { // By default form control layout icon is vertically centered, but our textarea // can expand to be multi-line, so we position it with padding that matches // the parent textarea padding @@ -67,18 +67,4 @@ margin-left: -1px; width: calc(100% + 1px); } -} - -.kbnQueryBar__datePickerWrapper { - .euiDatePopoverButton-isInvalid { - background-image: euiFormControlGradient($euiColorDanger); - - // @todo Remove when EUI issue is resolved. - // @see https://github.com/elastic/eui/issues/4612 - &:focus { - color: $euiTextColor; - background-color: $euiFormBackgroundColor; - background-image: euiFormControlGradient($euiColorPrimary); - } - } -} +} \ No newline at end of file diff --git a/src/plugins/unified_search/public/query_string_input/query_string_input.tsx b/src/plugins/unified_search/public/query_string_input/query_string_input.tsx index 31ff302f9e699..dc606690fb7dd 100644 --- a/src/plugins/unified_search/public/query_string_input/query_string_input.tsx +++ b/src/plugins/unified_search/public/query_string_input/query_string_input.tsx @@ -45,6 +45,7 @@ import { onRaf } from '../utils'; import { FilterButtonGroup } from '../filter_bar/filter_button_group/filter_button_group'; import { QuerySuggestion, QuerySuggestionTypes } from '../autocomplete'; import { getTheme, getAutocomplete } from '../services'; +import './query_string_input.scss'; export interface QueryStringInputProps { indexPatterns: Array; diff --git a/src/plugins/unified_search/public/saved_query_management/_index.scss b/src/plugins/unified_search/public/saved_query_management/_index.scss deleted file mode 100644 index 0c90d7817b685..0000000000000 --- a/src/plugins/unified_search/public/saved_query_management/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './saved_query_management_list'; diff --git a/src/plugins/unified_search/public/saved_query_management/_saved_query_management_list.scss b/src/plugins/unified_search/public/saved_query_management/saved_query_management_list.scss similarity index 100% rename from src/plugins/unified_search/public/saved_query_management/_saved_query_management_list.scss rename to src/plugins/unified_search/public/saved_query_management/saved_query_management_list.scss diff --git a/src/plugins/unified_search/public/saved_query_management/saved_query_management_list.tsx b/src/plugins/unified_search/public/saved_query_management/saved_query_management_list.tsx index 127aa804f77f8..8f9a159c466c0 100644 --- a/src/plugins/unified_search/public/saved_query_management/saved_query_management_list.tsx +++ b/src/plugins/unified_search/public/saved_query_management/saved_query_management_list.tsx @@ -29,6 +29,7 @@ import { sortBy } from 'lodash'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { IDataPluginServices, SavedQuery, SavedQueryService } from '@kbn/data-plugin/public'; import type { SavedQueryAttributes } from '@kbn/data-plugin/common'; +import './saved_query_management_list.scss'; export interface SavedQueryManagementListProps { showSaveQuery?: boolean; diff --git a/src/plugins/unified_search/public/search_bar/index.tsx b/src/plugins/unified_search/public/search_bar/index.tsx index 40421a50a5fe2..f8c9de7ec7d87 100644 --- a/src/plugins/unified_search/public/search_bar/index.tsx +++ b/src/plugins/unified_search/public/search_bar/index.tsx @@ -10,7 +10,6 @@ import React from 'react'; import { injectI18n } from '@kbn/i18n-react'; import { withKibana } from '@kbn/kibana-react-plugin/public'; import type { SearchBarProps } from './search_bar'; -import '../index.scss'; const Fallback = () =>
; diff --git a/src/plugins/unified_search/public/typeahead/_index.scss b/src/plugins/unified_search/public/typeahead/_index.scss deleted file mode 100644 index c0ba5f05f589c..0000000000000 --- a/src/plugins/unified_search/public/typeahead/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import 'suggestion'; From b191f141f34be719cb8e5affc8899b883531f6e7 Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Thu, 12 May 2022 04:49:52 -0500 Subject: [PATCH 2/9] =?UTF-8?q?Upgrade=20`axios`=20dependency=20(`0.21.1`?= =?UTF-8?q?=20=E2=86=92=20`0.27.2`).=20(#111655)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Aleh Zasypkin --- package.json | 3 +- packages/kbn-pm/dist/index.js | 3143 ++++++++++++++--- .../lib/integration_tests/download.test.ts | 4 +- .../builtin_action_types/lib/axios_utils.ts | 3 + .../servicenow/utils.test.ts | 7 +- .../builtin_action_types/servicenow/utils.ts | 6 +- .../server/builtin_action_types/webhook.ts | 2 +- .../helpers/call_kibana.ts | 2 +- .../plugins/canvas/common/lib/fetch.test.ts | 17 +- .../plugins/fleet/server/telemetry/sender.ts | 2 +- .../osquery/server/lib/telemetry/sender.ts | 4 +- .../scripts/endpoint/blocklists/index.ts | 2 +- .../scripts/endpoint/event_filters/index.ts | 2 +- .../host_isolation_exceptions/index.ts | 2 +- .../server/lib/telemetry/sender.ts | 4 +- .../synthetics/server/lib/telemetry/sender.ts | 4 +- x-pack/test/performance/services/auth.ts | 2 +- .../common/services/ui_capabilities.ts | 4 +- yarn.lock | 37 +- 19 files changed, 2761 insertions(+), 489 deletions(-) diff --git a/package.json b/package.json index f04cc1acb25c1..01bb0cf56bd7b 100644 --- a/package.json +++ b/package.json @@ -223,7 +223,7 @@ "abort-controller": "^3.0.0", "antlr4ts": "^0.5.0-alpha.3", "archiver": "^5.2.0", - "axios": "^0.21.1", + "axios": "^0.27.2", "base64-js": "^1.3.1", "bitmap-sdf": "^1.0.3", "brace": "0.11.1", @@ -951,7 +951,6 @@ "url-loader": "^2.2.0", "val-loader": "^1.1.1", "vinyl-fs": "^3.0.3", - "wait-on": "^5.2.1", "watchpack": "^1.6.0", "webpack": "^4.41.5", "webpack-bundle-analyzer": "^4.5.0", diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index 1043c357da8d1..5045611c2ac2c 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -15289,6 +15289,447 @@ const arrify = value => { module.exports = arrify; +/***/ }), + +/***/ "../../node_modules/asynckit/index.js": +/***/ (function(module, exports, __webpack_require__) { + +module.exports = +{ + parallel : __webpack_require__("../../node_modules/asynckit/parallel.js"), + serial : __webpack_require__("../../node_modules/asynckit/serial.js"), + serialOrdered : __webpack_require__("../../node_modules/asynckit/serialOrdered.js") +}; + + +/***/ }), + +/***/ "../../node_modules/asynckit/lib/abort.js": +/***/ (function(module, exports) { + +// API +module.exports = abort; + +/** + * Aborts leftover active jobs + * + * @param {object} state - current state object + */ +function abort(state) +{ + Object.keys(state.jobs).forEach(clean.bind(state)); + + // reset leftover jobs + state.jobs = {}; +} + +/** + * Cleans up leftover job by invoking abort function for the provided job id + * + * @this state + * @param {string|number} key - job id to abort + */ +function clean(key) +{ + if (typeof this.jobs[key] == 'function') + { + this.jobs[key](); + } +} + + +/***/ }), + +/***/ "../../node_modules/asynckit/lib/async.js": +/***/ (function(module, exports, __webpack_require__) { + +var defer = __webpack_require__("../../node_modules/asynckit/lib/defer.js"); + +// API +module.exports = async; + +/** + * Runs provided callback asynchronously + * even if callback itself is not + * + * @param {function} callback - callback to invoke + * @returns {function} - augmented callback + */ +function async(callback) +{ + var isAsync = false; + + // check if async happened + defer(function() { isAsync = true; }); + + return function async_callback(err, result) + { + if (isAsync) + { + callback(err, result); + } + else + { + defer(function nextTick_callback() + { + callback(err, result); + }); + } + }; +} + + +/***/ }), + +/***/ "../../node_modules/asynckit/lib/defer.js": +/***/ (function(module, exports) { + +module.exports = defer; + +/** + * Runs provided function on next iteration of the event loop + * + * @param {function} fn - function to run + */ +function defer(fn) +{ + var nextTick = typeof setImmediate == 'function' + ? setImmediate + : ( + typeof process == 'object' && typeof process.nextTick == 'function' + ? process.nextTick + : null + ); + + if (nextTick) + { + nextTick(fn); + } + else + { + setTimeout(fn, 0); + } +} + + +/***/ }), + +/***/ "../../node_modules/asynckit/lib/iterate.js": +/***/ (function(module, exports, __webpack_require__) { + +var async = __webpack_require__("../../node_modules/asynckit/lib/async.js") + , abort = __webpack_require__("../../node_modules/asynckit/lib/abort.js") + ; + +// API +module.exports = iterate; + +/** + * Iterates over each job object + * + * @param {array|object} list - array or object (named list) to iterate over + * @param {function} iterator - iterator to run + * @param {object} state - current job status + * @param {function} callback - invoked when all elements processed + */ +function iterate(list, iterator, state, callback) +{ + // store current index + var key = state['keyedList'] ? state['keyedList'][state.index] : state.index; + + state.jobs[key] = runJob(iterator, key, list[key], function(error, output) + { + // don't repeat yourself + // skip secondary callbacks + if (!(key in state.jobs)) + { + return; + } + + // clean up jobs + delete state.jobs[key]; + + if (error) + { + // don't process rest of the results + // stop still active jobs + // and reset the list + abort(state); + } + else + { + state.results[key] = output; + } + + // return salvaged results + callback(error, state.results); + }); +} + +/** + * Runs iterator over provided job element + * + * @param {function} iterator - iterator to invoke + * @param {string|number} key - key/index of the element in the list of jobs + * @param {mixed} item - job description + * @param {function} callback - invoked after iterator is done with the job + * @returns {function|mixed} - job abort function or something else + */ +function runJob(iterator, key, item, callback) +{ + var aborter; + + // allow shortcut if iterator expects only two arguments + if (iterator.length == 2) + { + aborter = iterator(item, async(callback)); + } + // otherwise go with full three arguments + else + { + aborter = iterator(item, key, async(callback)); + } + + return aborter; +} + + +/***/ }), + +/***/ "../../node_modules/asynckit/lib/state.js": +/***/ (function(module, exports) { + +// API +module.exports = state; + +/** + * Creates initial state object + * for iteration over list + * + * @param {array|object} list - list to iterate over + * @param {function|null} sortMethod - function to use for keys sort, + * or `null` to keep them as is + * @returns {object} - initial state object + */ +function state(list, sortMethod) +{ + var isNamedList = !Array.isArray(list) + , initState = + { + index : 0, + keyedList: isNamedList || sortMethod ? Object.keys(list) : null, + jobs : {}, + results : isNamedList ? {} : [], + size : isNamedList ? Object.keys(list).length : list.length + } + ; + + if (sortMethod) + { + // sort array keys based on it's values + // sort object's keys just on own merit + initState.keyedList.sort(isNamedList ? sortMethod : function(a, b) + { + return sortMethod(list[a], list[b]); + }); + } + + return initState; +} + + +/***/ }), + +/***/ "../../node_modules/asynckit/lib/terminator.js": +/***/ (function(module, exports, __webpack_require__) { + +var abort = __webpack_require__("../../node_modules/asynckit/lib/abort.js") + , async = __webpack_require__("../../node_modules/asynckit/lib/async.js") + ; + +// API +module.exports = terminator; + +/** + * Terminates jobs in the attached state context + * + * @this AsyncKitState# + * @param {function} callback - final callback to invoke after termination + */ +function terminator(callback) +{ + if (!Object.keys(this.jobs).length) + { + return; + } + + // fast forward iteration index + this.index = this.size; + + // abort jobs + abort(this); + + // send back results we have so far + async(callback)(null, this.results); +} + + +/***/ }), + +/***/ "../../node_modules/asynckit/parallel.js": +/***/ (function(module, exports, __webpack_require__) { + +var iterate = __webpack_require__("../../node_modules/asynckit/lib/iterate.js") + , initState = __webpack_require__("../../node_modules/asynckit/lib/state.js") + , terminator = __webpack_require__("../../node_modules/asynckit/lib/terminator.js") + ; + +// Public API +module.exports = parallel; + +/** + * Runs iterator over provided array elements in parallel + * + * @param {array|object} list - array or object (named list) to iterate over + * @param {function} iterator - iterator to run + * @param {function} callback - invoked when all elements processed + * @returns {function} - jobs terminator + */ +function parallel(list, iterator, callback) +{ + var state = initState(list); + + while (state.index < (state['keyedList'] || list).length) + { + iterate(list, iterator, state, function(error, result) + { + if (error) + { + callback(error, result); + return; + } + + // looks like it's the last one + if (Object.keys(state.jobs).length === 0) + { + callback(null, state.results); + return; + } + }); + + state.index++; + } + + return terminator.bind(state, callback); +} + + +/***/ }), + +/***/ "../../node_modules/asynckit/serial.js": +/***/ (function(module, exports, __webpack_require__) { + +var serialOrdered = __webpack_require__("../../node_modules/asynckit/serialOrdered.js"); + +// Public API +module.exports = serial; + +/** + * Runs iterator over provided array elements in series + * + * @param {array|object} list - array or object (named list) to iterate over + * @param {function} iterator - iterator to run + * @param {function} callback - invoked when all elements processed + * @returns {function} - jobs terminator + */ +function serial(list, iterator, callback) +{ + return serialOrdered(list, iterator, null, callback); +} + + +/***/ }), + +/***/ "../../node_modules/asynckit/serialOrdered.js": +/***/ (function(module, exports, __webpack_require__) { + +var iterate = __webpack_require__("../../node_modules/asynckit/lib/iterate.js") + , initState = __webpack_require__("../../node_modules/asynckit/lib/state.js") + , terminator = __webpack_require__("../../node_modules/asynckit/lib/terminator.js") + ; + +// Public API +module.exports = serialOrdered; +// sorting helpers +module.exports.ascending = ascending; +module.exports.descending = descending; + +/** + * Runs iterator over provided sorted array elements in series + * + * @param {array|object} list - array or object (named list) to iterate over + * @param {function} iterator - iterator to run + * @param {function} sortMethod - custom sort function + * @param {function} callback - invoked when all elements processed + * @returns {function} - jobs terminator + */ +function serialOrdered(list, iterator, sortMethod, callback) +{ + var state = initState(list, sortMethod); + + iterate(list, iterator, state, function iteratorHandler(error, result) + { + if (error) + { + callback(error, result); + return; + } + + state.index++; + + // are we there yet? + if (state.index < (state['keyedList'] || list).length) + { + iterate(list, iterator, state, iteratorHandler); + return; + } + + // done here + callback(null, state.results); + }); + + return terminator.bind(state, callback); +} + +/* + * -- Sort methods + */ + +/** + * sort helper to sort array elements in ascending order + * + * @param {mixed} a - an item to compare + * @param {mixed} b - an item to compare + * @returns {number} - comparison result + */ +function ascending(a, b) +{ + return a < b ? -1 : a > b ? 1 : 0; +} + +/** + * sort helper to sort array elements in descending order + * + * @param {mixed} a - an item to compare + * @param {mixed} b - an item to compare + * @returns {number} - comparison result + */ +function descending(a, b) +{ + return -1 * ascending(a, b); +} + + /***/ }), /***/ "../../node_modules/axios/index.js": @@ -15314,12 +15755,15 @@ var httpFollow = __webpack_require__("../../node_modules/follow-redirects/index. var httpsFollow = __webpack_require__("../../node_modules/follow-redirects/index.js").https; var url = __webpack_require__("url"); var zlib = __webpack_require__("zlib"); -var pkg = __webpack_require__("../../node_modules/axios/package.json"); -var createError = __webpack_require__("../../node_modules/axios/lib/core/createError.js"); -var enhanceError = __webpack_require__("../../node_modules/axios/lib/core/enhanceError.js"); +var VERSION = __webpack_require__("../../node_modules/axios/lib/env/data.js").version; +var transitionalDefaults = __webpack_require__("../../node_modules/axios/lib/defaults/transitional.js"); +var AxiosError = __webpack_require__("../../node_modules/axios/lib/core/AxiosError.js"); +var CanceledError = __webpack_require__("../../node_modules/axios/lib/cancel/CanceledError.js"); var isHttps = /https:?/; +var supportedProtocols = [ 'http:', 'https:', 'file:' ]; + /** * * @param {http.ClientRequestArgs} options @@ -15348,23 +15792,51 @@ function setProxy(options, proxy, location) { /*eslint consistent-return:0*/ module.exports = function httpAdapter(config) { return new Promise(function dispatchHttpRequest(resolvePromise, rejectPromise) { + var onCanceled; + function done() { + if (config.cancelToken) { + config.cancelToken.unsubscribe(onCanceled); + } + + if (config.signal) { + config.signal.removeEventListener('abort', onCanceled); + } + } var resolve = function resolve(value) { + done(); resolvePromise(value); }; + var rejected = false; var reject = function reject(value) { + done(); + rejected = true; rejectPromise(value); }; var data = config.data; var headers = config.headers; + var headerNames = {}; + + Object.keys(headers).forEach(function storeLowerName(name) { + headerNames[name.toLowerCase()] = name; + }); // Set User-Agent (required by some servers) - // Only set header if it hasn't been set in config // See https://github.com/axios/axios/issues/69 - if (!headers['User-Agent'] && !headers['user-agent']) { - headers['User-Agent'] = 'axios/' + pkg.version; + if ('user-agent' in headerNames) { + // User-Agent is specified; handle case where no UA header is desired + if (!headers[headerNames['user-agent']]) { + delete headers[headerNames['user-agent']]; + } + // Otherwise, use specified value + } else { + // Only set header if it hasn't been set in config + headers['User-Agent'] = 'axios/' + VERSION; } - if (data && !utils.isStream(data)) { + // support for https://www.npmjs.com/package/form-data api + if (utils.isFormData(data) && utils.isFunction(data.getHeaders)) { + Object.assign(headers, data.getHeaders()); + } else if (data && !utils.isStream(data)) { if (Buffer.isBuffer(data)) { // Nothing to do... } else if (utils.isArrayBuffer(data)) { @@ -15372,14 +15844,25 @@ module.exports = function httpAdapter(config) { } else if (utils.isString(data)) { data = Buffer.from(data, 'utf-8'); } else { - return reject(createError( + return reject(new AxiosError( 'Data after transformation must be a string, an ArrayBuffer, a Buffer, or a Stream', + AxiosError.ERR_BAD_REQUEST, + config + )); + } + + if (config.maxBodyLength > -1 && data.length > config.maxBodyLength) { + return reject(new AxiosError( + 'Request body larger than maxBodyLength limit', + AxiosError.ERR_BAD_REQUEST, config )); } // Add Content-Length header if data exists - headers['Content-Length'] = data.length; + if (!headerNames['content-length']) { + headers['Content-Length'] = data.length; + } } // HTTP basic authentication @@ -15393,7 +15876,15 @@ module.exports = function httpAdapter(config) { // Parse url var fullPath = buildFullPath(config.baseURL, config.url); var parsed = url.parse(fullPath); - var protocol = parsed.protocol || 'http:'; + var protocol = parsed.protocol || supportedProtocols[0]; + + if (supportedProtocols.indexOf(protocol) === -1) { + return reject(new AxiosError( + 'Unsupported protocol ' + protocol, + AxiosError.ERR_BAD_REQUEST, + config + )); + } if (!auth && parsed.auth) { var urlAuth = parsed.auth.split(':'); @@ -15402,13 +15893,23 @@ module.exports = function httpAdapter(config) { auth = urlUsername + ':' + urlPassword; } - if (auth) { - delete headers.Authorization; + if (auth && headerNames.authorization) { + delete headers[headerNames.authorization]; } var isHttpsRequest = isHttps.test(protocol); var agent = isHttpsRequest ? config.httpsAgent : config.httpAgent; + try { + buildURL(parsed.path, config.params, config.paramsSerializer).replace(/^\?/, ''); + } catch (err) { + var customErr = new Error(err.message); + customErr.config = config; + customErr.url = config.url; + customErr.exists = true; + reject(customErr); + } + var options = { path: buildURL(parsed.path, config.params, config.paramsSerializer).replace(/^\?/, ''), method: config.method.toUpperCase(), @@ -15488,6 +15989,9 @@ module.exports = function httpAdapter(config) { if (config.maxRedirects) { options.maxRedirects = config.maxRedirects; } + if (config.beforeRedirect) { + options.beforeRedirect = config.beforeRedirect; + } transport = isHttpsProxy ? httpsFollow : httpFollow; } @@ -15495,6 +15999,10 @@ module.exports = function httpAdapter(config) { options.maxBodyLength = config.maxBodyLength; } + if (config.insecureHTTPParser) { + options.insecureHTTPParser = config.insecureHTTPParser; + } + // Create the request var req = transport.request(options, function handleResponse(res) { if (req.aborted) return; @@ -15535,32 +16043,52 @@ module.exports = function httpAdapter(config) { settle(resolve, reject, response); } else { var responseBuffer = []; + var totalResponseBytes = 0; stream.on('data', function handleStreamData(chunk) { responseBuffer.push(chunk); + totalResponseBytes += chunk.length; // make sure the content length is not over the maxContentLength if specified - if (config.maxContentLength > -1 && Buffer.concat(responseBuffer).length > config.maxContentLength) { + if (config.maxContentLength > -1 && totalResponseBytes > config.maxContentLength) { + // stream.destoy() emit aborted event before calling reject() on Node.js v16 + rejected = true; stream.destroy(); - reject(createError('maxContentLength size of ' + config.maxContentLength + ' exceeded', - config, null, lastRequest)); + reject(new AxiosError('maxContentLength size of ' + config.maxContentLength + ' exceeded', + AxiosError.ERR_BAD_RESPONSE, config, lastRequest)); + } + }); + + stream.on('aborted', function handlerStreamAborted() { + if (rejected) { + return; } + stream.destroy(); + reject(new AxiosError( + 'maxContentLength size of ' + config.maxContentLength + ' exceeded', + AxiosError.ERR_BAD_RESPONSE, + config, + lastRequest + )); }); stream.on('error', function handleStreamError(err) { if (req.aborted) return; - reject(enhanceError(err, config, null, lastRequest)); + reject(AxiosError.from(err, null, config, lastRequest)); }); stream.on('end', function handleStreamEnd() { - var responseData = Buffer.concat(responseBuffer); - if (config.responseType !== 'arraybuffer') { - responseData = responseData.toString(config.responseEncoding); - if (!config.responseEncoding || config.responseEncoding === 'utf8') { - responseData = utils.stripBOM(responseData); + try { + var responseData = responseBuffer.length === 1 ? responseBuffer[0] : Buffer.concat(responseBuffer); + if (config.responseType !== 'arraybuffer') { + responseData = responseData.toString(config.responseEncoding); + if (!config.responseEncoding || config.responseEncoding === 'utf8') { + responseData = utils.stripBOM(responseData); + } } + response.data = responseData; + } catch (err) { + reject(AxiosError.from(err, null, config, response.request, response)); } - - response.data = responseData; settle(resolve, reject, response); }); } @@ -15568,37 +16096,71 @@ module.exports = function httpAdapter(config) { // Handle errors req.on('error', function handleRequestError(err) { - if (req.aborted && err.code !== 'ERR_FR_TOO_MANY_REDIRECTS') return; - reject(enhanceError(err, config, null, req)); + // @todo remove + // if (req.aborted && err.code !== AxiosError.ERR_FR_TOO_MANY_REDIRECTS) return; + reject(AxiosError.from(err, null, config, req)); + }); + + // set tcp keep alive to prevent drop connection by peer + req.on('socket', function handleRequestSocket(socket) { + // default interval of sending ack packet is 1 minute + socket.setKeepAlive(true, 1000 * 60); }); // Handle request timeout if (config.timeout) { + // This is forcing a int timeout to avoid problems if the `req` interface doesn't handle other types. + var timeout = parseInt(config.timeout, 10); + + if (isNaN(timeout)) { + reject(new AxiosError( + 'error trying to parse `config.timeout` to int', + AxiosError.ERR_BAD_OPTION_VALUE, + config, + req + )); + + return; + } + // Sometime, the response will be very slow, and does not respond, the connect event will be block by event loop system. // And timer callback will be fired, and abort() will be invoked before connection, then get "socket hang up" and code ECONNRESET. // At this time, if we have a large number of request, nodejs will hang up some socket on background. and the number will up and up. // And then these socket which be hang up will devoring CPU little by little. // ClientRequest.setTimeout will be fired on the specify milliseconds, and can make sure that abort() will be fired after connect. - req.setTimeout(config.timeout, function handleRequestTimeout() { + req.setTimeout(timeout, function handleRequestTimeout() { req.abort(); - reject(createError('timeout of ' + config.timeout + 'ms exceeded', config, 'ECONNABORTED', req)); + var transitional = config.transitional || transitionalDefaults; + reject(new AxiosError( + 'timeout of ' + timeout + 'ms exceeded', + transitional.clarifyTimeoutError ? AxiosError.ETIMEDOUT : AxiosError.ECONNABORTED, + config, + req + )); }); } - if (config.cancelToken) { + if (config.cancelToken || config.signal) { // Handle cancellation - config.cancelToken.promise.then(function onCanceled(cancel) { + // eslint-disable-next-line func-names + onCanceled = function(cancel) { if (req.aborted) return; req.abort(); - reject(cancel); - }); + reject(!cancel || (cancel && cancel.type) ? new CanceledError() : cancel); + }; + + config.cancelToken && config.cancelToken.subscribe(onCanceled); + if (config.signal) { + config.signal.aborted ? onCanceled() : config.signal.addEventListener('abort', onCanceled); + } } + // Send the request if (utils.isStream(data)) { data.on('error', function handleStreamError(err) { - reject(enhanceError(err, config, null, req)); + reject(AxiosError.from(err, config, null, req)); }).pipe(req); } else { req.end(data); @@ -15622,14 +16184,28 @@ var buildURL = __webpack_require__("../../node_modules/axios/lib/helpers/buildUR var buildFullPath = __webpack_require__("../../node_modules/axios/lib/core/buildFullPath.js"); var parseHeaders = __webpack_require__("../../node_modules/axios/lib/helpers/parseHeaders.js"); var isURLSameOrigin = __webpack_require__("../../node_modules/axios/lib/helpers/isURLSameOrigin.js"); -var createError = __webpack_require__("../../node_modules/axios/lib/core/createError.js"); +var transitionalDefaults = __webpack_require__("../../node_modules/axios/lib/defaults/transitional.js"); +var AxiosError = __webpack_require__("../../node_modules/axios/lib/core/AxiosError.js"); +var CanceledError = __webpack_require__("../../node_modules/axios/lib/cancel/CanceledError.js"); +var parseProtocol = __webpack_require__("../../node_modules/axios/lib/helpers/parseProtocol.js"); module.exports = function xhrAdapter(config) { return new Promise(function dispatchXhrRequest(resolve, reject) { var requestData = config.data; var requestHeaders = config.headers; + var responseType = config.responseType; + var onCanceled; + function done() { + if (config.cancelToken) { + config.cancelToken.unsubscribe(onCanceled); + } - if (utils.isFormData(requestData)) { + if (config.signal) { + config.signal.removeEventListener('abort', onCanceled); + } + } + + if (utils.isFormData(requestData) && utils.isStandardBrowserEnv()) { delete requestHeaders['Content-Type']; // Let the browser set it } @@ -15643,28 +16219,20 @@ module.exports = function xhrAdapter(config) { } var fullPath = buildFullPath(config.baseURL, config.url); + request.open(config.method.toUpperCase(), buildURL(fullPath, config.params, config.paramsSerializer), true); // Set the request timeout in MS request.timeout = config.timeout; - // Listen for ready state - request.onreadystatechange = function handleLoad() { - if (!request || request.readyState !== 4) { - return; - } - - // The request errored out and we didn't get a response, this will be - // handled by onerror instead - // With one exception: request that using file: protocol, most browsers - // will return status as 0 even though it's a successful request - if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) { + function onloadend() { + if (!request) { return; } - // Prepare the response var responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null; - var responseData = !config.responseType || config.responseType === 'text' ? request.responseText : request.response; + var responseData = !responseType || responseType === 'text' || responseType === 'json' ? + request.responseText : request.response; var response = { data: responseData, status: request.status, @@ -15674,11 +16242,40 @@ module.exports = function xhrAdapter(config) { request: request }; - settle(resolve, reject, response); + settle(function _resolve(value) { + resolve(value); + done(); + }, function _reject(err) { + reject(err); + done(); + }, response); // Clean up request request = null; - }; + } + + if ('onloadend' in request) { + // Use onloadend if available + request.onloadend = onloadend; + } else { + // Listen for ready state to emulate onloadend + request.onreadystatechange = function handleLoad() { + if (!request || request.readyState !== 4) { + return; + } + + // The request errored out and we didn't get a response, this will be + // handled by onerror instead + // With one exception: request that using file: protocol, most browsers + // will return status as 0 even though it's a successful request + if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) { + return; + } + // readystate handler is calling before onerror or ontimeout handlers, + // so we should call onloadend on the next 'tick' + setTimeout(onloadend); + }; + } // Handle browser request cancellation (as opposed to a manual cancellation) request.onabort = function handleAbort() { @@ -15686,7 +16283,7 @@ module.exports = function xhrAdapter(config) { return; } - reject(createError('Request aborted', config, 'ECONNABORTED', request)); + reject(new AxiosError('Request aborted', AxiosError.ECONNABORTED, config, request)); // Clean up request request = null; @@ -15696,7 +16293,7 @@ module.exports = function xhrAdapter(config) { request.onerror = function handleError() { // Real errors are hidden from us by the browser // onerror should only fire if it's a network error - reject(createError('Network Error', config, null, request)); + reject(new AxiosError('Network Error', AxiosError.ERR_NETWORK, config, request, request)); // Clean up request request = null; @@ -15704,11 +16301,15 @@ module.exports = function xhrAdapter(config) { // Handle timeout request.ontimeout = function handleTimeout() { - var timeoutErrorMessage = 'timeout of ' + config.timeout + 'ms exceeded'; + var timeoutErrorMessage = config.timeout ? 'timeout of ' + config.timeout + 'ms exceeded' : 'timeout exceeded'; + var transitional = config.transitional || transitionalDefaults; if (config.timeoutErrorMessage) { timeoutErrorMessage = config.timeoutErrorMessage; } - reject(createError(timeoutErrorMessage, config, 'ECONNABORTED', + reject(new AxiosError( + timeoutErrorMessage, + transitional.clarifyTimeoutError ? AxiosError.ETIMEDOUT : AxiosError.ECONNABORTED, + config, request)); // Clean up request @@ -15748,16 +16349,8 @@ module.exports = function xhrAdapter(config) { } // Add responseType to request if needed - if (config.responseType) { - try { - request.responseType = config.responseType; - } catch (e) { - // Expected DOMException thrown by browsers not compatible XMLHttpRequest Level 2. - // But, this can be suppressed for 'json' type as it can be parsed by default 'transformResponse' function. - if (config.responseType !== 'json') { - throw e; - } - } + if (responseType && responseType !== 'json') { + request.responseType = config.responseType; } // Handle progress if needed @@ -15770,24 +16363,36 @@ module.exports = function xhrAdapter(config) { request.upload.addEventListener('progress', config.onUploadProgress); } - if (config.cancelToken) { + if (config.cancelToken || config.signal) { // Handle cancellation - config.cancelToken.promise.then(function onCanceled(cancel) { + // eslint-disable-next-line func-names + onCanceled = function(cancel) { if (!request) { return; } - + reject(!cancel || (cancel && cancel.type) ? new CanceledError() : cancel); request.abort(); - reject(cancel); - // Clean up request request = null; - }); + }; + + config.cancelToken && config.cancelToken.subscribe(onCanceled); + if (config.signal) { + config.signal.aborted ? onCanceled() : config.signal.addEventListener('abort', onCanceled); + } } if (!requestData) { requestData = null; } + var protocol = parseProtocol(fullPath); + + if (protocol && [ 'http', 'https', 'file' ].indexOf(protocol) === -1) { + reject(new AxiosError('Unsupported protocol ' + protocol + ':', AxiosError.ERR_BAD_REQUEST, config)); + return; + } + + // Send the request request.send(requestData); }); @@ -15806,7 +16411,7 @@ var utils = __webpack_require__("../../node_modules/axios/lib/utils.js"); var bind = __webpack_require__("../../node_modules/axios/lib/helpers/bind.js"); var Axios = __webpack_require__("../../node_modules/axios/lib/core/Axios.js"); var mergeConfig = __webpack_require__("../../node_modules/axios/lib/core/mergeConfig.js"); -var defaults = __webpack_require__("../../node_modules/axios/lib/defaults.js"); +var defaults = __webpack_require__("../../node_modules/axios/lib/defaults/index.js"); /** * Create an instance of Axios @@ -15824,6 +16429,11 @@ function createInstance(defaultConfig) { // Copy context to instance utils.extend(instance, context); + // Factory for creating new instances + instance.create = function create(instanceConfig) { + return createInstance(mergeConfig(defaultConfig, instanceConfig)); + }; + return instance; } @@ -15833,15 +16443,18 @@ var axios = createInstance(defaults); // Expose Axios class to allow class inheritance axios.Axios = Axios; -// Factory for creating new instances -axios.create = function create(instanceConfig) { - return createInstance(mergeConfig(axios.defaults, instanceConfig)); -}; - // Expose Cancel & CancelToken -axios.Cancel = __webpack_require__("../../node_modules/axios/lib/cancel/Cancel.js"); +axios.CanceledError = __webpack_require__("../../node_modules/axios/lib/cancel/CanceledError.js"); axios.CancelToken = __webpack_require__("../../node_modules/axios/lib/cancel/CancelToken.js"); axios.isCancel = __webpack_require__("../../node_modules/axios/lib/cancel/isCancel.js"); +axios.VERSION = __webpack_require__("../../node_modules/axios/lib/env/data.js").version; +axios.toFormData = __webpack_require__("../../node_modules/axios/lib/helpers/toFormData.js"); + +// Expose AxiosError class +axios.AxiosError = __webpack_require__("../../node_modules/axios/lib/core/AxiosError.js"); + +// alias for CanceledError for backward compatibility +axios.Cancel = axios.CanceledError; // Expose all/spread axios.all = function all(promises) { @@ -15858,33 +16471,6 @@ module.exports = axios; module.exports.default = axios; -/***/ }), - -/***/ "../../node_modules/axios/lib/cancel/Cancel.js": -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/** - * A `Cancel` is an object that is thrown when an operation is canceled. - * - * @class - * @param {string=} message The message. - */ -function Cancel(message) { - this.message = message; -} - -Cancel.prototype.toString = function toString() { - return 'Cancel' + (this.message ? ': ' + this.message : ''); -}; - -Cancel.prototype.__CANCEL__ = true; - -module.exports = Cancel; - - /***/ }), /***/ "../../node_modules/axios/lib/cancel/CancelToken.js": @@ -15893,7 +16479,7 @@ module.exports = Cancel; "use strict"; -var Cancel = __webpack_require__("../../node_modules/axios/lib/cancel/Cancel.js"); +var CanceledError = __webpack_require__("../../node_modules/axios/lib/cancel/CanceledError.js"); /** * A `CancelToken` is an object that can be used to request cancellation of an operation. @@ -15907,24 +16493,55 @@ function CancelToken(executor) { } var resolvePromise; + this.promise = new Promise(function promiseExecutor(resolve) { resolvePromise = resolve; }); var token = this; + + // eslint-disable-next-line func-names + this.promise.then(function(cancel) { + if (!token._listeners) return; + + var i; + var l = token._listeners.length; + + for (i = 0; i < l; i++) { + token._listeners[i](cancel); + } + token._listeners = null; + }); + + // eslint-disable-next-line func-names + this.promise.then = function(onfulfilled) { + var _resolve; + // eslint-disable-next-line func-names + var promise = new Promise(function(resolve) { + token.subscribe(resolve); + _resolve = resolve; + }).then(onfulfilled); + + promise.cancel = function reject() { + token.unsubscribe(_resolve); + }; + + return promise; + }; + executor(function cancel(message) { if (token.reason) { // Cancellation has already been requested return; } - token.reason = new Cancel(message); + token.reason = new CanceledError(message); resolvePromise(token.reason); }); } /** - * Throws a `Cancel` if cancellation has been requested. + * Throws a `CanceledError` if cancellation has been requested. */ CancelToken.prototype.throwIfRequested = function throwIfRequested() { if (this.reason) { @@ -15932,6 +16549,37 @@ CancelToken.prototype.throwIfRequested = function throwIfRequested() { } }; +/** + * Subscribe to the cancel signal + */ + +CancelToken.prototype.subscribe = function subscribe(listener) { + if (this.reason) { + listener(this.reason); + return; + } + + if (this._listeners) { + this._listeners.push(listener); + } else { + this._listeners = [listener]; + } +}; + +/** + * Unsubscribe from the cancel signal + */ + +CancelToken.prototype.unsubscribe = function unsubscribe(listener) { + if (!this._listeners) { + return; + } + var index = this._listeners.indexOf(listener); + if (index !== -1) { + this._listeners.splice(index, 1); + } +}; + /** * Returns an object that contains a new `CancelToken` and a function that, when called, * cancels the `CancelToken`. @@ -15950,6 +16598,36 @@ CancelToken.source = function source() { module.exports = CancelToken; +/***/ }), + +/***/ "../../node_modules/axios/lib/cancel/CanceledError.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var AxiosError = __webpack_require__("../../node_modules/axios/lib/core/AxiosError.js"); +var utils = __webpack_require__("../../node_modules/axios/lib/utils.js"); + +/** + * A `CanceledError` is an object that is thrown when an operation is canceled. + * + * @class + * @param {string=} message The message. + */ +function CanceledError(message) { + // eslint-disable-next-line no-eq-null,eqeqeq + AxiosError.call(this, message == null ? 'canceled' : message, AxiosError.ERR_CANCELED); + this.name = 'CanceledError'; +} + +utils.inherits(CanceledError, AxiosError, { + __CANCEL__: true +}); + +module.exports = CanceledError; + + /***/ }), /***/ "../../node_modules/axios/lib/cancel/isCancel.js": @@ -15976,7 +16654,10 @@ var buildURL = __webpack_require__("../../node_modules/axios/lib/helpers/buildUR var InterceptorManager = __webpack_require__("../../node_modules/axios/lib/core/InterceptorManager.js"); var dispatchRequest = __webpack_require__("../../node_modules/axios/lib/core/dispatchRequest.js"); var mergeConfig = __webpack_require__("../../node_modules/axios/lib/core/mergeConfig.js"); +var buildFullPath = __webpack_require__("../../node_modules/axios/lib/core/buildFullPath.js"); +var validator = __webpack_require__("../../node_modules/axios/lib/helpers/validator.js"); +var validators = validator.validators; /** * Create a new instance of Axios * @@ -15995,14 +16676,14 @@ function Axios(instanceConfig) { * * @param {Object} config The config specific for this request (merged with this.defaults) */ -Axios.prototype.request = function request(config) { +Axios.prototype.request = function request(configOrUrl, config) { /*eslint no-param-reassign:0*/ // Allow for axios('example/url'[, config]) a la fetch API - if (typeof config === 'string') { - config = arguments[1] || {}; - config.url = arguments[0]; - } else { + if (typeof configOrUrl === 'string') { config = config || {}; + config.url = configOrUrl; + } else { + config = configOrUrl || {}; } config = mergeConfig(this.defaults, config); @@ -16016,54 +16697,210 @@ Axios.prototype.request = function request(config) { config.method = 'get'; } - // Hook up interceptors middleware - var chain = [dispatchRequest, undefined]; - var promise = Promise.resolve(config); + var transitional = config.transitional; + + if (transitional !== undefined) { + validator.assertOptions(transitional, { + silentJSONParsing: validators.transitional(validators.boolean), + forcedJSONParsing: validators.transitional(validators.boolean), + clarifyTimeoutError: validators.transitional(validators.boolean) + }, false); + } + + // filter out skipped interceptors + var requestInterceptorChain = []; + var synchronousRequestInterceptors = true; + this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) { + if (typeof interceptor.runWhen === 'function' && interceptor.runWhen(config) === false) { + return; + } + + synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous; + + requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected); + }); + + var responseInterceptorChain = []; + this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) { + responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected); + }); + + var promise; + + if (!synchronousRequestInterceptors) { + var chain = [dispatchRequest, undefined]; + + Array.prototype.unshift.apply(chain, requestInterceptorChain); + chain = chain.concat(responseInterceptorChain); + + promise = Promise.resolve(config); + while (chain.length) { + promise = promise.then(chain.shift(), chain.shift()); + } + + return promise; + } + + + var newConfig = config; + while (requestInterceptorChain.length) { + var onFulfilled = requestInterceptorChain.shift(); + var onRejected = requestInterceptorChain.shift(); + try { + newConfig = onFulfilled(newConfig); + } catch (error) { + onRejected(error); + break; + } + } + + try { + promise = dispatchRequest(newConfig); + } catch (error) { + return Promise.reject(error); + } + + while (responseInterceptorChain.length) { + promise = promise.then(responseInterceptorChain.shift(), responseInterceptorChain.shift()); + } + + return promise; +}; + +Axios.prototype.getUri = function getUri(config) { + config = mergeConfig(this.defaults, config); + var fullPath = buildFullPath(config.baseURL, config.url); + return buildURL(fullPath, config.params, config.paramsSerializer); +}; + +// Provide aliases for supported request methods +utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) { + /*eslint func-names:0*/ + Axios.prototype[method] = function(url, config) { + return this.request(mergeConfig(config || {}, { + method: method, + url: url, + data: (config || {}).data + })); + }; +}); + +utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) { + /*eslint func-names:0*/ + + function generateHTTPMethod(isForm) { + return function httpMethod(url, data, config) { + return this.request(mergeConfig(config || {}, { + method: method, + headers: isForm ? { + 'Content-Type': 'multipart/form-data' + } : {}, + url: url, + data: data + })); + }; + } + + Axios.prototype[method] = generateHTTPMethod(); + + Axios.prototype[method + 'Form'] = generateHTTPMethod(true); +}); + +module.exports = Axios; + + +/***/ }), + +/***/ "../../node_modules/axios/lib/core/AxiosError.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var utils = __webpack_require__("../../node_modules/axios/lib/utils.js"); + +/** + * Create an Error with the specified message, config, error code, request and response. + * + * @param {string} message The error message. + * @param {string} [code] The error code (for example, 'ECONNABORTED'). + * @param {Object} [config] The config. + * @param {Object} [request] The request. + * @param {Object} [response] The response. + * @returns {Error} The created error. + */ +function AxiosError(message, code, config, request, response) { + Error.call(this); + this.message = message; + this.name = 'AxiosError'; + code && (this.code = code); + config && (this.config = config); + request && (this.request = request); + response && (this.response = response); +} + +utils.inherits(AxiosError, Error, { + toJSON: function toJSON() { + return { + // Standard + message: this.message, + name: this.name, + // Microsoft + description: this.description, + number: this.number, + // Mozilla + fileName: this.fileName, + lineNumber: this.lineNumber, + columnNumber: this.columnNumber, + stack: this.stack, + // Axios + config: this.config, + code: this.code, + status: this.response && this.response.status ? this.response.status : null + }; + } +}); + +var prototype = AxiosError.prototype; +var descriptors = {}; - this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) { - chain.unshift(interceptor.fulfilled, interceptor.rejected); - }); +[ + 'ERR_BAD_OPTION_VALUE', + 'ERR_BAD_OPTION', + 'ECONNABORTED', + 'ETIMEDOUT', + 'ERR_NETWORK', + 'ERR_FR_TOO_MANY_REDIRECTS', + 'ERR_DEPRECATED', + 'ERR_BAD_RESPONSE', + 'ERR_BAD_REQUEST', + 'ERR_CANCELED' +// eslint-disable-next-line func-names +].forEach(function(code) { + descriptors[code] = {value: code}; +}); - this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) { - chain.push(interceptor.fulfilled, interceptor.rejected); - }); +Object.defineProperties(AxiosError, descriptors); +Object.defineProperty(prototype, 'isAxiosError', {value: true}); - while (chain.length) { - promise = promise.then(chain.shift(), chain.shift()); - } +// eslint-disable-next-line func-names +AxiosError.from = function(error, code, config, request, response, customProps) { + var axiosError = Object.create(prototype); - return promise; -}; + utils.toFlatObject(error, axiosError, function filter(obj) { + return obj !== Error.prototype; + }); -Axios.prototype.getUri = function getUri(config) { - config = mergeConfig(this.defaults, config); - return buildURL(config.url, config.params, config.paramsSerializer).replace(/^\?/, ''); -}; + AxiosError.call(axiosError, error.message, code, config, request, response); -// Provide aliases for supported request methods -utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) { - /*eslint func-names:0*/ - Axios.prototype[method] = function(url, config) { - return this.request(mergeConfig(config || {}, { - method: method, - url: url, - data: (config || {}).data - })); - }; -}); + axiosError.name = error.name; -utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) { - /*eslint func-names:0*/ - Axios.prototype[method] = function(url, data, config) { - return this.request(mergeConfig(config || {}, { - method: method, - url: url, - data: data - })); - }; -}); + customProps && Object.assign(axiosError, customProps); -module.exports = Axios; + return axiosError; +}; + +module.exports = AxiosError; /***/ }), @@ -16088,10 +16925,12 @@ function InterceptorManager() { * * @return {Number} An ID used to remove interceptor later */ -InterceptorManager.prototype.use = function use(fulfilled, rejected) { +InterceptorManager.prototype.use = function use(fulfilled, rejected, options) { this.handlers.push({ fulfilled: fulfilled, - rejected: rejected + rejected: rejected, + synchronous: options ? options.synchronous : false, + runWhen: options ? options.runWhen : null }); return this.handlers.length - 1; }; @@ -16154,32 +16993,6 @@ module.exports = function buildFullPath(baseURL, requestedURL) { }; -/***/ }), - -/***/ "../../node_modules/axios/lib/core/createError.js": -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var enhanceError = __webpack_require__("../../node_modules/axios/lib/core/enhanceError.js"); - -/** - * Create an Error with the specified message, config, error code, request and response. - * - * @param {string} message The error message. - * @param {Object} config The config. - * @param {string} [code] The error code (for example, 'ECONNABORTED'). - * @param {Object} [request] The request. - * @param {Object} [response] The response. - * @returns {Error} The created error. - */ -module.exports = function createError(message, config, code, request, response) { - var error = new Error(message); - return enhanceError(error, config, code, request, response); -}; - - /***/ }), /***/ "../../node_modules/axios/lib/core/dispatchRequest.js": @@ -16191,15 +17004,20 @@ module.exports = function createError(message, config, code, request, response) var utils = __webpack_require__("../../node_modules/axios/lib/utils.js"); var transformData = __webpack_require__("../../node_modules/axios/lib/core/transformData.js"); var isCancel = __webpack_require__("../../node_modules/axios/lib/cancel/isCancel.js"); -var defaults = __webpack_require__("../../node_modules/axios/lib/defaults.js"); +var defaults = __webpack_require__("../../node_modules/axios/lib/defaults/index.js"); +var CanceledError = __webpack_require__("../../node_modules/axios/lib/cancel/CanceledError.js"); /** - * Throws a `Cancel` if cancellation has been requested. + * Throws a `CanceledError` if cancellation has been requested. */ function throwIfCancellationRequested(config) { if (config.cancelToken) { config.cancelToken.throwIfRequested(); } + + if (config.signal && config.signal.aborted) { + throw new CanceledError(); + } } /** @@ -16215,7 +17033,8 @@ module.exports = function dispatchRequest(config) { config.headers = config.headers || {}; // Transform request data - config.data = transformData( + config.data = transformData.call( + config, config.data, config.headers, config.transformRequest @@ -16241,7 +17060,8 @@ module.exports = function dispatchRequest(config) { throwIfCancellationRequested(config); // Transform response data - response.data = transformData( + response.data = transformData.call( + config, response.data, response.headers, config.transformResponse @@ -16254,7 +17074,8 @@ module.exports = function dispatchRequest(config) { // Transform response data if (reason && reason.response) { - reason.response.data = transformData( + reason.response.data = transformData.call( + config, reason.response.data, reason.response.headers, config.transformResponse @@ -16267,56 +17088,6 @@ module.exports = function dispatchRequest(config) { }; -/***/ }), - -/***/ "../../node_modules/axios/lib/core/enhanceError.js": -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/** - * Update an Error with the specified config, error code, and response. - * - * @param {Error} error The error to update. - * @param {Object} config The config. - * @param {string} [code] The error code (for example, 'ECONNABORTED'). - * @param {Object} [request] The request. - * @param {Object} [response] The response. - * @returns {Error} The error. - */ -module.exports = function enhanceError(error, config, code, request, response) { - error.config = config; - if (code) { - error.code = code; - } - - error.request = request; - error.response = response; - error.isAxiosError = true; - - error.toJSON = function toJSON() { - return { - // Standard - message: this.message, - name: this.name, - // Microsoft - description: this.description, - number: this.number, - // Mozilla - fileName: this.fileName, - lineNumber: this.lineNumber, - columnNumber: this.columnNumber, - stack: this.stack, - // Axios - config: this.config, - code: this.code - }; - }; - return error; -}; - - /***/ }), /***/ "../../node_modules/axios/lib/core/mergeConfig.js": @@ -16340,17 +17111,6 @@ module.exports = function mergeConfig(config1, config2) { config2 = config2 || {}; var config = {}; - var valueFromConfig2Keys = ['url', 'method', 'data']; - var mergeDeepPropertiesKeys = ['headers', 'auth', 'proxy', 'params']; - var defaultToConfig2Keys = [ - 'baseURL', 'transformRequest', 'transformResponse', 'paramsSerializer', - 'timeout', 'timeoutMessage', 'withCredentials', 'adapter', 'responseType', 'xsrfCookieName', - 'xsrfHeaderName', 'onUploadProgress', 'onDownloadProgress', 'decompress', - 'maxContentLength', 'maxBodyLength', 'maxRedirects', 'transport', 'httpAgent', - 'httpsAgent', 'cancelToken', 'socketPath', 'responseEncoding' - ]; - var directMergeKeys = ['validateStatus']; - function getMergedValue(target, source) { if (utils.isPlainObject(target) && utils.isPlainObject(source)) { return utils.merge(target, source); @@ -16362,51 +17122,75 @@ module.exports = function mergeConfig(config1, config2) { return source; } + // eslint-disable-next-line consistent-return function mergeDeepProperties(prop) { if (!utils.isUndefined(config2[prop])) { - config[prop] = getMergedValue(config1[prop], config2[prop]); + return getMergedValue(config1[prop], config2[prop]); } else if (!utils.isUndefined(config1[prop])) { - config[prop] = getMergedValue(undefined, config1[prop]); + return getMergedValue(undefined, config1[prop]); } } - utils.forEach(valueFromConfig2Keys, function valueFromConfig2(prop) { + // eslint-disable-next-line consistent-return + function valueFromConfig2(prop) { if (!utils.isUndefined(config2[prop])) { - config[prop] = getMergedValue(undefined, config2[prop]); + return getMergedValue(undefined, config2[prop]); } - }); - - utils.forEach(mergeDeepPropertiesKeys, mergeDeepProperties); + } - utils.forEach(defaultToConfig2Keys, function defaultToConfig2(prop) { + // eslint-disable-next-line consistent-return + function defaultToConfig2(prop) { if (!utils.isUndefined(config2[prop])) { - config[prop] = getMergedValue(undefined, config2[prop]); + return getMergedValue(undefined, config2[prop]); } else if (!utils.isUndefined(config1[prop])) { - config[prop] = getMergedValue(undefined, config1[prop]); + return getMergedValue(undefined, config1[prop]); } - }); + } - utils.forEach(directMergeKeys, function merge(prop) { + // eslint-disable-next-line consistent-return + function mergeDirectKeys(prop) { if (prop in config2) { - config[prop] = getMergedValue(config1[prop], config2[prop]); + return getMergedValue(config1[prop], config2[prop]); } else if (prop in config1) { - config[prop] = getMergedValue(undefined, config1[prop]); - } - }); - - var axiosKeys = valueFromConfig2Keys - .concat(mergeDeepPropertiesKeys) - .concat(defaultToConfig2Keys) - .concat(directMergeKeys); - - var otherKeys = Object - .keys(config1) - .concat(Object.keys(config2)) - .filter(function filterAxiosKeys(key) { - return axiosKeys.indexOf(key) === -1; - }); + return getMergedValue(undefined, config1[prop]); + } + } + + var mergeMap = { + 'url': valueFromConfig2, + 'method': valueFromConfig2, + 'data': valueFromConfig2, + 'baseURL': defaultToConfig2, + 'transformRequest': defaultToConfig2, + 'transformResponse': defaultToConfig2, + 'paramsSerializer': defaultToConfig2, + 'timeout': defaultToConfig2, + 'timeoutMessage': defaultToConfig2, + 'withCredentials': defaultToConfig2, + 'adapter': defaultToConfig2, + 'responseType': defaultToConfig2, + 'xsrfCookieName': defaultToConfig2, + 'xsrfHeaderName': defaultToConfig2, + 'onUploadProgress': defaultToConfig2, + 'onDownloadProgress': defaultToConfig2, + 'decompress': defaultToConfig2, + 'maxContentLength': defaultToConfig2, + 'maxBodyLength': defaultToConfig2, + 'beforeRedirect': defaultToConfig2, + 'transport': defaultToConfig2, + 'httpAgent': defaultToConfig2, + 'httpsAgent': defaultToConfig2, + 'cancelToken': defaultToConfig2, + 'socketPath': defaultToConfig2, + 'responseEncoding': defaultToConfig2, + 'validateStatus': mergeDirectKeys + }; - utils.forEach(otherKeys, mergeDeepProperties); + utils.forEach(Object.keys(config1).concat(Object.keys(config2)), function computeConfigValue(prop) { + var merge = mergeMap[prop] || mergeDeepProperties; + var configValue = merge(prop); + (utils.isUndefined(configValue) && merge !== mergeDirectKeys) || (config[prop] = configValue); + }); return config; }; @@ -16420,7 +17204,7 @@ module.exports = function mergeConfig(config1, config2) { "use strict"; -var createError = __webpack_require__("../../node_modules/axios/lib/core/createError.js"); +var AxiosError = __webpack_require__("../../node_modules/axios/lib/core/AxiosError.js"); /** * Resolve or reject a Promise based on response status. @@ -16434,10 +17218,10 @@ module.exports = function settle(resolve, reject, response) { if (!response.status || !validateStatus || validateStatus(response.status)) { resolve(response); } else { - reject(createError( + reject(new AxiosError( 'Request failed with status code ' + response.status, + [AxiosError.ERR_BAD_REQUEST, AxiosError.ERR_BAD_RESPONSE][Math.floor(response.status / 100) - 4], response.config, - null, response.request, response )); @@ -16454,6 +17238,7 @@ module.exports = function settle(resolve, reject, response) { var utils = __webpack_require__("../../node_modules/axios/lib/utils.js"); +var defaults = __webpack_require__("../../node_modules/axios/lib/defaults/index.js"); /** * Transform the data for a request or a response @@ -16464,9 +17249,10 @@ var utils = __webpack_require__("../../node_modules/axios/lib/utils.js"); * @returns {*} The resulting transformed data */ module.exports = function transformData(data, headers, fns) { + var context = this || defaults; /*eslint no-param-reassign:0*/ utils.forEach(fns, function transform(fn) { - data = fn(data, headers); + data = fn.call(context, data, headers); }); return data; @@ -16475,7 +17261,16 @@ module.exports = function transformData(data, headers, fns) { /***/ }), -/***/ "../../node_modules/axios/lib/defaults.js": +/***/ "../../node_modules/axios/lib/defaults/env/FormData.js": +/***/ (function(module, exports, __webpack_require__) { + +// eslint-disable-next-line strict +module.exports = __webpack_require__("../../node_modules/form-data/lib/form_data.js"); + + +/***/ }), + +/***/ "../../node_modules/axios/lib/defaults/index.js": /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -16483,6 +17278,9 @@ module.exports = function transformData(data, headers, fns) { var utils = __webpack_require__("../../node_modules/axios/lib/utils.js"); var normalizeHeaderName = __webpack_require__("../../node_modules/axios/lib/helpers/normalizeHeaderName.js"); +var AxiosError = __webpack_require__("../../node_modules/axios/lib/core/AxiosError.js"); +var transitionalDefaults = __webpack_require__("../../node_modules/axios/lib/defaults/transitional.js"); +var toFormData = __webpack_require__("../../node_modules/axios/lib/helpers/toFormData.js"); var DEFAULT_CONTENT_TYPE = { 'Content-Type': 'application/x-www-form-urlencoded' @@ -16506,12 +17304,31 @@ function getDefaultAdapter() { return adapter; } +function stringifySafely(rawValue, parser, encoder) { + if (utils.isString(rawValue)) { + try { + (parser || JSON.parse)(rawValue); + return utils.trim(rawValue); + } catch (e) { + if (e.name !== 'SyntaxError') { + throw e; + } + } + } + + return (encoder || JSON.stringify)(rawValue); +} + var defaults = { + + transitional: transitionalDefaults, + adapter: getDefaultAdapter(), transformRequest: [function transformRequest(data, headers) { normalizeHeaderName(headers, 'Accept'); normalizeHeaderName(headers, 'Content-Type'); + if (utils.isFormData(data) || utils.isArrayBuffer(data) || utils.isBuffer(data) || @@ -16528,20 +17345,42 @@ var defaults = { setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8'); return data.toString(); } - if (utils.isObject(data)) { - setContentTypeIfUnset(headers, 'application/json;charset=utf-8'); - return JSON.stringify(data); + + var isObjectPayload = utils.isObject(data); + var contentType = headers && headers['Content-Type']; + + var isFileList; + + if ((isFileList = utils.isFileList(data)) || (isObjectPayload && contentType === 'multipart/form-data')) { + var _FormData = this.env && this.env.FormData; + return toFormData(isFileList ? {'files[]': data} : data, _FormData && new _FormData()); + } else if (isObjectPayload || contentType === 'application/json') { + setContentTypeIfUnset(headers, 'application/json'); + return stringifySafely(data); } + return data; }], transformResponse: [function transformResponse(data) { - /*eslint no-param-reassign:0*/ - if (typeof data === 'string') { + var transitional = this.transitional || defaults.transitional; + var silentJSONParsing = transitional && transitional.silentJSONParsing; + var forcedJSONParsing = transitional && transitional.forcedJSONParsing; + var strictJSONParsing = !silentJSONParsing && this.responseType === 'json'; + + if (strictJSONParsing || (forcedJSONParsing && utils.isString(data) && data.length)) { try { - data = JSON.parse(data); - } catch (e) { /* Ignore */ } + return JSON.parse(data); + } catch (e) { + if (strictJSONParsing) { + if (e.name === 'SyntaxError') { + throw AxiosError.from(e, AxiosError.ERR_BAD_RESPONSE, this, null, this.response); + } + throw e; + } + } } + return data; }], @@ -16557,14 +17396,18 @@ var defaults = { maxContentLength: -1, maxBodyLength: -1, + env: { + FormData: __webpack_require__("../../node_modules/axios/lib/defaults/env/FormData.js") + }, + validateStatus: function validateStatus(status) { return status >= 200 && status < 300; - } -}; + }, -defaults.headers = { - common: { - 'Accept': 'application/json, text/plain, */*' + headers: { + common: { + 'Accept': 'application/json, text/plain, */*' + } } }; @@ -16579,6 +17422,30 @@ utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) { module.exports = defaults; +/***/ }), + +/***/ "../../node_modules/axios/lib/defaults/transitional.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +module.exports = { + silentJSONParsing: true, + forcedJSONParsing: true, + clarifyTimeoutError: false +}; + + +/***/ }), + +/***/ "../../node_modules/axios/lib/env/data.js": +/***/ (function(module, exports) { + +module.exports = { + "version": "0.27.2" +}; + /***/ }), /***/ "../../node_modules/axios/lib/helpers/bind.js": @@ -16777,7 +17644,7 @@ module.exports = function isAbsoluteURL(url) { // A URL is considered absolute if it begins with "://" or "//" (protocol-relative URL). // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed // by any combination of letters, digits, plus, period, or hyphen. - return /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url); + return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url); }; @@ -16789,6 +17656,8 @@ module.exports = function isAbsoluteURL(url) { "use strict"; +var utils = __webpack_require__("../../node_modules/axios/lib/utils.js"); + /** * Determines whether the payload is an error thrown by Axios * @@ -16796,7 +17665,7 @@ module.exports = function isAbsoluteURL(url) { * @returns {boolean} True if the payload is an error thrown by Axios, otherwise false */ module.exports = function isAxiosError(payload) { - return (typeof payload === 'object') && (payload.isAxiosError === true); + return utils.isObject(payload) && (payload.isAxiosError === true); }; @@ -16953,44 +17822,232 @@ module.exports = function parseHeaders(headers) { } }); - return parsed; -}; + return parsed; +}; + + +/***/ }), + +/***/ "../../node_modules/axios/lib/helpers/parseProtocol.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +module.exports = function parseProtocol(url) { + var match = /^([-+\w]{1,25})(:?\/\/|:)/.exec(url); + return match && match[1] || ''; +}; + + +/***/ }), + +/***/ "../../node_modules/axios/lib/helpers/spread.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +/** + * Syntactic sugar for invoking a function and expanding an array for arguments. + * + * Common use case would be to use `Function.prototype.apply`. + * + * ```js + * function f(x, y, z) {} + * var args = [1, 2, 3]; + * f.apply(null, args); + * ``` + * + * With `spread` this example can be re-written. + * + * ```js + * spread(function(x, y, z) {})([1, 2, 3]); + * ``` + * + * @param {Function} callback + * @returns {Function} + */ +module.exports = function spread(callback) { + return function wrap(arr) { + return callback.apply(null, arr); + }; +}; + + +/***/ }), + +/***/ "../../node_modules/axios/lib/helpers/toFormData.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var utils = __webpack_require__("../../node_modules/axios/lib/utils.js"); + +/** + * Convert a data object to FormData + * @param {Object} obj + * @param {?Object} [formData] + * @returns {Object} + **/ + +function toFormData(obj, formData) { + // eslint-disable-next-line no-param-reassign + formData = formData || new FormData(); + + var stack = []; + + function convertValue(value) { + if (value === null) return ''; + + if (utils.isDate(value)) { + return value.toISOString(); + } + + if (utils.isArrayBuffer(value) || utils.isTypedArray(value)) { + return typeof Blob === 'function' ? new Blob([value]) : Buffer.from(value); + } + + return value; + } + + function build(data, parentKey) { + if (utils.isPlainObject(data) || utils.isArray(data)) { + if (stack.indexOf(data) !== -1) { + throw Error('Circular reference detected in ' + parentKey); + } + + stack.push(data); + + utils.forEach(data, function each(value, key) { + if (utils.isUndefined(value)) return; + var fullKey = parentKey ? parentKey + '.' + key : key; + var arr; + + if (value && !parentKey && typeof value === 'object') { + if (utils.endsWith(key, '{}')) { + // eslint-disable-next-line no-param-reassign + value = JSON.stringify(value); + } else if (utils.endsWith(key, '[]') && (arr = utils.toArray(value))) { + // eslint-disable-next-line func-names + arr.forEach(function(el) { + !utils.isUndefined(el) && formData.append(fullKey, convertValue(el)); + }); + return; + } + } + + build(value, fullKey); + }); + + stack.pop(); + } else { + formData.append(parentKey, convertValue(data)); + } + } + + build(obj); + + return formData; +} + +module.exports = toFormData; /***/ }), -/***/ "../../node_modules/axios/lib/helpers/spread.js": +/***/ "../../node_modules/axios/lib/helpers/validator.js": /***/ (function(module, exports, __webpack_require__) { "use strict"; +var VERSION = __webpack_require__("../../node_modules/axios/lib/env/data.js").version; +var AxiosError = __webpack_require__("../../node_modules/axios/lib/core/AxiosError.js"); + +var validators = {}; + +// eslint-disable-next-line func-names +['object', 'boolean', 'number', 'function', 'string', 'symbol'].forEach(function(type, i) { + validators[type] = function validator(thing) { + return typeof thing === type || 'a' + (i < 1 ? 'n ' : ' ') + type; + }; +}); + +var deprecatedWarnings = {}; + /** - * Syntactic sugar for invoking a function and expanding an array for arguments. - * - * Common use case would be to use `Function.prototype.apply`. - * - * ```js - * function f(x, y, z) {} - * var args = [1, 2, 3]; - * f.apply(null, args); - * ``` - * - * With `spread` this example can be re-written. - * - * ```js - * spread(function(x, y, z) {})([1, 2, 3]); - * ``` - * - * @param {Function} callback - * @returns {Function} - */ -module.exports = function spread(callback) { - return function wrap(arr) { - return callback.apply(null, arr); + * Transitional option validator + * @param {function|boolean?} validator - set to false if the transitional option has been removed + * @param {string?} version - deprecated version / removed since version + * @param {string?} message - some message with additional info + * @returns {function} + */ +validators.transitional = function transitional(validator, version, message) { + function formatMessage(opt, desc) { + return '[Axios v' + VERSION + '] Transitional option \'' + opt + '\'' + desc + (message ? '. ' + message : ''); + } + + // eslint-disable-next-line func-names + return function(value, opt, opts) { + if (validator === false) { + throw new AxiosError( + formatMessage(opt, ' has been removed' + (version ? ' in ' + version : '')), + AxiosError.ERR_DEPRECATED + ); + } + + if (version && !deprecatedWarnings[opt]) { + deprecatedWarnings[opt] = true; + // eslint-disable-next-line no-console + console.warn( + formatMessage( + opt, + ' has been deprecated since v' + version + ' and will be removed in the near future' + ) + ); + } + + return validator ? validator(value, opt, opts) : true; }; }; +/** + * Assert object's properties type + * @param {object} options + * @param {object} schema + * @param {boolean?} allowUnknown + */ + +function assertOptions(options, schema, allowUnknown) { + if (typeof options !== 'object') { + throw new AxiosError('options must be an object', AxiosError.ERR_BAD_OPTION_VALUE); + } + var keys = Object.keys(options); + var i = keys.length; + while (i-- > 0) { + var opt = keys[i]; + var validator = schema[opt]; + if (validator) { + var value = options[opt]; + var result = value === undefined || validator(value, opt, options); + if (result !== true) { + throw new AxiosError('option ' + opt + ' must be ' + result, AxiosError.ERR_BAD_OPTION_VALUE); + } + continue; + } + if (allowUnknown !== true) { + throw new AxiosError('Unknown option ' + opt, AxiosError.ERR_BAD_OPTION); + } + } +} + +module.exports = { + assertOptions: assertOptions, + validators: validators +}; + /***/ }), @@ -17002,12 +18059,26 @@ module.exports = function spread(callback) { var bind = __webpack_require__("../../node_modules/axios/lib/helpers/bind.js"); -/*global toString:true*/ - // utils is a library of generic helper functions non-specific to axios var toString = Object.prototype.toString; +// eslint-disable-next-line func-names +var kindOf = (function(cache) { + // eslint-disable-next-line func-names + return function(thing) { + var str = toString.call(thing); + return cache[str] || (cache[str] = str.slice(8, -1).toLowerCase()); + }; +})(Object.create(null)); + +function kindOfTest(type) { + type = type.toLowerCase(); + return function isKindOf(thing) { + return kindOf(thing) === type; + }; +} + /** * Determine if a value is an Array * @@ -17015,7 +18086,7 @@ var toString = Object.prototype.toString; * @returns {boolean} True if value is an Array, otherwise false */ function isArray(val) { - return toString.call(val) === '[object Array]'; + return Array.isArray(val); } /** @@ -17042,22 +18113,12 @@ function isBuffer(val) { /** * Determine if a value is an ArrayBuffer * + * @function * @param {Object} val The value to test * @returns {boolean} True if value is an ArrayBuffer, otherwise false */ -function isArrayBuffer(val) { - return toString.call(val) === '[object ArrayBuffer]'; -} +var isArrayBuffer = kindOfTest('ArrayBuffer'); -/** - * Determine if a value is a FormData - * - * @param {Object} val The value to test - * @returns {boolean} True if value is an FormData, otherwise false - */ -function isFormData(val) { - return (typeof FormData !== 'undefined') && (val instanceof FormData); -} /** * Determine if a value is a view on an ArrayBuffer @@ -17070,7 +18131,7 @@ function isArrayBufferView(val) { if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) { result = ArrayBuffer.isView(val); } else { - result = (val) && (val.buffer) && (val.buffer instanceof ArrayBuffer); + result = (val) && (val.buffer) && (isArrayBuffer(val.buffer)); } return result; } @@ -17112,7 +18173,7 @@ function isObject(val) { * @return {boolean} True if value is a plain Object, otherwise false */ function isPlainObject(val) { - if (toString.call(val) !== '[object Object]') { + if (kindOf(val) !== 'object') { return false; } @@ -17123,32 +18184,38 @@ function isPlainObject(val) { /** * Determine if a value is a Date * + * @function * @param {Object} val The value to test * @returns {boolean} True if value is a Date, otherwise false */ -function isDate(val) { - return toString.call(val) === '[object Date]'; -} +var isDate = kindOfTest('Date'); /** * Determine if a value is a File * + * @function * @param {Object} val The value to test * @returns {boolean} True if value is a File, otherwise false */ -function isFile(val) { - return toString.call(val) === '[object File]'; -} +var isFile = kindOfTest('File'); /** * Determine if a value is a Blob * + * @function * @param {Object} val The value to test * @returns {boolean} True if value is a Blob, otherwise false */ -function isBlob(val) { - return toString.call(val) === '[object Blob]'; -} +var isBlob = kindOfTest('Blob'); + +/** + * Determine if a value is a FileList + * + * @function + * @param {Object} val The value to test + * @returns {boolean} True if value is a File, otherwise false + */ +var isFileList = kindOfTest('FileList'); /** * Determine if a value is a Function @@ -17171,14 +18238,27 @@ function isStream(val) { } /** - * Determine if a value is a URLSearchParams object + * Determine if a value is a FormData * + * @param {Object} thing The value to test + * @returns {boolean} True if value is an FormData, otherwise false + */ +function isFormData(thing) { + var pattern = '[object FormData]'; + return thing && ( + (typeof FormData === 'function' && thing instanceof FormData) || + toString.call(thing) === pattern || + (isFunction(thing.toString) && thing.toString() === pattern) + ); +} + +/** + * Determine if a value is a URLSearchParams object + * @function * @param {Object} val The value to test * @returns {boolean} True if value is a URLSearchParams object, otherwise false */ -function isURLSearchParams(val) { - return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams; -} +var isURLSearchParams = kindOfTest('URLSearchParams'); /** * Trim excess whitespace off the beginning and end of a string @@ -17187,7 +18267,7 @@ function isURLSearchParams(val) { * @returns {String} The String freed of excess whitespace */ function trim(str) { - return str.replace(/^\s*/, '').replace(/\s*$/, ''); + return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, ''); } /** @@ -17325,6 +18405,94 @@ function stripBOM(content) { return content; } +/** + * Inherit the prototype methods from one constructor into another + * @param {function} constructor + * @param {function} superConstructor + * @param {object} [props] + * @param {object} [descriptors] + */ + +function inherits(constructor, superConstructor, props, descriptors) { + constructor.prototype = Object.create(superConstructor.prototype, descriptors); + constructor.prototype.constructor = constructor; + props && Object.assign(constructor.prototype, props); +} + +/** + * Resolve object with deep prototype chain to a flat object + * @param {Object} sourceObj source object + * @param {Object} [destObj] + * @param {Function} [filter] + * @returns {Object} + */ + +function toFlatObject(sourceObj, destObj, filter) { + var props; + var i; + var prop; + var merged = {}; + + destObj = destObj || {}; + + do { + props = Object.getOwnPropertyNames(sourceObj); + i = props.length; + while (i-- > 0) { + prop = props[i]; + if (!merged[prop]) { + destObj[prop] = sourceObj[prop]; + merged[prop] = true; + } + } + sourceObj = Object.getPrototypeOf(sourceObj); + } while (sourceObj && (!filter || filter(sourceObj, destObj)) && sourceObj !== Object.prototype); + + return destObj; +} + +/* + * determines whether a string ends with the characters of a specified string + * @param {String} str + * @param {String} searchString + * @param {Number} [position= 0] + * @returns {boolean} + */ +function endsWith(str, searchString, position) { + str = String(str); + if (position === undefined || position > str.length) { + position = str.length; + } + position -= searchString.length; + var lastIndex = str.indexOf(searchString, position); + return lastIndex !== -1 && lastIndex === position; +} + + +/** + * Returns new array from array like object + * @param {*} [thing] + * @returns {Array} + */ +function toArray(thing) { + if (!thing) return null; + var i = thing.length; + if (isUndefined(i)) return null; + var arr = new Array(i); + while (i-- > 0) { + arr[i] = thing[i]; + } + return arr; +} + +// eslint-disable-next-line func-names +var isTypedArray = (function(TypedArray) { + // eslint-disable-next-line func-names + return function(thing) { + return TypedArray && thing instanceof TypedArray; + }; +})(typeof Uint8Array !== 'undefined' && Object.getPrototypeOf(Uint8Array)); + module.exports = { isArray: isArray, isArrayBuffer: isArrayBuffer, @@ -17347,17 +18515,18 @@ module.exports = { merge: merge, extend: extend, trim: trim, - stripBOM: stripBOM + stripBOM: stripBOM, + inherits: inherits, + toFlatObject: toFlatObject, + kindOf: kindOf, + kindOfTest: kindOfTest, + endsWith: endsWith, + toArray: toArray, + isTypedArray: isTypedArray, + isFileList: isFileList }; -/***/ }), - -/***/ "../../node_modules/axios/package.json": -/***/ (function(module) { - -module.exports = JSON.parse("{\"name\":\"axios\",\"version\":\"0.21.1\",\"description\":\"Promise based HTTP client for the browser and node.js\",\"main\":\"index.js\",\"scripts\":{\"test\":\"grunt test && bundlesize\",\"start\":\"node ./sandbox/server.js\",\"build\":\"NODE_ENV=production grunt build\",\"preversion\":\"npm test\",\"version\":\"npm run build && grunt version && git add -A dist && git add CHANGELOG.md bower.json package.json\",\"postversion\":\"git push && git push --tags\",\"examples\":\"node ./examples/server.js\",\"coveralls\":\"cat coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js\",\"fix\":\"eslint --fix lib/**/*.js\"},\"repository\":{\"type\":\"git\",\"url\":\"https://github.com/axios/axios.git\"},\"keywords\":[\"xhr\",\"http\",\"ajax\",\"promise\",\"node\"],\"author\":\"Matt Zabriskie\",\"license\":\"MIT\",\"bugs\":{\"url\":\"https://github.com/axios/axios/issues\"},\"homepage\":\"https://github.com/axios/axios\",\"devDependencies\":{\"bundlesize\":\"^0.17.0\",\"coveralls\":\"^3.0.0\",\"es6-promise\":\"^4.2.4\",\"grunt\":\"^1.0.2\",\"grunt-banner\":\"^0.6.0\",\"grunt-cli\":\"^1.2.0\",\"grunt-contrib-clean\":\"^1.1.0\",\"grunt-contrib-watch\":\"^1.0.0\",\"grunt-eslint\":\"^20.1.0\",\"grunt-karma\":\"^2.0.0\",\"grunt-mocha-test\":\"^0.13.3\",\"grunt-ts\":\"^6.0.0-beta.19\",\"grunt-webpack\":\"^1.0.18\",\"istanbul-instrumenter-loader\":\"^1.0.0\",\"jasmine-core\":\"^2.4.1\",\"karma\":\"^1.3.0\",\"karma-chrome-launcher\":\"^2.2.0\",\"karma-coverage\":\"^1.1.1\",\"karma-firefox-launcher\":\"^1.1.0\",\"karma-jasmine\":\"^1.1.1\",\"karma-jasmine-ajax\":\"^0.1.13\",\"karma-opera-launcher\":\"^1.0.0\",\"karma-safari-launcher\":\"^1.0.0\",\"karma-sauce-launcher\":\"^1.2.0\",\"karma-sinon\":\"^1.0.5\",\"karma-sourcemap-loader\":\"^0.3.7\",\"karma-webpack\":\"^1.7.0\",\"load-grunt-tasks\":\"^3.5.2\",\"minimist\":\"^1.2.0\",\"mocha\":\"^5.2.0\",\"sinon\":\"^4.5.0\",\"typescript\":\"^2.8.1\",\"url-search-params\":\"^0.10.0\",\"webpack\":\"^1.13.1\",\"webpack-dev-server\":\"^1.14.1\"},\"browser\":{\"./lib/adapters/http.js\":\"./lib/adapters/xhr.js\"},\"jsdelivr\":\"dist/axios.min.js\",\"unpkg\":\"dist/axios.min.js\",\"typings\":\"./index.d.ts\",\"dependencies\":{\"follow-redirects\":\"^1.10.0\"},\"bundlesize\":[{\"path\":\"./dist/axios.min.js\",\"threshold\":\"5kB\"}]}"); - /***/ }), /***/ "../../node_modules/balanced-match/index.js": @@ -20982,6 +22151,221 @@ module.exports = { }; +/***/ }), + +/***/ "../../node_modules/combined-stream/lib/combined_stream.js": +/***/ (function(module, exports, __webpack_require__) { + +var util = __webpack_require__("util"); +var Stream = __webpack_require__("stream").Stream; +var DelayedStream = __webpack_require__("../../node_modules/delayed-stream/lib/delayed_stream.js"); + +module.exports = CombinedStream; +function CombinedStream() { + this.writable = false; + this.readable = true; + this.dataSize = 0; + this.maxDataSize = 2 * 1024 * 1024; + this.pauseStreams = true; + + this._released = false; + this._streams = []; + this._currentStream = null; + this._insideLoop = false; + this._pendingNext = false; +} +util.inherits(CombinedStream, Stream); + +CombinedStream.create = function(options) { + var combinedStream = new this(); + + options = options || {}; + for (var option in options) { + combinedStream[option] = options[option]; + } + + return combinedStream; +}; + +CombinedStream.isStreamLike = function(stream) { + return (typeof stream !== 'function') + && (typeof stream !== 'string') + && (typeof stream !== 'boolean') + && (typeof stream !== 'number') + && (!Buffer.isBuffer(stream)); +}; + +CombinedStream.prototype.append = function(stream) { + var isStreamLike = CombinedStream.isStreamLike(stream); + + if (isStreamLike) { + if (!(stream instanceof DelayedStream)) { + var newStream = DelayedStream.create(stream, { + maxDataSize: Infinity, + pauseStream: this.pauseStreams, + }); + stream.on('data', this._checkDataSize.bind(this)); + stream = newStream; + } + + this._handleErrors(stream); + + if (this.pauseStreams) { + stream.pause(); + } + } + + this._streams.push(stream); + return this; +}; + +CombinedStream.prototype.pipe = function(dest, options) { + Stream.prototype.pipe.call(this, dest, options); + this.resume(); + return dest; +}; + +CombinedStream.prototype._getNext = function() { + this._currentStream = null; + + if (this._insideLoop) { + this._pendingNext = true; + return; // defer call + } + + this._insideLoop = true; + try { + do { + this._pendingNext = false; + this._realGetNext(); + } while (this._pendingNext); + } finally { + this._insideLoop = false; + } +}; + +CombinedStream.prototype._realGetNext = function() { + var stream = this._streams.shift(); + + + if (typeof stream == 'undefined') { + this.end(); + return; + } + + if (typeof stream !== 'function') { + this._pipeNext(stream); + return; + } + + var getStream = stream; + getStream(function(stream) { + var isStreamLike = CombinedStream.isStreamLike(stream); + if (isStreamLike) { + stream.on('data', this._checkDataSize.bind(this)); + this._handleErrors(stream); + } + + this._pipeNext(stream); + }.bind(this)); +}; + +CombinedStream.prototype._pipeNext = function(stream) { + this._currentStream = stream; + + var isStreamLike = CombinedStream.isStreamLike(stream); + if (isStreamLike) { + stream.on('end', this._getNext.bind(this)); + stream.pipe(this, {end: false}); + return; + } + + var value = stream; + this.write(value); + this._getNext(); +}; + +CombinedStream.prototype._handleErrors = function(stream) { + var self = this; + stream.on('error', function(err) { + self._emitError(err); + }); +}; + +CombinedStream.prototype.write = function(data) { + this.emit('data', data); +}; + +CombinedStream.prototype.pause = function() { + if (!this.pauseStreams) { + return; + } + + if(this.pauseStreams && this._currentStream && typeof(this._currentStream.pause) == 'function') this._currentStream.pause(); + this.emit('pause'); +}; + +CombinedStream.prototype.resume = function() { + if (!this._released) { + this._released = true; + this.writable = true; + this._getNext(); + } + + if(this.pauseStreams && this._currentStream && typeof(this._currentStream.resume) == 'function') this._currentStream.resume(); + this.emit('resume'); +}; + +CombinedStream.prototype.end = function() { + this._reset(); + this.emit('end'); +}; + +CombinedStream.prototype.destroy = function() { + this._reset(); + this.emit('close'); +}; + +CombinedStream.prototype._reset = function() { + this.writable = false; + this._streams = []; + this._currentStream = null; +}; + +CombinedStream.prototype._checkDataSize = function() { + this._updateDataSize(); + if (this.dataSize <= this.maxDataSize) { + return; + } + + var message = + 'DelayedStream#maxDataSize of ' + this.maxDataSize + ' bytes exceeded.'; + this._emitError(new Error(message)); +}; + +CombinedStream.prototype._updateDataSize = function() { + this.dataSize = 0; + + var self = this; + this._streams.forEach(function(stream) { + if (!stream.dataSize) { + return; + } + + self.dataSize += stream.dataSize; + }); + + if (this._currentStream && this._currentStream.dataSize) { + this.dataSize += this._currentStream.dataSize; + } +}; + +CombinedStream.prototype._emitError = function(err) { + this._reset(); + this.emit('error', err); +}; + + /***/ }), /***/ "../../node_modules/concat-map/index.js": @@ -24633,14 +26017,128 @@ module.exports = async ( })(); }; - for (let i = 0; i < concurrency; i++) { - next(); + for (let i = 0; i < concurrency; i++) { + next(); + + if (isIterableDone) { + break; + } + } + }); +}; + + +/***/ }), + +/***/ "../../node_modules/delayed-stream/lib/delayed_stream.js": +/***/ (function(module, exports, __webpack_require__) { + +var Stream = __webpack_require__("stream").Stream; +var util = __webpack_require__("util"); + +module.exports = DelayedStream; +function DelayedStream() { + this.source = null; + this.dataSize = 0; + this.maxDataSize = 1024 * 1024; + this.pauseStream = true; + + this._maxDataSizeExceeded = false; + this._released = false; + this._bufferedEvents = []; +} +util.inherits(DelayedStream, Stream); + +DelayedStream.create = function(source, options) { + var delayedStream = new this(); + + options = options || {}; + for (var option in options) { + delayedStream[option] = options[option]; + } + + delayedStream.source = source; + + var realEmit = source.emit; + source.emit = function() { + delayedStream._handleEmit(arguments); + return realEmit.apply(source, arguments); + }; + + source.on('error', function() {}); + if (delayedStream.pauseStream) { + source.pause(); + } + + return delayedStream; +}; + +Object.defineProperty(DelayedStream.prototype, 'readable', { + configurable: true, + enumerable: true, + get: function() { + return this.source.readable; + } +}); + +DelayedStream.prototype.setEncoding = function() { + return this.source.setEncoding.apply(this.source, arguments); +}; + +DelayedStream.prototype.resume = function() { + if (!this._released) { + this.release(); + } + + this.source.resume(); +}; + +DelayedStream.prototype.pause = function() { + this.source.pause(); +}; + +DelayedStream.prototype.release = function() { + this._released = true; - if (isIterableDone) { - break; - } - } - }); + this._bufferedEvents.forEach(function(args) { + this.emit.apply(this, args); + }.bind(this)); + this._bufferedEvents = []; +}; + +DelayedStream.prototype.pipe = function() { + var r = Stream.prototype.pipe.apply(this, arguments); + this.resume(); + return r; +}; + +DelayedStream.prototype._handleEmit = function(args) { + if (this._released) { + this.emit.apply(this, args); + return; + } + + if (args[0] === 'data') { + this.dataSize += args[1].length; + this._checkIfMaxDataSizeExceeded(); + } + + this._bufferedEvents.push(args); +}; + +DelayedStream.prototype._checkIfMaxDataSizeExceeded = function() { + if (this._maxDataSizeExceeded) { + return; + } + + if (this.dataSize <= this.maxDataSize) { + return; + } + + this._maxDataSizeExceeded = true; + var message = + 'DelayedStream#maxDataSize of ' + this.maxDataSize + ' bytes exceeded.' + this.emit('error', new Error(message)); }; @@ -26759,7 +28257,7 @@ RedirectableRequest.prototype._performRequest = function () { // If specified, use the agent corresponding to the protocol // (HTTP and HTTPS use different types of agents) if (this._options.agents) { - var scheme = protocol.substr(0, protocol.length - 1); + var scheme = protocol.slice(0, -1); this._options.agent = this._options.agents[scheme]; } @@ -26851,10 +28349,21 @@ RedirectableRequest.prototype._processResponse = function (response) { return; } + // Store the request headers if applicable + var requestHeaders; + var beforeRedirect = this._options.beforeRedirect; + if (beforeRedirect) { + requestHeaders = Object.assign({ + // The Host header was set by nativeProtocol.request + Host: response.req.getHeader("host"), + }, this._options.headers); + } + // RFC7231§6.4: Automatic redirection needs to done with // care for methods not known to be safe, […] // RFC7231§6.4.2–3: For historical reasons, a user agent MAY change // the request method from POST to GET for the subsequent request. + var method = this._options.method; if ((statusCode === 301 || statusCode === 302) && this._options.method === "POST" || // RFC7231§6.4.4: The 303 (See Other) status code indicates that // the server is redirecting the user agent to a different resource […] @@ -26902,10 +28411,18 @@ RedirectableRequest.prototype._processResponse = function (response) { } // Evaluate the beforeRedirect callback - if (typeof this._options.beforeRedirect === "function") { - var responseDetails = { headers: response.headers }; + if (typeof beforeRedirect === "function") { + var responseDetails = { + headers: response.headers, + statusCode: statusCode, + }; + var requestDetails = { + url: currentUrl, + method: method, + headers: requestHeaders, + }; try { - this._options.beforeRedirect.call(null, this._options, responseDetails); + beforeRedirect(this._options, responseDetails, requestDetails); } catch (err) { this.emit("error", err); @@ -26971,96 +28488,621 @@ function wrap(protocols) { }, input, options); options.nativeProtocols = nativeProtocols; - assert.equal(options.protocol, protocol, "protocol mismatch"); - debug("options", options); - return new RedirectableRequest(options, callback); + assert.equal(options.protocol, protocol, "protocol mismatch"); + debug("options", options); + return new RedirectableRequest(options, callback); + } + + // Executes a GET request, following redirects + function get(input, options, callback) { + var wrappedRequest = wrappedProtocol.request(input, options, callback); + wrappedRequest.end(); + return wrappedRequest; + } + + // Expose the properties on the wrapped protocol + Object.defineProperties(wrappedProtocol, { + request: { value: request, configurable: true, enumerable: true, writable: true }, + get: { value: get, configurable: true, enumerable: true, writable: true }, + }); + }); + return exports; +} + +/* istanbul ignore next */ +function noop() { /* empty */ } + +// from https://github.com/nodejs/node/blob/master/lib/internal/url.js +function urlToOptions(urlObject) { + var options = { + protocol: urlObject.protocol, + hostname: urlObject.hostname.startsWith("[") ? + /* istanbul ignore next */ + urlObject.hostname.slice(1, -1) : + urlObject.hostname, + hash: urlObject.hash, + search: urlObject.search, + pathname: urlObject.pathname, + path: urlObject.pathname + urlObject.search, + href: urlObject.href, + }; + if (urlObject.port !== "") { + options.port = Number(urlObject.port); + } + return options; +} + +function removeMatchingHeaders(regex, headers) { + var lastValue; + for (var header in headers) { + if (regex.test(header)) { + lastValue = headers[header]; + delete headers[header]; + } + } + return (lastValue === null || typeof lastValue === "undefined") ? + undefined : String(lastValue).trim(); +} + +function createErrorType(code, defaultMessage) { + function CustomError(cause) { + Error.captureStackTrace(this, this.constructor); + if (!cause) { + this.message = defaultMessage; + } + else { + this.message = defaultMessage + ": " + cause.message; + this.cause = cause; + } + } + CustomError.prototype = new Error(); + CustomError.prototype.constructor = CustomError; + CustomError.prototype.name = "Error [" + code + "]"; + CustomError.prototype.code = code; + return CustomError; +} + +function abortRequest(request) { + for (var e = 0; e < events.length; e++) { + request.removeListener(events[e], eventHandlers[events[e]]); + } + request.on("error", noop); + request.abort(); +} + +function isSubdomain(subdomain, domain) { + const dot = subdomain.length - domain.length - 1; + return dot > 0 && subdomain[dot] === "." && subdomain.endsWith(domain); +} + +// Exports +module.exports = wrap({ http: http, https: https }); +module.exports.wrap = wrap; + + +/***/ }), + +/***/ "../../node_modules/form-data/lib/form_data.js": +/***/ (function(module, exports, __webpack_require__) { + +var CombinedStream = __webpack_require__("../../node_modules/combined-stream/lib/combined_stream.js"); +var util = __webpack_require__("util"); +var path = __webpack_require__("path"); +var http = __webpack_require__("http"); +var https = __webpack_require__("https"); +var parseUrl = __webpack_require__("url").parse; +var fs = __webpack_require__("fs"); +var Stream = __webpack_require__("stream").Stream; +var mime = __webpack_require__("../../node_modules/mime-types/index.js"); +var asynckit = __webpack_require__("../../node_modules/asynckit/index.js"); +var populate = __webpack_require__("../../node_modules/form-data/lib/populate.js"); + +// Public API +module.exports = FormData; + +// make it a Stream +util.inherits(FormData, CombinedStream); + +/** + * Create readable "multipart/form-data" streams. + * Can be used to submit forms + * and file uploads to other web applications. + * + * @constructor + * @param {Object} options - Properties to be added/overriden for FormData and CombinedStream + */ +function FormData(options) { + if (!(this instanceof FormData)) { + return new FormData(options); + } + + this._overheadLength = 0; + this._valueLength = 0; + this._valuesToMeasure = []; + + CombinedStream.call(this); + + options = options || {}; + for (var option in options) { + this[option] = options[option]; + } +} + +FormData.LINE_BREAK = '\r\n'; +FormData.DEFAULT_CONTENT_TYPE = 'application/octet-stream'; + +FormData.prototype.append = function(field, value, options) { + + options = options || {}; + + // allow filename as single option + if (typeof options == 'string') { + options = {filename: options}; + } + + var append = CombinedStream.prototype.append.bind(this); + + // all that streamy business can't handle numbers + if (typeof value == 'number') { + value = '' + value; + } + + // https://github.com/felixge/node-form-data/issues/38 + if (util.isArray(value)) { + // Please convert your array into string + // the way web server expects it + this._error(new Error('Arrays are not supported.')); + return; + } + + var header = this._multiPartHeader(field, value, options); + var footer = this._multiPartFooter(); + + append(header); + append(value); + append(footer); + + // pass along options.knownLength + this._trackLength(header, value, options); +}; + +FormData.prototype._trackLength = function(header, value, options) { + var valueLength = 0; + + // used w/ getLengthSync(), when length is known. + // e.g. for streaming directly from a remote server, + // w/ a known file a size, and not wanting to wait for + // incoming file to finish to get its size. + if (options.knownLength != null) { + valueLength += +options.knownLength; + } else if (Buffer.isBuffer(value)) { + valueLength = value.length; + } else if (typeof value === 'string') { + valueLength = Buffer.byteLength(value); + } + + this._valueLength += valueLength; + + // @check why add CRLF? does this account for custom/multiple CRLFs? + this._overheadLength += + Buffer.byteLength(header) + + FormData.LINE_BREAK.length; + + // empty or either doesn't have path or not an http response or not a stream + if (!value || ( !value.path && !(value.readable && value.hasOwnProperty('httpVersion')) && !(value instanceof Stream))) { + return; + } + + // no need to bother with the length + if (!options.knownLength) { + this._valuesToMeasure.push(value); + } +}; + +FormData.prototype._lengthRetriever = function(value, callback) { + + if (value.hasOwnProperty('fd')) { + + // take read range into a account + // `end` = Infinity –> read file till the end + // + // TODO: Looks like there is bug in Node fs.createReadStream + // it doesn't respect `end` options without `start` options + // Fix it when node fixes it. + // https://github.com/joyent/node/issues/7819 + if (value.end != undefined && value.end != Infinity && value.start != undefined) { + + // when end specified + // no need to calculate range + // inclusive, starts with 0 + callback(null, value.end + 1 - (value.start ? value.start : 0)); + + // not that fast snoopy + } else { + // still need to fetch file size from fs + fs.stat(value.path, function(err, stat) { + + var fileSize; + + if (err) { + callback(err); + return; + } + + // update final size based on the range options + fileSize = stat.size - (value.start ? value.start : 0); + callback(null, fileSize); + }); + } + + // or http response + } else if (value.hasOwnProperty('httpVersion')) { + callback(null, +value.headers['content-length']); + + // or request stream http://github.com/mikeal/request + } else if (value.hasOwnProperty('httpModule')) { + // wait till response come back + value.on('response', function(response) { + value.pause(); + callback(null, +response.headers['content-length']); + }); + value.resume(); + + // something else + } else { + callback('Unknown stream'); + } +}; + +FormData.prototype._multiPartHeader = function(field, value, options) { + // custom header specified (as string)? + // it becomes responsible for boundary + // (e.g. to handle extra CRLFs on .NET servers) + if (typeof options.header == 'string') { + return options.header; + } + + var contentDisposition = this._getContentDisposition(value, options); + var contentType = this._getContentType(value, options); + + var contents = ''; + var headers = { + // add custom disposition as third element or keep it two elements if not + 'Content-Disposition': ['form-data', 'name="' + field + '"'].concat(contentDisposition || []), + // if no content type. allow it to be empty array + 'Content-Type': [].concat(contentType || []) + }; + + // allow custom headers. + if (typeof options.header == 'object') { + populate(headers, options.header); + } + + var header; + for (var prop in headers) { + if (!headers.hasOwnProperty(prop)) continue; + header = headers[prop]; + + // skip nullish headers. + if (header == null) { + continue; + } + + // convert all headers to arrays. + if (!Array.isArray(header)) { + header = [header]; + } + + // add non-empty headers. + if (header.length) { + contents += prop + ': ' + header.join('; ') + FormData.LINE_BREAK; + } + } + + return '--' + this.getBoundary() + FormData.LINE_BREAK + contents + FormData.LINE_BREAK; +}; + +FormData.prototype._getContentDisposition = function(value, options) { + + var filename + , contentDisposition + ; + + if (typeof options.filepath === 'string') { + // custom filepath for relative paths + filename = path.normalize(options.filepath).replace(/\\/g, '/'); + } else if (options.filename || value.name || value.path) { + // custom filename take precedence + // formidable and the browser add a name property + // fs- and request- streams have path property + filename = path.basename(options.filename || value.name || value.path); + } else if (value.readable && value.hasOwnProperty('httpVersion')) { + // or try http response + filename = path.basename(value.client._httpMessage.path || ''); + } + + if (filename) { + contentDisposition = 'filename="' + filename + '"'; + } + + return contentDisposition; +}; + +FormData.prototype._getContentType = function(value, options) { + + // use custom content-type above all + var contentType = options.contentType; + + // or try `name` from formidable, browser + if (!contentType && value.name) { + contentType = mime.lookup(value.name); + } + + // or try `path` from fs-, request- streams + if (!contentType && value.path) { + contentType = mime.lookup(value.path); + } + + // or if it's http-reponse + if (!contentType && value.readable && value.hasOwnProperty('httpVersion')) { + contentType = value.headers['content-type']; + } + + // or guess it from the filepath or filename + if (!contentType && (options.filepath || options.filename)) { + contentType = mime.lookup(options.filepath || options.filename); + } + + // fallback to the default content type if `value` is not simple value + if (!contentType && typeof value == 'object') { + contentType = FormData.DEFAULT_CONTENT_TYPE; + } + + return contentType; +}; + +FormData.prototype._multiPartFooter = function() { + return function(next) { + var footer = FormData.LINE_BREAK; + + var lastPart = (this._streams.length === 0); + if (lastPart) { + footer += this._lastBoundary(); + } + + next(footer); + }.bind(this); +}; + +FormData.prototype._lastBoundary = function() { + return '--' + this.getBoundary() + '--' + FormData.LINE_BREAK; +}; + +FormData.prototype.getHeaders = function(userHeaders) { + var header; + var formHeaders = { + 'content-type': 'multipart/form-data; boundary=' + this.getBoundary() + }; + + for (header in userHeaders) { + if (userHeaders.hasOwnProperty(header)) { + formHeaders[header.toLowerCase()] = userHeaders[header]; + } + } + + return formHeaders; +}; + +FormData.prototype.setBoundary = function(boundary) { + this._boundary = boundary; +}; + +FormData.prototype.getBoundary = function() { + if (!this._boundary) { + this._generateBoundary(); + } + + return this._boundary; +}; + +FormData.prototype.getBuffer = function() { + var dataBuffer = new Buffer.alloc( 0 ); + var boundary = this.getBoundary(); + + // Create the form content. Add Line breaks to the end of data. + for (var i = 0, len = this._streams.length; i < len; i++) { + if (typeof this._streams[i] !== 'function') { + + // Add content to the buffer. + if(Buffer.isBuffer(this._streams[i])) { + dataBuffer = Buffer.concat( [dataBuffer, this._streams[i]]); + }else { + dataBuffer = Buffer.concat( [dataBuffer, Buffer.from(this._streams[i])]); + } + + // Add break after content. + if (typeof this._streams[i] !== 'string' || this._streams[i].substring( 2, boundary.length + 2 ) !== boundary) { + dataBuffer = Buffer.concat( [dataBuffer, Buffer.from(FormData.LINE_BREAK)] ); + } } + } - // Executes a GET request, following redirects - function get(input, options, callback) { - var wrappedRequest = wrappedProtocol.request(input, options, callback); - wrappedRequest.end(); - return wrappedRequest; + // Add the footer and return the Buffer object. + return Buffer.concat( [dataBuffer, Buffer.from(this._lastBoundary())] ); +}; + +FormData.prototype._generateBoundary = function() { + // This generates a 50 character boundary similar to those used by Firefox. + // They are optimized for boyer-moore parsing. + var boundary = '--------------------------'; + for (var i = 0; i < 24; i++) { + boundary += Math.floor(Math.random() * 10).toString(16); + } + + this._boundary = boundary; +}; + +// Note: getLengthSync DOESN'T calculate streams length +// As workaround one can calculate file size manually +// and add it as knownLength option +FormData.prototype.getLengthSync = function() { + var knownLength = this._overheadLength + this._valueLength; + + // Don't get confused, there are 3 "internal" streams for each keyval pair + // so it basically checks if there is any value added to the form + if (this._streams.length) { + knownLength += this._lastBoundary().length; + } + + // https://github.com/form-data/form-data/issues/40 + if (!this.hasKnownLength()) { + // Some async length retrievers are present + // therefore synchronous length calculation is false. + // Please use getLength(callback) to get proper length + this._error(new Error('Cannot calculate proper length in synchronous way.')); + } + + return knownLength; +}; + +// Public API to check if length of added values is known +// https://github.com/form-data/form-data/issues/196 +// https://github.com/form-data/form-data/issues/262 +FormData.prototype.hasKnownLength = function() { + var hasKnownLength = true; + + if (this._valuesToMeasure.length) { + hasKnownLength = false; + } + + return hasKnownLength; +}; + +FormData.prototype.getLength = function(cb) { + var knownLength = this._overheadLength + this._valueLength; + + if (this._streams.length) { + knownLength += this._lastBoundary().length; + } + + if (!this._valuesToMeasure.length) { + process.nextTick(cb.bind(this, null, knownLength)); + return; + } + + asynckit.parallel(this._valuesToMeasure, this._lengthRetriever, function(err, values) { + if (err) { + cb(err); + return; } - // Expose the properties on the wrapped protocol - Object.defineProperties(wrappedProtocol, { - request: { value: request, configurable: true, enumerable: true, writable: true }, - get: { value: get, configurable: true, enumerable: true, writable: true }, + values.forEach(function(length) { + knownLength += length; }); + + cb(null, knownLength); }); - return exports; -} +}; -/* istanbul ignore next */ -function noop() { /* empty */ } +FormData.prototype.submit = function(params, cb) { + var request + , options + , defaults = {method: 'post'} + ; -// from https://github.com/nodejs/node/blob/master/lib/internal/url.js -function urlToOptions(urlObject) { - var options = { - protocol: urlObject.protocol, - hostname: urlObject.hostname.startsWith("[") ? - /* istanbul ignore next */ - urlObject.hostname.slice(1, -1) : - urlObject.hostname, - hash: urlObject.hash, - search: urlObject.search, - pathname: urlObject.pathname, - path: urlObject.pathname + urlObject.search, - href: urlObject.href, - }; - if (urlObject.port !== "") { - options.port = Number(urlObject.port); - } - return options; -} + // parse provided url if it's string + // or treat it as options object + if (typeof params == 'string') { -function removeMatchingHeaders(regex, headers) { - var lastValue; - for (var header in headers) { - if (regex.test(header)) { - lastValue = headers[header]; - delete headers[header]; + params = parseUrl(params); + options = populate({ + port: params.port, + path: params.pathname, + host: params.hostname, + protocol: params.protocol + }, defaults); + + // use custom params + } else { + + options = populate(params, defaults); + // if no port provided use default one + if (!options.port) { + options.port = options.protocol == 'https:' ? 443 : 80; } } - return (lastValue === null || typeof lastValue === "undefined") ? - undefined : String(lastValue).trim(); -} -function createErrorType(code, defaultMessage) { - function CustomError(cause) { - Error.captureStackTrace(this, this.constructor); - if (!cause) { - this.message = defaultMessage; + // put that good code in getHeaders to some use + options.headers = this.getHeaders(params.headers); + + // https if specified, fallback to http in any other case + if (options.protocol == 'https:') { + request = https.request(options); + } else { + request = http.request(options); + } + + // get content length and fire away + this.getLength(function(err, length) { + if (err && err !== 'Unknown stream') { + this._error(err); + return; } - else { - this.message = defaultMessage + ": " + cause.message; - this.cause = cause; + + // add content length + if (length) { + request.setHeader('Content-Length', length); } - } - CustomError.prototype = new Error(); - CustomError.prototype.constructor = CustomError; - CustomError.prototype.name = "Error [" + code + "]"; - CustomError.prototype.code = code; - return CustomError; -} -function abortRequest(request) { - for (var e = 0; e < events.length; e++) { - request.removeListener(events[e], eventHandlers[events[e]]); + this.pipe(request); + if (cb) { + var onResponse; + + var callback = function (error, responce) { + request.removeListener('error', callback); + request.removeListener('response', onResponse); + + return cb.call(this, error, responce); + }; + + onResponse = callback.bind(this, null); + + request.on('error', callback); + request.on('response', onResponse); + } + }.bind(this)); + + return request; +}; + +FormData.prototype._error = function(err) { + if (!this.error) { + this.error = err; + this.pause(); + this.emit('error', err); } - request.on("error", noop); - request.abort(); -} +}; -function isSubdomain(subdomain, domain) { - const dot = subdomain.length - domain.length - 1; - return dot > 0 && subdomain[dot] === "." && subdomain.endsWith(domain); -} +FormData.prototype.toString = function () { + return '[object FormData]'; +}; -// Exports -module.exports = wrap({ http: http, https: https }); -module.exports.wrap = wrap; + +/***/ }), + +/***/ "../../node_modules/form-data/lib/populate.js": +/***/ (function(module, exports) { + +// populates missing values +module.exports = function(dst, src) { + + Object.keys(src).forEach(function(prop) + { + dst[prop] = dst[prop] || src[prop]; + }); + + return dst; +}; /***/ }), @@ -34967,6 +37009,227 @@ function pauseStreams (streams, options) { } +/***/ }), + +/***/ "../../node_modules/mime-db/db.json": +/***/ (function(module) { + +module.exports = JSON.parse("{\"application/1d-interleaved-parityfec\":{\"source\":\"iana\"},\"application/3gpdash-qoe-report+xml\":{\"source\":\"iana\",\"charset\":\"UTF-8\",\"compressible\":true},\"application/3gpp-ims+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/a2l\":{\"source\":\"iana\"},\"application/activemessage\":{\"source\":\"iana\"},\"application/activity+json\":{\"source\":\"iana\",\"compressible\":true},\"application/alto-costmap+json\":{\"source\":\"iana\",\"compressible\":true},\"application/alto-costmapfilter+json\":{\"source\":\"iana\",\"compressible\":true},\"application/alto-directory+json\":{\"source\":\"iana\",\"compressible\":true},\"application/alto-endpointcost+json\":{\"source\":\"iana\",\"compressible\":true},\"application/alto-endpointcostparams+json\":{\"source\":\"iana\",\"compressible\":true},\"application/alto-endpointprop+json\":{\"source\":\"iana\",\"compressible\":true},\"application/alto-endpointpropparams+json\":{\"source\":\"iana\",\"compressible\":true},\"application/alto-error+json\":{\"source\":\"iana\",\"compressible\":true},\"application/alto-networkmap+json\":{\"source\":\"iana\",\"compressible\":true},\"application/alto-networkmapfilter+json\":{\"source\":\"iana\",\"compressible\":true},\"application/alto-updatestreamcontrol+json\":{\"source\":\"iana\",\"compressible\":true},\"application/alto-updatestreamparams+json\":{\"source\":\"iana\",\"compressible\":true},\"application/aml\":{\"source\":\"iana\"},\"application/andrew-inset\":{\"source\":\"iana\",\"extensions\":[\"ez\"]},\"application/applefile\":{\"source\":\"iana\"},\"application/applixware\":{\"source\":\"apache\",\"extensions\":[\"aw\"]},\"application/atf\":{\"source\":\"iana\"},\"application/atfx\":{\"source\":\"iana\"},\"application/atom+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"atom\"]},\"application/atomcat+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"atomcat\"]},\"application/atomdeleted+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"atomdeleted\"]},\"application/atomicmail\":{\"source\":\"iana\"},\"application/atomsvc+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"atomsvc\"]},\"application/atsc-dwd+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"dwd\"]},\"application/atsc-dynamic-event-message\":{\"source\":\"iana\"},\"application/atsc-held+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"held\"]},\"application/atsc-rdt+json\":{\"source\":\"iana\",\"compressible\":true},\"application/atsc-rsat+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"rsat\"]},\"application/atxml\":{\"source\":\"iana\"},\"application/auth-policy+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/bacnet-xdd+zip\":{\"source\":\"iana\",\"compressible\":false},\"application/batch-smtp\":{\"source\":\"iana\"},\"application/bdoc\":{\"compressible\":false,\"extensions\":[\"bdoc\"]},\"application/beep+xml\":{\"source\":\"iana\",\"charset\":\"UTF-8\",\"compressible\":true},\"application/calendar+json\":{\"source\":\"iana\",\"compressible\":true},\"application/calendar+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"xcs\"]},\"application/call-completion\":{\"source\":\"iana\"},\"application/cals-1840\":{\"source\":\"iana\"},\"application/cap+xml\":{\"source\":\"iana\",\"charset\":\"UTF-8\",\"compressible\":true},\"application/cbor\":{\"source\":\"iana\"},\"application/cbor-seq\":{\"source\":\"iana\"},\"application/cccex\":{\"source\":\"iana\"},\"application/ccmp+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/ccxml+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"ccxml\"]},\"application/cdfx+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"cdfx\"]},\"application/cdmi-capability\":{\"source\":\"iana\",\"extensions\":[\"cdmia\"]},\"application/cdmi-container\":{\"source\":\"iana\",\"extensions\":[\"cdmic\"]},\"application/cdmi-domain\":{\"source\":\"iana\",\"extensions\":[\"cdmid\"]},\"application/cdmi-object\":{\"source\":\"iana\",\"extensions\":[\"cdmio\"]},\"application/cdmi-queue\":{\"source\":\"iana\",\"extensions\":[\"cdmiq\"]},\"application/cdni\":{\"source\":\"iana\"},\"application/cea\":{\"source\":\"iana\"},\"application/cea-2018+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/cellml+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/cfw\":{\"source\":\"iana\"},\"application/clue+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/clue_info+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/cms\":{\"source\":\"iana\"},\"application/cnrp+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/coap-group+json\":{\"source\":\"iana\",\"compressible\":true},\"application/coap-payload\":{\"source\":\"iana\"},\"application/commonground\":{\"source\":\"iana\"},\"application/conference-info+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/cose\":{\"source\":\"iana\"},\"application/cose-key\":{\"source\":\"iana\"},\"application/cose-key-set\":{\"source\":\"iana\"},\"application/cpl+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/csrattrs\":{\"source\":\"iana\"},\"application/csta+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/cstadata+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/csvm+json\":{\"source\":\"iana\",\"compressible\":true},\"application/cu-seeme\":{\"source\":\"apache\",\"extensions\":[\"cu\"]},\"application/cwt\":{\"source\":\"iana\"},\"application/cybercash\":{\"source\":\"iana\"},\"application/dart\":{\"compressible\":true},\"application/dash+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"mpd\"]},\"application/dashdelta\":{\"source\":\"iana\"},\"application/davmount+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"davmount\"]},\"application/dca-rft\":{\"source\":\"iana\"},\"application/dcd\":{\"source\":\"iana\"},\"application/dec-dx\":{\"source\":\"iana\"},\"application/dialog-info+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/dicom\":{\"source\":\"iana\"},\"application/dicom+json\":{\"source\":\"iana\",\"compressible\":true},\"application/dicom+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/dii\":{\"source\":\"iana\"},\"application/dit\":{\"source\":\"iana\"},\"application/dns\":{\"source\":\"iana\"},\"application/dns+json\":{\"source\":\"iana\",\"compressible\":true},\"application/dns-message\":{\"source\":\"iana\"},\"application/docbook+xml\":{\"source\":\"apache\",\"compressible\":true,\"extensions\":[\"dbk\"]},\"application/dots+cbor\":{\"source\":\"iana\"},\"application/dskpp+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/dssc+der\":{\"source\":\"iana\",\"extensions\":[\"dssc\"]},\"application/dssc+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"xdssc\"]},\"application/dvcs\":{\"source\":\"iana\"},\"application/ecmascript\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"ecma\",\"es\"]},\"application/edi-consent\":{\"source\":\"iana\"},\"application/edi-x12\":{\"source\":\"iana\",\"compressible\":false},\"application/edifact\":{\"source\":\"iana\",\"compressible\":false},\"application/efi\":{\"source\":\"iana\"},\"application/emergencycalldata.comment+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/emergencycalldata.control+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/emergencycalldata.deviceinfo+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/emergencycalldata.ecall.msd\":{\"source\":\"iana\"},\"application/emergencycalldata.providerinfo+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/emergencycalldata.serviceinfo+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/emergencycalldata.subscriberinfo+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/emergencycalldata.veds+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/emma+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"emma\"]},\"application/emotionml+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"emotionml\"]},\"application/encaprtp\":{\"source\":\"iana\"},\"application/epp+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/epub+zip\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"epub\"]},\"application/eshop\":{\"source\":\"iana\"},\"application/exi\":{\"source\":\"iana\",\"extensions\":[\"exi\"]},\"application/expect-ct-report+json\":{\"source\":\"iana\",\"compressible\":true},\"application/fastinfoset\":{\"source\":\"iana\"},\"application/fastsoap\":{\"source\":\"iana\"},\"application/fdt+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"fdt\"]},\"application/fhir+json\":{\"source\":\"iana\",\"charset\":\"UTF-8\",\"compressible\":true},\"application/fhir+xml\":{\"source\":\"iana\",\"charset\":\"UTF-8\",\"compressible\":true},\"application/fido.trusted-apps+json\":{\"compressible\":true},\"application/fits\":{\"source\":\"iana\"},\"application/flexfec\":{\"source\":\"iana\"},\"application/font-sfnt\":{\"source\":\"iana\"},\"application/font-tdpfr\":{\"source\":\"iana\",\"extensions\":[\"pfr\"]},\"application/font-woff\":{\"source\":\"iana\",\"compressible\":false},\"application/framework-attributes+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/geo+json\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"geojson\"]},\"application/geo+json-seq\":{\"source\":\"iana\"},\"application/geopackage+sqlite3\":{\"source\":\"iana\"},\"application/geoxacml+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/gltf-buffer\":{\"source\":\"iana\"},\"application/gml+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"gml\"]},\"application/gpx+xml\":{\"source\":\"apache\",\"compressible\":true,\"extensions\":[\"gpx\"]},\"application/gxf\":{\"source\":\"apache\",\"extensions\":[\"gxf\"]},\"application/gzip\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"gz\"]},\"application/h224\":{\"source\":\"iana\"},\"application/held+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/hjson\":{\"extensions\":[\"hjson\"]},\"application/http\":{\"source\":\"iana\"},\"application/hyperstudio\":{\"source\":\"iana\",\"extensions\":[\"stk\"]},\"application/ibe-key-request+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/ibe-pkg-reply+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/ibe-pp-data\":{\"source\":\"iana\"},\"application/iges\":{\"source\":\"iana\"},\"application/im-iscomposing+xml\":{\"source\":\"iana\",\"charset\":\"UTF-8\",\"compressible\":true},\"application/index\":{\"source\":\"iana\"},\"application/index.cmd\":{\"source\":\"iana\"},\"application/index.obj\":{\"source\":\"iana\"},\"application/index.response\":{\"source\":\"iana\"},\"application/index.vnd\":{\"source\":\"iana\"},\"application/inkml+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"ink\",\"inkml\"]},\"application/iotp\":{\"source\":\"iana\"},\"application/ipfix\":{\"source\":\"iana\",\"extensions\":[\"ipfix\"]},\"application/ipp\":{\"source\":\"iana\"},\"application/isup\":{\"source\":\"iana\"},\"application/its+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"its\"]},\"application/java-archive\":{\"source\":\"apache\",\"compressible\":false,\"extensions\":[\"jar\",\"war\",\"ear\"]},\"application/java-serialized-object\":{\"source\":\"apache\",\"compressible\":false,\"extensions\":[\"ser\"]},\"application/java-vm\":{\"source\":\"apache\",\"compressible\":false,\"extensions\":[\"class\"]},\"application/javascript\":{\"source\":\"iana\",\"charset\":\"UTF-8\",\"compressible\":true,\"extensions\":[\"js\",\"mjs\"]},\"application/jf2feed+json\":{\"source\":\"iana\",\"compressible\":true},\"application/jose\":{\"source\":\"iana\"},\"application/jose+json\":{\"source\":\"iana\",\"compressible\":true},\"application/jrd+json\":{\"source\":\"iana\",\"compressible\":true},\"application/json\":{\"source\":\"iana\",\"charset\":\"UTF-8\",\"compressible\":true,\"extensions\":[\"json\",\"map\"]},\"application/json-patch+json\":{\"source\":\"iana\",\"compressible\":true},\"application/json-seq\":{\"source\":\"iana\"},\"application/json5\":{\"extensions\":[\"json5\"]},\"application/jsonml+json\":{\"source\":\"apache\",\"compressible\":true,\"extensions\":[\"jsonml\"]},\"application/jwk+json\":{\"source\":\"iana\",\"compressible\":true},\"application/jwk-set+json\":{\"source\":\"iana\",\"compressible\":true},\"application/jwt\":{\"source\":\"iana\"},\"application/kpml-request+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/kpml-response+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/ld+json\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"jsonld\"]},\"application/lgr+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"lgr\"]},\"application/link-format\":{\"source\":\"iana\"},\"application/load-control+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/lost+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"lostxml\"]},\"application/lostsync+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/lpf+zip\":{\"source\":\"iana\",\"compressible\":false},\"application/lxf\":{\"source\":\"iana\"},\"application/mac-binhex40\":{\"source\":\"iana\",\"extensions\":[\"hqx\"]},\"application/mac-compactpro\":{\"source\":\"apache\",\"extensions\":[\"cpt\"]},\"application/macwriteii\":{\"source\":\"iana\"},\"application/mads+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"mads\"]},\"application/manifest+json\":{\"charset\":\"UTF-8\",\"compressible\":true,\"extensions\":[\"webmanifest\"]},\"application/marc\":{\"source\":\"iana\",\"extensions\":[\"mrc\"]},\"application/marcxml+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"mrcx\"]},\"application/mathematica\":{\"source\":\"iana\",\"extensions\":[\"ma\",\"nb\",\"mb\"]},\"application/mathml+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"mathml\"]},\"application/mathml-content+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/mathml-presentation+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/mbms-associated-procedure-description+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/mbms-deregister+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/mbms-envelope+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/mbms-msk+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/mbms-msk-response+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/mbms-protection-description+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/mbms-reception-report+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/mbms-register+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/mbms-register-response+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/mbms-schedule+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/mbms-user-service-description+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/mbox\":{\"source\":\"iana\",\"extensions\":[\"mbox\"]},\"application/media-policy-dataset+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/media_control+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/mediaservercontrol+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"mscml\"]},\"application/merge-patch+json\":{\"source\":\"iana\",\"compressible\":true},\"application/metalink+xml\":{\"source\":\"apache\",\"compressible\":true,\"extensions\":[\"metalink\"]},\"application/metalink4+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"meta4\"]},\"application/mets+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"mets\"]},\"application/mf4\":{\"source\":\"iana\"},\"application/mikey\":{\"source\":\"iana\"},\"application/mipc\":{\"source\":\"iana\"},\"application/mmt-aei+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"maei\"]},\"application/mmt-usd+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"musd\"]},\"application/mods+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"mods\"]},\"application/moss-keys\":{\"source\":\"iana\"},\"application/moss-signature\":{\"source\":\"iana\"},\"application/mosskey-data\":{\"source\":\"iana\"},\"application/mosskey-request\":{\"source\":\"iana\"},\"application/mp21\":{\"source\":\"iana\",\"extensions\":[\"m21\",\"mp21\"]},\"application/mp4\":{\"source\":\"iana\",\"extensions\":[\"mp4s\",\"m4p\"]},\"application/mpeg4-generic\":{\"source\":\"iana\"},\"application/mpeg4-iod\":{\"source\":\"iana\"},\"application/mpeg4-iod-xmt\":{\"source\":\"iana\"},\"application/mrb-consumer+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"xdf\"]},\"application/mrb-publish+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"xdf\"]},\"application/msc-ivr+xml\":{\"source\":\"iana\",\"charset\":\"UTF-8\",\"compressible\":true},\"application/msc-mixer+xml\":{\"source\":\"iana\",\"charset\":\"UTF-8\",\"compressible\":true},\"application/msword\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"doc\",\"dot\"]},\"application/mud+json\":{\"source\":\"iana\",\"compressible\":true},\"application/multipart-core\":{\"source\":\"iana\"},\"application/mxf\":{\"source\":\"iana\",\"extensions\":[\"mxf\"]},\"application/n-quads\":{\"source\":\"iana\",\"extensions\":[\"nq\"]},\"application/n-triples\":{\"source\":\"iana\",\"extensions\":[\"nt\"]},\"application/nasdata\":{\"source\":\"iana\"},\"application/news-checkgroups\":{\"source\":\"iana\",\"charset\":\"US-ASCII\"},\"application/news-groupinfo\":{\"source\":\"iana\",\"charset\":\"US-ASCII\"},\"application/news-transmission\":{\"source\":\"iana\"},\"application/nlsml+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/node\":{\"source\":\"iana\",\"extensions\":[\"cjs\"]},\"application/nss\":{\"source\":\"iana\"},\"application/ocsp-request\":{\"source\":\"iana\"},\"application/ocsp-response\":{\"source\":\"iana\"},\"application/octet-stream\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"bin\",\"dms\",\"lrf\",\"mar\",\"so\",\"dist\",\"distz\",\"pkg\",\"bpk\",\"dump\",\"elc\",\"deploy\",\"exe\",\"dll\",\"deb\",\"dmg\",\"iso\",\"img\",\"msi\",\"msp\",\"msm\",\"buffer\"]},\"application/oda\":{\"source\":\"iana\",\"extensions\":[\"oda\"]},\"application/odm+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/odx\":{\"source\":\"iana\"},\"application/oebps-package+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"opf\"]},\"application/ogg\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"ogx\"]},\"application/omdoc+xml\":{\"source\":\"apache\",\"compressible\":true,\"extensions\":[\"omdoc\"]},\"application/onenote\":{\"source\":\"apache\",\"extensions\":[\"onetoc\",\"onetoc2\",\"onetmp\",\"onepkg\"]},\"application/oscore\":{\"source\":\"iana\"},\"application/oxps\":{\"source\":\"iana\",\"extensions\":[\"oxps\"]},\"application/p2p-overlay+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"relo\"]},\"application/parityfec\":{\"source\":\"iana\"},\"application/passport\":{\"source\":\"iana\"},\"application/patch-ops-error+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"xer\"]},\"application/pdf\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"pdf\"]},\"application/pdx\":{\"source\":\"iana\"},\"application/pem-certificate-chain\":{\"source\":\"iana\"},\"application/pgp-encrypted\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"pgp\"]},\"application/pgp-keys\":{\"source\":\"iana\"},\"application/pgp-signature\":{\"source\":\"iana\",\"extensions\":[\"asc\",\"sig\"]},\"application/pics-rules\":{\"source\":\"apache\",\"extensions\":[\"prf\"]},\"application/pidf+xml\":{\"source\":\"iana\",\"charset\":\"UTF-8\",\"compressible\":true},\"application/pidf-diff+xml\":{\"source\":\"iana\",\"charset\":\"UTF-8\",\"compressible\":true},\"application/pkcs10\":{\"source\":\"iana\",\"extensions\":[\"p10\"]},\"application/pkcs12\":{\"source\":\"iana\"},\"application/pkcs7-mime\":{\"source\":\"iana\",\"extensions\":[\"p7m\",\"p7c\"]},\"application/pkcs7-signature\":{\"source\":\"iana\",\"extensions\":[\"p7s\"]},\"application/pkcs8\":{\"source\":\"iana\",\"extensions\":[\"p8\"]},\"application/pkcs8-encrypted\":{\"source\":\"iana\"},\"application/pkix-attr-cert\":{\"source\":\"iana\",\"extensions\":[\"ac\"]},\"application/pkix-cert\":{\"source\":\"iana\",\"extensions\":[\"cer\"]},\"application/pkix-crl\":{\"source\":\"iana\",\"extensions\":[\"crl\"]},\"application/pkix-pkipath\":{\"source\":\"iana\",\"extensions\":[\"pkipath\"]},\"application/pkixcmp\":{\"source\":\"iana\",\"extensions\":[\"pki\"]},\"application/pls+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"pls\"]},\"application/poc-settings+xml\":{\"source\":\"iana\",\"charset\":\"UTF-8\",\"compressible\":true},\"application/postscript\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"ai\",\"eps\",\"ps\"]},\"application/ppsp-tracker+json\":{\"source\":\"iana\",\"compressible\":true},\"application/problem+json\":{\"source\":\"iana\",\"compressible\":true},\"application/problem+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/provenance+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"provx\"]},\"application/prs.alvestrand.titrax-sheet\":{\"source\":\"iana\"},\"application/prs.cww\":{\"source\":\"iana\",\"extensions\":[\"cww\"]},\"application/prs.hpub+zip\":{\"source\":\"iana\",\"compressible\":false},\"application/prs.nprend\":{\"source\":\"iana\"},\"application/prs.plucker\":{\"source\":\"iana\"},\"application/prs.rdf-xml-crypt\":{\"source\":\"iana\"},\"application/prs.xsf+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/pskc+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"pskcxml\"]},\"application/pvd+json\":{\"source\":\"iana\",\"compressible\":true},\"application/qsig\":{\"source\":\"iana\"},\"application/raml+yaml\":{\"compressible\":true,\"extensions\":[\"raml\"]},\"application/raptorfec\":{\"source\":\"iana\"},\"application/rdap+json\":{\"source\":\"iana\",\"compressible\":true},\"application/rdf+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"rdf\",\"owl\"]},\"application/reginfo+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"rif\"]},\"application/relax-ng-compact-syntax\":{\"source\":\"iana\",\"extensions\":[\"rnc\"]},\"application/remote-printing\":{\"source\":\"iana\"},\"application/reputon+json\":{\"source\":\"iana\",\"compressible\":true},\"application/resource-lists+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"rl\"]},\"application/resource-lists-diff+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"rld\"]},\"application/rfc+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/riscos\":{\"source\":\"iana\"},\"application/rlmi+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/rls-services+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"rs\"]},\"application/route-apd+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"rapd\"]},\"application/route-s-tsid+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"sls\"]},\"application/route-usd+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"rusd\"]},\"application/rpki-ghostbusters\":{\"source\":\"iana\",\"extensions\":[\"gbr\"]},\"application/rpki-manifest\":{\"source\":\"iana\",\"extensions\":[\"mft\"]},\"application/rpki-publication\":{\"source\":\"iana\"},\"application/rpki-roa\":{\"source\":\"iana\",\"extensions\":[\"roa\"]},\"application/rpki-updown\":{\"source\":\"iana\"},\"application/rsd+xml\":{\"source\":\"apache\",\"compressible\":true,\"extensions\":[\"rsd\"]},\"application/rss+xml\":{\"source\":\"apache\",\"compressible\":true,\"extensions\":[\"rss\"]},\"application/rtf\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"rtf\"]},\"application/rtploopback\":{\"source\":\"iana\"},\"application/rtx\":{\"source\":\"iana\"},\"application/samlassertion+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/samlmetadata+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/sbe\":{\"source\":\"iana\"},\"application/sbml+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"sbml\"]},\"application/scaip+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/scim+json\":{\"source\":\"iana\",\"compressible\":true},\"application/scvp-cv-request\":{\"source\":\"iana\",\"extensions\":[\"scq\"]},\"application/scvp-cv-response\":{\"source\":\"iana\",\"extensions\":[\"scs\"]},\"application/scvp-vp-request\":{\"source\":\"iana\",\"extensions\":[\"spq\"]},\"application/scvp-vp-response\":{\"source\":\"iana\",\"extensions\":[\"spp\"]},\"application/sdp\":{\"source\":\"iana\",\"extensions\":[\"sdp\"]},\"application/secevent+jwt\":{\"source\":\"iana\"},\"application/senml+cbor\":{\"source\":\"iana\"},\"application/senml+json\":{\"source\":\"iana\",\"compressible\":true},\"application/senml+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"senmlx\"]},\"application/senml-etch+cbor\":{\"source\":\"iana\"},\"application/senml-etch+json\":{\"source\":\"iana\",\"compressible\":true},\"application/senml-exi\":{\"source\":\"iana\"},\"application/sensml+cbor\":{\"source\":\"iana\"},\"application/sensml+json\":{\"source\":\"iana\",\"compressible\":true},\"application/sensml+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"sensmlx\"]},\"application/sensml-exi\":{\"source\":\"iana\"},\"application/sep+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/sep-exi\":{\"source\":\"iana\"},\"application/session-info\":{\"source\":\"iana\"},\"application/set-payment\":{\"source\":\"iana\"},\"application/set-payment-initiation\":{\"source\":\"iana\",\"extensions\":[\"setpay\"]},\"application/set-registration\":{\"source\":\"iana\"},\"application/set-registration-initiation\":{\"source\":\"iana\",\"extensions\":[\"setreg\"]},\"application/sgml\":{\"source\":\"iana\"},\"application/sgml-open-catalog\":{\"source\":\"iana\"},\"application/shf+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"shf\"]},\"application/sieve\":{\"source\":\"iana\",\"extensions\":[\"siv\",\"sieve\"]},\"application/simple-filter+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/simple-message-summary\":{\"source\":\"iana\"},\"application/simplesymbolcontainer\":{\"source\":\"iana\"},\"application/sipc\":{\"source\":\"iana\"},\"application/slate\":{\"source\":\"iana\"},\"application/smil\":{\"source\":\"iana\"},\"application/smil+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"smi\",\"smil\"]},\"application/smpte336m\":{\"source\":\"iana\"},\"application/soap+fastinfoset\":{\"source\":\"iana\"},\"application/soap+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/sparql-query\":{\"source\":\"iana\",\"extensions\":[\"rq\"]},\"application/sparql-results+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"srx\"]},\"application/spirits-event+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/sql\":{\"source\":\"iana\"},\"application/srgs\":{\"source\":\"iana\",\"extensions\":[\"gram\"]},\"application/srgs+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"grxml\"]},\"application/sru+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"sru\"]},\"application/ssdl+xml\":{\"source\":\"apache\",\"compressible\":true,\"extensions\":[\"ssdl\"]},\"application/ssml+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"ssml\"]},\"application/stix+json\":{\"source\":\"iana\",\"compressible\":true},\"application/swid+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"swidtag\"]},\"application/tamp-apex-update\":{\"source\":\"iana\"},\"application/tamp-apex-update-confirm\":{\"source\":\"iana\"},\"application/tamp-community-update\":{\"source\":\"iana\"},\"application/tamp-community-update-confirm\":{\"source\":\"iana\"},\"application/tamp-error\":{\"source\":\"iana\"},\"application/tamp-sequence-adjust\":{\"source\":\"iana\"},\"application/tamp-sequence-adjust-confirm\":{\"source\":\"iana\"},\"application/tamp-status-query\":{\"source\":\"iana\"},\"application/tamp-status-response\":{\"source\":\"iana\"},\"application/tamp-update\":{\"source\":\"iana\"},\"application/tamp-update-confirm\":{\"source\":\"iana\"},\"application/tar\":{\"compressible\":true},\"application/taxii+json\":{\"source\":\"iana\",\"compressible\":true},\"application/td+json\":{\"source\":\"iana\",\"compressible\":true},\"application/tei+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"tei\",\"teicorpus\"]},\"application/tetra_isi\":{\"source\":\"iana\"},\"application/thraud+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"tfi\"]},\"application/timestamp-query\":{\"source\":\"iana\"},\"application/timestamp-reply\":{\"source\":\"iana\"},\"application/timestamped-data\":{\"source\":\"iana\",\"extensions\":[\"tsd\"]},\"application/tlsrpt+gzip\":{\"source\":\"iana\"},\"application/tlsrpt+json\":{\"source\":\"iana\",\"compressible\":true},\"application/tnauthlist\":{\"source\":\"iana\"},\"application/toml\":{\"compressible\":true,\"extensions\":[\"toml\"]},\"application/trickle-ice-sdpfrag\":{\"source\":\"iana\"},\"application/trig\":{\"source\":\"iana\"},\"application/ttml+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"ttml\"]},\"application/tve-trigger\":{\"source\":\"iana\"},\"application/tzif\":{\"source\":\"iana\"},\"application/tzif-leap\":{\"source\":\"iana\"},\"application/ulpfec\":{\"source\":\"iana\"},\"application/urc-grpsheet+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/urc-ressheet+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"rsheet\"]},\"application/urc-targetdesc+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/urc-uisocketdesc+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vcard+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vcard+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vemmi\":{\"source\":\"iana\"},\"application/vividence.scriptfile\":{\"source\":\"apache\"},\"application/vnd.1000minds.decision-model+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"1km\"]},\"application/vnd.3gpp-prose+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp-prose-pc3ch+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp-v2x-local-service-information\":{\"source\":\"iana\"},\"application/vnd.3gpp.access-transfer-events+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.bsf+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.gmop+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.mc-signalling-ear\":{\"source\":\"iana\"},\"application/vnd.3gpp.mcdata-affiliation-command+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.mcdata-info+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.mcdata-payload\":{\"source\":\"iana\"},\"application/vnd.3gpp.mcdata-service-config+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.mcdata-signalling\":{\"source\":\"iana\"},\"application/vnd.3gpp.mcdata-ue-config+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.mcdata-user-profile+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.mcptt-affiliation-command+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.mcptt-floor-request+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.mcptt-info+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.mcptt-location-info+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.mcptt-mbms-usage-info+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.mcptt-service-config+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.mcptt-signed+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.mcptt-ue-config+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.mcptt-ue-init-config+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.mcptt-user-profile+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.mcvideo-affiliation-command+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.mcvideo-affiliation-info+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.mcvideo-info+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.mcvideo-location-info+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.mcvideo-mbms-usage-info+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.mcvideo-service-config+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.mcvideo-transmission-request+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.mcvideo-ue-config+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.mcvideo-user-profile+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.mid-call+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.pic-bw-large\":{\"source\":\"iana\",\"extensions\":[\"plb\"]},\"application/vnd.3gpp.pic-bw-small\":{\"source\":\"iana\",\"extensions\":[\"psb\"]},\"application/vnd.3gpp.pic-bw-var\":{\"source\":\"iana\",\"extensions\":[\"pvb\"]},\"application/vnd.3gpp.sms\":{\"source\":\"iana\"},\"application/vnd.3gpp.sms+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.srvcc-ext+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.srvcc-info+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.state-and-event-info+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp.ussd+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp2.bcmcsinfo+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.3gpp2.sms\":{\"source\":\"iana\"},\"application/vnd.3gpp2.tcap\":{\"source\":\"iana\",\"extensions\":[\"tcap\"]},\"application/vnd.3lightssoftware.imagescal\":{\"source\":\"iana\"},\"application/vnd.3m.post-it-notes\":{\"source\":\"iana\",\"extensions\":[\"pwn\"]},\"application/vnd.accpac.simply.aso\":{\"source\":\"iana\",\"extensions\":[\"aso\"]},\"application/vnd.accpac.simply.imp\":{\"source\":\"iana\",\"extensions\":[\"imp\"]},\"application/vnd.acucobol\":{\"source\":\"iana\",\"extensions\":[\"acu\"]},\"application/vnd.acucorp\":{\"source\":\"iana\",\"extensions\":[\"atc\",\"acutc\"]},\"application/vnd.adobe.air-application-installer-package+zip\":{\"source\":\"apache\",\"compressible\":false,\"extensions\":[\"air\"]},\"application/vnd.adobe.flash.movie\":{\"source\":\"iana\"},\"application/vnd.adobe.formscentral.fcdt\":{\"source\":\"iana\",\"extensions\":[\"fcdt\"]},\"application/vnd.adobe.fxp\":{\"source\":\"iana\",\"extensions\":[\"fxp\",\"fxpl\"]},\"application/vnd.adobe.partial-upload\":{\"source\":\"iana\"},\"application/vnd.adobe.xdp+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"xdp\"]},\"application/vnd.adobe.xfdf\":{\"source\":\"iana\",\"extensions\":[\"xfdf\"]},\"application/vnd.aether.imp\":{\"source\":\"iana\"},\"application/vnd.afpc.afplinedata\":{\"source\":\"iana\"},\"application/vnd.afpc.afplinedata-pagedef\":{\"source\":\"iana\"},\"application/vnd.afpc.foca-charset\":{\"source\":\"iana\"},\"application/vnd.afpc.foca-codedfont\":{\"source\":\"iana\"},\"application/vnd.afpc.foca-codepage\":{\"source\":\"iana\"},\"application/vnd.afpc.modca\":{\"source\":\"iana\"},\"application/vnd.afpc.modca-formdef\":{\"source\":\"iana\"},\"application/vnd.afpc.modca-mediummap\":{\"source\":\"iana\"},\"application/vnd.afpc.modca-objectcontainer\":{\"source\":\"iana\"},\"application/vnd.afpc.modca-overlay\":{\"source\":\"iana\"},\"application/vnd.afpc.modca-pagesegment\":{\"source\":\"iana\"},\"application/vnd.ah-barcode\":{\"source\":\"iana\"},\"application/vnd.ahead.space\":{\"source\":\"iana\",\"extensions\":[\"ahead\"]},\"application/vnd.airzip.filesecure.azf\":{\"source\":\"iana\",\"extensions\":[\"azf\"]},\"application/vnd.airzip.filesecure.azs\":{\"source\":\"iana\",\"extensions\":[\"azs\"]},\"application/vnd.amadeus+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.amazon.ebook\":{\"source\":\"apache\",\"extensions\":[\"azw\"]},\"application/vnd.amazon.mobi8-ebook\":{\"source\":\"iana\"},\"application/vnd.americandynamics.acc\":{\"source\":\"iana\",\"extensions\":[\"acc\"]},\"application/vnd.amiga.ami\":{\"source\":\"iana\",\"extensions\":[\"ami\"]},\"application/vnd.amundsen.maze+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.android.ota\":{\"source\":\"iana\"},\"application/vnd.android.package-archive\":{\"source\":\"apache\",\"compressible\":false,\"extensions\":[\"apk\"]},\"application/vnd.anki\":{\"source\":\"iana\"},\"application/vnd.anser-web-certificate-issue-initiation\":{\"source\":\"iana\",\"extensions\":[\"cii\"]},\"application/vnd.anser-web-funds-transfer-initiation\":{\"source\":\"apache\",\"extensions\":[\"fti\"]},\"application/vnd.antix.game-component\":{\"source\":\"iana\",\"extensions\":[\"atx\"]},\"application/vnd.apache.thrift.binary\":{\"source\":\"iana\"},\"application/vnd.apache.thrift.compact\":{\"source\":\"iana\"},\"application/vnd.apache.thrift.json\":{\"source\":\"iana\"},\"application/vnd.api+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.aplextor.warrp+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.apothekende.reservation+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.apple.installer+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"mpkg\"]},\"application/vnd.apple.keynote\":{\"source\":\"iana\",\"extensions\":[\"keynote\"]},\"application/vnd.apple.mpegurl\":{\"source\":\"iana\",\"extensions\":[\"m3u8\"]},\"application/vnd.apple.numbers\":{\"source\":\"iana\",\"extensions\":[\"numbers\"]},\"application/vnd.apple.pages\":{\"source\":\"iana\",\"extensions\":[\"pages\"]},\"application/vnd.apple.pkpass\":{\"compressible\":false,\"extensions\":[\"pkpass\"]},\"application/vnd.arastra.swi\":{\"source\":\"iana\"},\"application/vnd.aristanetworks.swi\":{\"source\":\"iana\",\"extensions\":[\"swi\"]},\"application/vnd.artisan+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.artsquare\":{\"source\":\"iana\"},\"application/vnd.astraea-software.iota\":{\"source\":\"iana\",\"extensions\":[\"iota\"]},\"application/vnd.audiograph\":{\"source\":\"iana\",\"extensions\":[\"aep\"]},\"application/vnd.autopackage\":{\"source\":\"iana\"},\"application/vnd.avalon+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.avistar+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.balsamiq.bmml+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"bmml\"]},\"application/vnd.balsamiq.bmpr\":{\"source\":\"iana\"},\"application/vnd.banana-accounting\":{\"source\":\"iana\"},\"application/vnd.bbf.usp.error\":{\"source\":\"iana\"},\"application/vnd.bbf.usp.msg\":{\"source\":\"iana\"},\"application/vnd.bbf.usp.msg+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.bekitzur-stech+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.bint.med-content\":{\"source\":\"iana\"},\"application/vnd.biopax.rdf+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.blink-idb-value-wrapper\":{\"source\":\"iana\"},\"application/vnd.blueice.multipass\":{\"source\":\"iana\",\"extensions\":[\"mpm\"]},\"application/vnd.bluetooth.ep.oob\":{\"source\":\"iana\"},\"application/vnd.bluetooth.le.oob\":{\"source\":\"iana\"},\"application/vnd.bmi\":{\"source\":\"iana\",\"extensions\":[\"bmi\"]},\"application/vnd.bpf\":{\"source\":\"iana\"},\"application/vnd.bpf3\":{\"source\":\"iana\"},\"application/vnd.businessobjects\":{\"source\":\"iana\",\"extensions\":[\"rep\"]},\"application/vnd.byu.uapi+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.cab-jscript\":{\"source\":\"iana\"},\"application/vnd.canon-cpdl\":{\"source\":\"iana\"},\"application/vnd.canon-lips\":{\"source\":\"iana\"},\"application/vnd.capasystems-pg+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.cendio.thinlinc.clientconf\":{\"source\":\"iana\"},\"application/vnd.century-systems.tcp_stream\":{\"source\":\"iana\"},\"application/vnd.chemdraw+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"cdxml\"]},\"application/vnd.chess-pgn\":{\"source\":\"iana\"},\"application/vnd.chipnuts.karaoke-mmd\":{\"source\":\"iana\",\"extensions\":[\"mmd\"]},\"application/vnd.ciedi\":{\"source\":\"iana\"},\"application/vnd.cinderella\":{\"source\":\"iana\",\"extensions\":[\"cdy\"]},\"application/vnd.cirpack.isdn-ext\":{\"source\":\"iana\"},\"application/vnd.citationstyles.style+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"csl\"]},\"application/vnd.claymore\":{\"source\":\"iana\",\"extensions\":[\"cla\"]},\"application/vnd.cloanto.rp9\":{\"source\":\"iana\",\"extensions\":[\"rp9\"]},\"application/vnd.clonk.c4group\":{\"source\":\"iana\",\"extensions\":[\"c4g\",\"c4d\",\"c4f\",\"c4p\",\"c4u\"]},\"application/vnd.cluetrust.cartomobile-config\":{\"source\":\"iana\",\"extensions\":[\"c11amc\"]},\"application/vnd.cluetrust.cartomobile-config-pkg\":{\"source\":\"iana\",\"extensions\":[\"c11amz\"]},\"application/vnd.coffeescript\":{\"source\":\"iana\"},\"application/vnd.collabio.xodocuments.document\":{\"source\":\"iana\"},\"application/vnd.collabio.xodocuments.document-template\":{\"source\":\"iana\"},\"application/vnd.collabio.xodocuments.presentation\":{\"source\":\"iana\"},\"application/vnd.collabio.xodocuments.presentation-template\":{\"source\":\"iana\"},\"application/vnd.collabio.xodocuments.spreadsheet\":{\"source\":\"iana\"},\"application/vnd.collabio.xodocuments.spreadsheet-template\":{\"source\":\"iana\"},\"application/vnd.collection+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.collection.doc+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.collection.next+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.comicbook+zip\":{\"source\":\"iana\",\"compressible\":false},\"application/vnd.comicbook-rar\":{\"source\":\"iana\"},\"application/vnd.commerce-battelle\":{\"source\":\"iana\"},\"application/vnd.commonspace\":{\"source\":\"iana\",\"extensions\":[\"csp\"]},\"application/vnd.contact.cmsg\":{\"source\":\"iana\",\"extensions\":[\"cdbcmsg\"]},\"application/vnd.coreos.ignition+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.cosmocaller\":{\"source\":\"iana\",\"extensions\":[\"cmc\"]},\"application/vnd.crick.clicker\":{\"source\":\"iana\",\"extensions\":[\"clkx\"]},\"application/vnd.crick.clicker.keyboard\":{\"source\":\"iana\",\"extensions\":[\"clkk\"]},\"application/vnd.crick.clicker.palette\":{\"source\":\"iana\",\"extensions\":[\"clkp\"]},\"application/vnd.crick.clicker.template\":{\"source\":\"iana\",\"extensions\":[\"clkt\"]},\"application/vnd.crick.clicker.wordbank\":{\"source\":\"iana\",\"extensions\":[\"clkw\"]},\"application/vnd.criticaltools.wbs+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"wbs\"]},\"application/vnd.cryptii.pipe+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.crypto-shade-file\":{\"source\":\"iana\"},\"application/vnd.ctc-posml\":{\"source\":\"iana\",\"extensions\":[\"pml\"]},\"application/vnd.ctct.ws+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.cups-pdf\":{\"source\":\"iana\"},\"application/vnd.cups-postscript\":{\"source\":\"iana\"},\"application/vnd.cups-ppd\":{\"source\":\"iana\",\"extensions\":[\"ppd\"]},\"application/vnd.cups-raster\":{\"source\":\"iana\"},\"application/vnd.cups-raw\":{\"source\":\"iana\"},\"application/vnd.curl\":{\"source\":\"iana\"},\"application/vnd.curl.car\":{\"source\":\"apache\",\"extensions\":[\"car\"]},\"application/vnd.curl.pcurl\":{\"source\":\"apache\",\"extensions\":[\"pcurl\"]},\"application/vnd.cyan.dean.root+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.cybank\":{\"source\":\"iana\"},\"application/vnd.d2l.coursepackage1p0+zip\":{\"source\":\"iana\",\"compressible\":false},\"application/vnd.dart\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"dart\"]},\"application/vnd.data-vision.rdz\":{\"source\":\"iana\",\"extensions\":[\"rdz\"]},\"application/vnd.datapackage+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.dataresource+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.dbf\":{\"source\":\"iana\"},\"application/vnd.debian.binary-package\":{\"source\":\"iana\"},\"application/vnd.dece.data\":{\"source\":\"iana\",\"extensions\":[\"uvf\",\"uvvf\",\"uvd\",\"uvvd\"]},\"application/vnd.dece.ttml+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"uvt\",\"uvvt\"]},\"application/vnd.dece.unspecified\":{\"source\":\"iana\",\"extensions\":[\"uvx\",\"uvvx\"]},\"application/vnd.dece.zip\":{\"source\":\"iana\",\"extensions\":[\"uvz\",\"uvvz\"]},\"application/vnd.denovo.fcselayout-link\":{\"source\":\"iana\",\"extensions\":[\"fe_launch\"]},\"application/vnd.desmume.movie\":{\"source\":\"iana\"},\"application/vnd.dir-bi.plate-dl-nosuffix\":{\"source\":\"iana\"},\"application/vnd.dm.delegation+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.dna\":{\"source\":\"iana\",\"extensions\":[\"dna\"]},\"application/vnd.document+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.dolby.mlp\":{\"source\":\"apache\",\"extensions\":[\"mlp\"]},\"application/vnd.dolby.mobile.1\":{\"source\":\"iana\"},\"application/vnd.dolby.mobile.2\":{\"source\":\"iana\"},\"application/vnd.doremir.scorecloud-binary-document\":{\"source\":\"iana\"},\"application/vnd.dpgraph\":{\"source\":\"iana\",\"extensions\":[\"dpg\"]},\"application/vnd.dreamfactory\":{\"source\":\"iana\",\"extensions\":[\"dfac\"]},\"application/vnd.drive+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.ds-keypoint\":{\"source\":\"apache\",\"extensions\":[\"kpxx\"]},\"application/vnd.dtg.local\":{\"source\":\"iana\"},\"application/vnd.dtg.local.flash\":{\"source\":\"iana\"},\"application/vnd.dtg.local.html\":{\"source\":\"iana\"},\"application/vnd.dvb.ait\":{\"source\":\"iana\",\"extensions\":[\"ait\"]},\"application/vnd.dvb.dvbisl+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.dvb.dvbj\":{\"source\":\"iana\"},\"application/vnd.dvb.esgcontainer\":{\"source\":\"iana\"},\"application/vnd.dvb.ipdcdftnotifaccess\":{\"source\":\"iana\"},\"application/vnd.dvb.ipdcesgaccess\":{\"source\":\"iana\"},\"application/vnd.dvb.ipdcesgaccess2\":{\"source\":\"iana\"},\"application/vnd.dvb.ipdcesgpdd\":{\"source\":\"iana\"},\"application/vnd.dvb.ipdcroaming\":{\"source\":\"iana\"},\"application/vnd.dvb.iptv.alfec-base\":{\"source\":\"iana\"},\"application/vnd.dvb.iptv.alfec-enhancement\":{\"source\":\"iana\"},\"application/vnd.dvb.notif-aggregate-root+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.dvb.notif-container+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.dvb.notif-generic+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.dvb.notif-ia-msglist+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.dvb.notif-ia-registration-request+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.dvb.notif-ia-registration-response+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.dvb.notif-init+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.dvb.pfr\":{\"source\":\"iana\"},\"application/vnd.dvb.service\":{\"source\":\"iana\",\"extensions\":[\"svc\"]},\"application/vnd.dxr\":{\"source\":\"iana\"},\"application/vnd.dynageo\":{\"source\":\"iana\",\"extensions\":[\"geo\"]},\"application/vnd.dzr\":{\"source\":\"iana\"},\"application/vnd.easykaraoke.cdgdownload\":{\"source\":\"iana\"},\"application/vnd.ecdis-update\":{\"source\":\"iana\"},\"application/vnd.ecip.rlp\":{\"source\":\"iana\"},\"application/vnd.ecowin.chart\":{\"source\":\"iana\",\"extensions\":[\"mag\"]},\"application/vnd.ecowin.filerequest\":{\"source\":\"iana\"},\"application/vnd.ecowin.fileupdate\":{\"source\":\"iana\"},\"application/vnd.ecowin.series\":{\"source\":\"iana\"},\"application/vnd.ecowin.seriesrequest\":{\"source\":\"iana\"},\"application/vnd.ecowin.seriesupdate\":{\"source\":\"iana\"},\"application/vnd.efi.img\":{\"source\":\"iana\"},\"application/vnd.efi.iso\":{\"source\":\"iana\"},\"application/vnd.emclient.accessrequest+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.enliven\":{\"source\":\"iana\",\"extensions\":[\"nml\"]},\"application/vnd.enphase.envoy\":{\"source\":\"iana\"},\"application/vnd.eprints.data+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.epson.esf\":{\"source\":\"iana\",\"extensions\":[\"esf\"]},\"application/vnd.epson.msf\":{\"source\":\"iana\",\"extensions\":[\"msf\"]},\"application/vnd.epson.quickanime\":{\"source\":\"iana\",\"extensions\":[\"qam\"]},\"application/vnd.epson.salt\":{\"source\":\"iana\",\"extensions\":[\"slt\"]},\"application/vnd.epson.ssf\":{\"source\":\"iana\",\"extensions\":[\"ssf\"]},\"application/vnd.ericsson.quickcall\":{\"source\":\"iana\"},\"application/vnd.espass-espass+zip\":{\"source\":\"iana\",\"compressible\":false},\"application/vnd.eszigno3+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"es3\",\"et3\"]},\"application/vnd.etsi.aoc+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.etsi.asic-e+zip\":{\"source\":\"iana\",\"compressible\":false},\"application/vnd.etsi.asic-s+zip\":{\"source\":\"iana\",\"compressible\":false},\"application/vnd.etsi.cug+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.etsi.iptvcommand+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.etsi.iptvdiscovery+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.etsi.iptvprofile+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.etsi.iptvsad-bc+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.etsi.iptvsad-cod+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.etsi.iptvsad-npvr+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.etsi.iptvservice+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.etsi.iptvsync+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.etsi.iptvueprofile+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.etsi.mcid+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.etsi.mheg5\":{\"source\":\"iana\"},\"application/vnd.etsi.overload-control-policy-dataset+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.etsi.pstn+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.etsi.sci+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.etsi.simservs+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.etsi.timestamp-token\":{\"source\":\"iana\"},\"application/vnd.etsi.tsl+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.etsi.tsl.der\":{\"source\":\"iana\"},\"application/vnd.eudora.data\":{\"source\":\"iana\"},\"application/vnd.evolv.ecig.profile\":{\"source\":\"iana\"},\"application/vnd.evolv.ecig.settings\":{\"source\":\"iana\"},\"application/vnd.evolv.ecig.theme\":{\"source\":\"iana\"},\"application/vnd.exstream-empower+zip\":{\"source\":\"iana\",\"compressible\":false},\"application/vnd.exstream-package\":{\"source\":\"iana\"},\"application/vnd.ezpix-album\":{\"source\":\"iana\",\"extensions\":[\"ez2\"]},\"application/vnd.ezpix-package\":{\"source\":\"iana\",\"extensions\":[\"ez3\"]},\"application/vnd.f-secure.mobile\":{\"source\":\"iana\"},\"application/vnd.fastcopy-disk-image\":{\"source\":\"iana\"},\"application/vnd.fdf\":{\"source\":\"iana\",\"extensions\":[\"fdf\"]},\"application/vnd.fdsn.mseed\":{\"source\":\"iana\",\"extensions\":[\"mseed\"]},\"application/vnd.fdsn.seed\":{\"source\":\"iana\",\"extensions\":[\"seed\",\"dataless\"]},\"application/vnd.ffsns\":{\"source\":\"iana\"},\"application/vnd.ficlab.flb+zip\":{\"source\":\"iana\",\"compressible\":false},\"application/vnd.filmit.zfc\":{\"source\":\"iana\"},\"application/vnd.fints\":{\"source\":\"iana\"},\"application/vnd.firemonkeys.cloudcell\":{\"source\":\"iana\"},\"application/vnd.flographit\":{\"source\":\"iana\",\"extensions\":[\"gph\"]},\"application/vnd.fluxtime.clip\":{\"source\":\"iana\",\"extensions\":[\"ftc\"]},\"application/vnd.font-fontforge-sfd\":{\"source\":\"iana\"},\"application/vnd.framemaker\":{\"source\":\"iana\",\"extensions\":[\"fm\",\"frame\",\"maker\",\"book\"]},\"application/vnd.frogans.fnc\":{\"source\":\"iana\",\"extensions\":[\"fnc\"]},\"application/vnd.frogans.ltf\":{\"source\":\"iana\",\"extensions\":[\"ltf\"]},\"application/vnd.fsc.weblaunch\":{\"source\":\"iana\",\"extensions\":[\"fsc\"]},\"application/vnd.fujitsu.oasys\":{\"source\":\"iana\",\"extensions\":[\"oas\"]},\"application/vnd.fujitsu.oasys2\":{\"source\":\"iana\",\"extensions\":[\"oa2\"]},\"application/vnd.fujitsu.oasys3\":{\"source\":\"iana\",\"extensions\":[\"oa3\"]},\"application/vnd.fujitsu.oasysgp\":{\"source\":\"iana\",\"extensions\":[\"fg5\"]},\"application/vnd.fujitsu.oasysprs\":{\"source\":\"iana\",\"extensions\":[\"bh2\"]},\"application/vnd.fujixerox.art-ex\":{\"source\":\"iana\"},\"application/vnd.fujixerox.art4\":{\"source\":\"iana\"},\"application/vnd.fujixerox.ddd\":{\"source\":\"iana\",\"extensions\":[\"ddd\"]},\"application/vnd.fujixerox.docuworks\":{\"source\":\"iana\",\"extensions\":[\"xdw\"]},\"application/vnd.fujixerox.docuworks.binder\":{\"source\":\"iana\",\"extensions\":[\"xbd\"]},\"application/vnd.fujixerox.docuworks.container\":{\"source\":\"iana\"},\"application/vnd.fujixerox.hbpl\":{\"source\":\"iana\"},\"application/vnd.fut-misnet\":{\"source\":\"iana\"},\"application/vnd.futoin+cbor\":{\"source\":\"iana\"},\"application/vnd.futoin+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.fuzzysheet\":{\"source\":\"iana\",\"extensions\":[\"fzs\"]},\"application/vnd.genomatix.tuxedo\":{\"source\":\"iana\",\"extensions\":[\"txd\"]},\"application/vnd.gentics.grd+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.geo+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.geocube+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.geogebra.file\":{\"source\":\"iana\",\"extensions\":[\"ggb\"]},\"application/vnd.geogebra.tool\":{\"source\":\"iana\",\"extensions\":[\"ggt\"]},\"application/vnd.geometry-explorer\":{\"source\":\"iana\",\"extensions\":[\"gex\",\"gre\"]},\"application/vnd.geonext\":{\"source\":\"iana\",\"extensions\":[\"gxt\"]},\"application/vnd.geoplan\":{\"source\":\"iana\",\"extensions\":[\"g2w\"]},\"application/vnd.geospace\":{\"source\":\"iana\",\"extensions\":[\"g3w\"]},\"application/vnd.gerber\":{\"source\":\"iana\"},\"application/vnd.globalplatform.card-content-mgt\":{\"source\":\"iana\"},\"application/vnd.globalplatform.card-content-mgt-response\":{\"source\":\"iana\"},\"application/vnd.gmx\":{\"source\":\"iana\",\"extensions\":[\"gmx\"]},\"application/vnd.google-apps.document\":{\"compressible\":false,\"extensions\":[\"gdoc\"]},\"application/vnd.google-apps.presentation\":{\"compressible\":false,\"extensions\":[\"gslides\"]},\"application/vnd.google-apps.spreadsheet\":{\"compressible\":false,\"extensions\":[\"gsheet\"]},\"application/vnd.google-earth.kml+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"kml\"]},\"application/vnd.google-earth.kmz\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"kmz\"]},\"application/vnd.gov.sk.e-form+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.gov.sk.e-form+zip\":{\"source\":\"iana\",\"compressible\":false},\"application/vnd.gov.sk.xmldatacontainer+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.grafeq\":{\"source\":\"iana\",\"extensions\":[\"gqf\",\"gqs\"]},\"application/vnd.gridmp\":{\"source\":\"iana\"},\"application/vnd.groove-account\":{\"source\":\"iana\",\"extensions\":[\"gac\"]},\"application/vnd.groove-help\":{\"source\":\"iana\",\"extensions\":[\"ghf\"]},\"application/vnd.groove-identity-message\":{\"source\":\"iana\",\"extensions\":[\"gim\"]},\"application/vnd.groove-injector\":{\"source\":\"iana\",\"extensions\":[\"grv\"]},\"application/vnd.groove-tool-message\":{\"source\":\"iana\",\"extensions\":[\"gtm\"]},\"application/vnd.groove-tool-template\":{\"source\":\"iana\",\"extensions\":[\"tpl\"]},\"application/vnd.groove-vcard\":{\"source\":\"iana\",\"extensions\":[\"vcg\"]},\"application/vnd.hal+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.hal+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"hal\"]},\"application/vnd.handheld-entertainment+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"zmm\"]},\"application/vnd.hbci\":{\"source\":\"iana\",\"extensions\":[\"hbci\"]},\"application/vnd.hc+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.hcl-bireports\":{\"source\":\"iana\"},\"application/vnd.hdt\":{\"source\":\"iana\"},\"application/vnd.heroku+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.hhe.lesson-player\":{\"source\":\"iana\",\"extensions\":[\"les\"]},\"application/vnd.hp-hpgl\":{\"source\":\"iana\",\"extensions\":[\"hpgl\"]},\"application/vnd.hp-hpid\":{\"source\":\"iana\",\"extensions\":[\"hpid\"]},\"application/vnd.hp-hps\":{\"source\":\"iana\",\"extensions\":[\"hps\"]},\"application/vnd.hp-jlyt\":{\"source\":\"iana\",\"extensions\":[\"jlt\"]},\"application/vnd.hp-pcl\":{\"source\":\"iana\",\"extensions\":[\"pcl\"]},\"application/vnd.hp-pclxl\":{\"source\":\"iana\",\"extensions\":[\"pclxl\"]},\"application/vnd.httphone\":{\"source\":\"iana\"},\"application/vnd.hydrostatix.sof-data\":{\"source\":\"iana\",\"extensions\":[\"sfd-hdstx\"]},\"application/vnd.hyper+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.hyper-item+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.hyperdrive+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.hzn-3d-crossword\":{\"source\":\"iana\"},\"application/vnd.ibm.afplinedata\":{\"source\":\"iana\"},\"application/vnd.ibm.electronic-media\":{\"source\":\"iana\"},\"application/vnd.ibm.minipay\":{\"source\":\"iana\",\"extensions\":[\"mpy\"]},\"application/vnd.ibm.modcap\":{\"source\":\"iana\",\"extensions\":[\"afp\",\"listafp\",\"list3820\"]},\"application/vnd.ibm.rights-management\":{\"source\":\"iana\",\"extensions\":[\"irm\"]},\"application/vnd.ibm.secure-container\":{\"source\":\"iana\",\"extensions\":[\"sc\"]},\"application/vnd.iccprofile\":{\"source\":\"iana\",\"extensions\":[\"icc\",\"icm\"]},\"application/vnd.ieee.1905\":{\"source\":\"iana\"},\"application/vnd.igloader\":{\"source\":\"iana\",\"extensions\":[\"igl\"]},\"application/vnd.imagemeter.folder+zip\":{\"source\":\"iana\",\"compressible\":false},\"application/vnd.imagemeter.image+zip\":{\"source\":\"iana\",\"compressible\":false},\"application/vnd.immervision-ivp\":{\"source\":\"iana\",\"extensions\":[\"ivp\"]},\"application/vnd.immervision-ivu\":{\"source\":\"iana\",\"extensions\":[\"ivu\"]},\"application/vnd.ims.imsccv1p1\":{\"source\":\"iana\"},\"application/vnd.ims.imsccv1p2\":{\"source\":\"iana\"},\"application/vnd.ims.imsccv1p3\":{\"source\":\"iana\"},\"application/vnd.ims.lis.v2.result+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.ims.lti.v2.toolconsumerprofile+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.ims.lti.v2.toolproxy+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.ims.lti.v2.toolproxy.id+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.ims.lti.v2.toolsettings+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.ims.lti.v2.toolsettings.simple+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.informedcontrol.rms+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.informix-visionary\":{\"source\":\"iana\"},\"application/vnd.infotech.project\":{\"source\":\"iana\"},\"application/vnd.infotech.project+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.innopath.wamp.notification\":{\"source\":\"iana\"},\"application/vnd.insors.igm\":{\"source\":\"iana\",\"extensions\":[\"igm\"]},\"application/vnd.intercon.formnet\":{\"source\":\"iana\",\"extensions\":[\"xpw\",\"xpx\"]},\"application/vnd.intergeo\":{\"source\":\"iana\",\"extensions\":[\"i2g\"]},\"application/vnd.intertrust.digibox\":{\"source\":\"iana\"},\"application/vnd.intertrust.nncp\":{\"source\":\"iana\"},\"application/vnd.intu.qbo\":{\"source\":\"iana\",\"extensions\":[\"qbo\"]},\"application/vnd.intu.qfx\":{\"source\":\"iana\",\"extensions\":[\"qfx\"]},\"application/vnd.iptc.g2.catalogitem+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.iptc.g2.conceptitem+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.iptc.g2.knowledgeitem+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.iptc.g2.newsitem+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.iptc.g2.newsmessage+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.iptc.g2.packageitem+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.iptc.g2.planningitem+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.ipunplugged.rcprofile\":{\"source\":\"iana\",\"extensions\":[\"rcprofile\"]},\"application/vnd.irepository.package+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"irp\"]},\"application/vnd.is-xpr\":{\"source\":\"iana\",\"extensions\":[\"xpr\"]},\"application/vnd.isac.fcs\":{\"source\":\"iana\",\"extensions\":[\"fcs\"]},\"application/vnd.iso11783-10+zip\":{\"source\":\"iana\",\"compressible\":false},\"application/vnd.jam\":{\"source\":\"iana\",\"extensions\":[\"jam\"]},\"application/vnd.japannet-directory-service\":{\"source\":\"iana\"},\"application/vnd.japannet-jpnstore-wakeup\":{\"source\":\"iana\"},\"application/vnd.japannet-payment-wakeup\":{\"source\":\"iana\"},\"application/vnd.japannet-registration\":{\"source\":\"iana\"},\"application/vnd.japannet-registration-wakeup\":{\"source\":\"iana\"},\"application/vnd.japannet-setstore-wakeup\":{\"source\":\"iana\"},\"application/vnd.japannet-verification\":{\"source\":\"iana\"},\"application/vnd.japannet-verification-wakeup\":{\"source\":\"iana\"},\"application/vnd.jcp.javame.midlet-rms\":{\"source\":\"iana\",\"extensions\":[\"rms\"]},\"application/vnd.jisp\":{\"source\":\"iana\",\"extensions\":[\"jisp\"]},\"application/vnd.joost.joda-archive\":{\"source\":\"iana\",\"extensions\":[\"joda\"]},\"application/vnd.jsk.isdn-ngn\":{\"source\":\"iana\"},\"application/vnd.kahootz\":{\"source\":\"iana\",\"extensions\":[\"ktz\",\"ktr\"]},\"application/vnd.kde.karbon\":{\"source\":\"iana\",\"extensions\":[\"karbon\"]},\"application/vnd.kde.kchart\":{\"source\":\"iana\",\"extensions\":[\"chrt\"]},\"application/vnd.kde.kformula\":{\"source\":\"iana\",\"extensions\":[\"kfo\"]},\"application/vnd.kde.kivio\":{\"source\":\"iana\",\"extensions\":[\"flw\"]},\"application/vnd.kde.kontour\":{\"source\":\"iana\",\"extensions\":[\"kon\"]},\"application/vnd.kde.kpresenter\":{\"source\":\"iana\",\"extensions\":[\"kpr\",\"kpt\"]},\"application/vnd.kde.kspread\":{\"source\":\"iana\",\"extensions\":[\"ksp\"]},\"application/vnd.kde.kword\":{\"source\":\"iana\",\"extensions\":[\"kwd\",\"kwt\"]},\"application/vnd.kenameaapp\":{\"source\":\"iana\",\"extensions\":[\"htke\"]},\"application/vnd.kidspiration\":{\"source\":\"iana\",\"extensions\":[\"kia\"]},\"application/vnd.kinar\":{\"source\":\"iana\",\"extensions\":[\"kne\",\"knp\"]},\"application/vnd.koan\":{\"source\":\"iana\",\"extensions\":[\"skp\",\"skd\",\"skt\",\"skm\"]},\"application/vnd.kodak-descriptor\":{\"source\":\"iana\",\"extensions\":[\"sse\"]},\"application/vnd.las\":{\"source\":\"iana\"},\"application/vnd.las.las+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.las.las+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"lasxml\"]},\"application/vnd.laszip\":{\"source\":\"iana\"},\"application/vnd.leap+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.liberty-request+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.llamagraphics.life-balance.desktop\":{\"source\":\"iana\",\"extensions\":[\"lbd\"]},\"application/vnd.llamagraphics.life-balance.exchange+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"lbe\"]},\"application/vnd.logipipe.circuit+zip\":{\"source\":\"iana\",\"compressible\":false},\"application/vnd.loom\":{\"source\":\"iana\"},\"application/vnd.lotus-1-2-3\":{\"source\":\"iana\",\"extensions\":[\"123\"]},\"application/vnd.lotus-approach\":{\"source\":\"iana\",\"extensions\":[\"apr\"]},\"application/vnd.lotus-freelance\":{\"source\":\"iana\",\"extensions\":[\"pre\"]},\"application/vnd.lotus-notes\":{\"source\":\"iana\",\"extensions\":[\"nsf\"]},\"application/vnd.lotus-organizer\":{\"source\":\"iana\",\"extensions\":[\"org\"]},\"application/vnd.lotus-screencam\":{\"source\":\"iana\",\"extensions\":[\"scm\"]},\"application/vnd.lotus-wordpro\":{\"source\":\"iana\",\"extensions\":[\"lwp\"]},\"application/vnd.macports.portpkg\":{\"source\":\"iana\",\"extensions\":[\"portpkg\"]},\"application/vnd.mapbox-vector-tile\":{\"source\":\"iana\"},\"application/vnd.marlin.drm.actiontoken+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.marlin.drm.conftoken+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.marlin.drm.license+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.marlin.drm.mdcf\":{\"source\":\"iana\"},\"application/vnd.mason+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.maxmind.maxmind-db\":{\"source\":\"iana\"},\"application/vnd.mcd\":{\"source\":\"iana\",\"extensions\":[\"mcd\"]},\"application/vnd.medcalcdata\":{\"source\":\"iana\",\"extensions\":[\"mc1\"]},\"application/vnd.mediastation.cdkey\":{\"source\":\"iana\",\"extensions\":[\"cdkey\"]},\"application/vnd.meridian-slingshot\":{\"source\":\"iana\"},\"application/vnd.mfer\":{\"source\":\"iana\",\"extensions\":[\"mwf\"]},\"application/vnd.mfmp\":{\"source\":\"iana\",\"extensions\":[\"mfm\"]},\"application/vnd.micro+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.micrografx.flo\":{\"source\":\"iana\",\"extensions\":[\"flo\"]},\"application/vnd.micrografx.igx\":{\"source\":\"iana\",\"extensions\":[\"igx\"]},\"application/vnd.microsoft.portable-executable\":{\"source\":\"iana\"},\"application/vnd.microsoft.windows.thumbnail-cache\":{\"source\":\"iana\"},\"application/vnd.miele+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.mif\":{\"source\":\"iana\",\"extensions\":[\"mif\"]},\"application/vnd.minisoft-hp3000-save\":{\"source\":\"iana\"},\"application/vnd.mitsubishi.misty-guard.trustweb\":{\"source\":\"iana\"},\"application/vnd.mobius.daf\":{\"source\":\"iana\",\"extensions\":[\"daf\"]},\"application/vnd.mobius.dis\":{\"source\":\"iana\",\"extensions\":[\"dis\"]},\"application/vnd.mobius.mbk\":{\"source\":\"iana\",\"extensions\":[\"mbk\"]},\"application/vnd.mobius.mqy\":{\"source\":\"iana\",\"extensions\":[\"mqy\"]},\"application/vnd.mobius.msl\":{\"source\":\"iana\",\"extensions\":[\"msl\"]},\"application/vnd.mobius.plc\":{\"source\":\"iana\",\"extensions\":[\"plc\"]},\"application/vnd.mobius.txf\":{\"source\":\"iana\",\"extensions\":[\"txf\"]},\"application/vnd.mophun.application\":{\"source\":\"iana\",\"extensions\":[\"mpn\"]},\"application/vnd.mophun.certificate\":{\"source\":\"iana\",\"extensions\":[\"mpc\"]},\"application/vnd.motorola.flexsuite\":{\"source\":\"iana\"},\"application/vnd.motorola.flexsuite.adsi\":{\"source\":\"iana\"},\"application/vnd.motorola.flexsuite.fis\":{\"source\":\"iana\"},\"application/vnd.motorola.flexsuite.gotap\":{\"source\":\"iana\"},\"application/vnd.motorola.flexsuite.kmr\":{\"source\":\"iana\"},\"application/vnd.motorola.flexsuite.ttc\":{\"source\":\"iana\"},\"application/vnd.motorola.flexsuite.wem\":{\"source\":\"iana\"},\"application/vnd.motorola.iprm\":{\"source\":\"iana\"},\"application/vnd.mozilla.xul+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"xul\"]},\"application/vnd.ms-3mfdocument\":{\"source\":\"iana\"},\"application/vnd.ms-artgalry\":{\"source\":\"iana\",\"extensions\":[\"cil\"]},\"application/vnd.ms-asf\":{\"source\":\"iana\"},\"application/vnd.ms-cab-compressed\":{\"source\":\"iana\",\"extensions\":[\"cab\"]},\"application/vnd.ms-color.iccprofile\":{\"source\":\"apache\"},\"application/vnd.ms-excel\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"xls\",\"xlm\",\"xla\",\"xlc\",\"xlt\",\"xlw\"]},\"application/vnd.ms-excel.addin.macroenabled.12\":{\"source\":\"iana\",\"extensions\":[\"xlam\"]},\"application/vnd.ms-excel.sheet.binary.macroenabled.12\":{\"source\":\"iana\",\"extensions\":[\"xlsb\"]},\"application/vnd.ms-excel.sheet.macroenabled.12\":{\"source\":\"iana\",\"extensions\":[\"xlsm\"]},\"application/vnd.ms-excel.template.macroenabled.12\":{\"source\":\"iana\",\"extensions\":[\"xltm\"]},\"application/vnd.ms-fontobject\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"eot\"]},\"application/vnd.ms-htmlhelp\":{\"source\":\"iana\",\"extensions\":[\"chm\"]},\"application/vnd.ms-ims\":{\"source\":\"iana\",\"extensions\":[\"ims\"]},\"application/vnd.ms-lrm\":{\"source\":\"iana\",\"extensions\":[\"lrm\"]},\"application/vnd.ms-office.activex+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.ms-officetheme\":{\"source\":\"iana\",\"extensions\":[\"thmx\"]},\"application/vnd.ms-opentype\":{\"source\":\"apache\",\"compressible\":true},\"application/vnd.ms-outlook\":{\"compressible\":false,\"extensions\":[\"msg\"]},\"application/vnd.ms-package.obfuscated-opentype\":{\"source\":\"apache\"},\"application/vnd.ms-pki.seccat\":{\"source\":\"apache\",\"extensions\":[\"cat\"]},\"application/vnd.ms-pki.stl\":{\"source\":\"apache\",\"extensions\":[\"stl\"]},\"application/vnd.ms-playready.initiator+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.ms-powerpoint\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"ppt\",\"pps\",\"pot\"]},\"application/vnd.ms-powerpoint.addin.macroenabled.12\":{\"source\":\"iana\",\"extensions\":[\"ppam\"]},\"application/vnd.ms-powerpoint.presentation.macroenabled.12\":{\"source\":\"iana\",\"extensions\":[\"pptm\"]},\"application/vnd.ms-powerpoint.slide.macroenabled.12\":{\"source\":\"iana\",\"extensions\":[\"sldm\"]},\"application/vnd.ms-powerpoint.slideshow.macroenabled.12\":{\"source\":\"iana\",\"extensions\":[\"ppsm\"]},\"application/vnd.ms-powerpoint.template.macroenabled.12\":{\"source\":\"iana\",\"extensions\":[\"potm\"]},\"application/vnd.ms-printdevicecapabilities+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.ms-printing.printticket+xml\":{\"source\":\"apache\",\"compressible\":true},\"application/vnd.ms-printschematicket+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.ms-project\":{\"source\":\"iana\",\"extensions\":[\"mpp\",\"mpt\"]},\"application/vnd.ms-tnef\":{\"source\":\"iana\"},\"application/vnd.ms-windows.devicepairing\":{\"source\":\"iana\"},\"application/vnd.ms-windows.nwprinting.oob\":{\"source\":\"iana\"},\"application/vnd.ms-windows.printerpairing\":{\"source\":\"iana\"},\"application/vnd.ms-windows.wsd.oob\":{\"source\":\"iana\"},\"application/vnd.ms-wmdrm.lic-chlg-req\":{\"source\":\"iana\"},\"application/vnd.ms-wmdrm.lic-resp\":{\"source\":\"iana\"},\"application/vnd.ms-wmdrm.meter-chlg-req\":{\"source\":\"iana\"},\"application/vnd.ms-wmdrm.meter-resp\":{\"source\":\"iana\"},\"application/vnd.ms-word.document.macroenabled.12\":{\"source\":\"iana\",\"extensions\":[\"docm\"]},\"application/vnd.ms-word.template.macroenabled.12\":{\"source\":\"iana\",\"extensions\":[\"dotm\"]},\"application/vnd.ms-works\":{\"source\":\"iana\",\"extensions\":[\"wps\",\"wks\",\"wcm\",\"wdb\"]},\"application/vnd.ms-wpl\":{\"source\":\"iana\",\"extensions\":[\"wpl\"]},\"application/vnd.ms-xpsdocument\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"xps\"]},\"application/vnd.msa-disk-image\":{\"source\":\"iana\"},\"application/vnd.mseq\":{\"source\":\"iana\",\"extensions\":[\"mseq\"]},\"application/vnd.msign\":{\"source\":\"iana\"},\"application/vnd.multiad.creator\":{\"source\":\"iana\"},\"application/vnd.multiad.creator.cif\":{\"source\":\"iana\"},\"application/vnd.music-niff\":{\"source\":\"iana\"},\"application/vnd.musician\":{\"source\":\"iana\",\"extensions\":[\"mus\"]},\"application/vnd.muvee.style\":{\"source\":\"iana\",\"extensions\":[\"msty\"]},\"application/vnd.mynfc\":{\"source\":\"iana\",\"extensions\":[\"taglet\"]},\"application/vnd.ncd.control\":{\"source\":\"iana\"},\"application/vnd.ncd.reference\":{\"source\":\"iana\"},\"application/vnd.nearst.inv+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.nervana\":{\"source\":\"iana\"},\"application/vnd.netfpx\":{\"source\":\"iana\"},\"application/vnd.neurolanguage.nlu\":{\"source\":\"iana\",\"extensions\":[\"nlu\"]},\"application/vnd.nimn\":{\"source\":\"iana\"},\"application/vnd.nintendo.nitro.rom\":{\"source\":\"iana\"},\"application/vnd.nintendo.snes.rom\":{\"source\":\"iana\"},\"application/vnd.nitf\":{\"source\":\"iana\",\"extensions\":[\"ntf\",\"nitf\"]},\"application/vnd.noblenet-directory\":{\"source\":\"iana\",\"extensions\":[\"nnd\"]},\"application/vnd.noblenet-sealer\":{\"source\":\"iana\",\"extensions\":[\"nns\"]},\"application/vnd.noblenet-web\":{\"source\":\"iana\",\"extensions\":[\"nnw\"]},\"application/vnd.nokia.catalogs\":{\"source\":\"iana\"},\"application/vnd.nokia.conml+wbxml\":{\"source\":\"iana\"},\"application/vnd.nokia.conml+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.nokia.iptv.config+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.nokia.isds-radio-presets\":{\"source\":\"iana\"},\"application/vnd.nokia.landmark+wbxml\":{\"source\":\"iana\"},\"application/vnd.nokia.landmark+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.nokia.landmarkcollection+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.nokia.n-gage.ac+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"ac\"]},\"application/vnd.nokia.n-gage.data\":{\"source\":\"iana\",\"extensions\":[\"ngdat\"]},\"application/vnd.nokia.n-gage.symbian.install\":{\"source\":\"iana\",\"extensions\":[\"n-gage\"]},\"application/vnd.nokia.ncd\":{\"source\":\"iana\"},\"application/vnd.nokia.pcd+wbxml\":{\"source\":\"iana\"},\"application/vnd.nokia.pcd+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.nokia.radio-preset\":{\"source\":\"iana\",\"extensions\":[\"rpst\"]},\"application/vnd.nokia.radio-presets\":{\"source\":\"iana\",\"extensions\":[\"rpss\"]},\"application/vnd.novadigm.edm\":{\"source\":\"iana\",\"extensions\":[\"edm\"]},\"application/vnd.novadigm.edx\":{\"source\":\"iana\",\"extensions\":[\"edx\"]},\"application/vnd.novadigm.ext\":{\"source\":\"iana\",\"extensions\":[\"ext\"]},\"application/vnd.ntt-local.content-share\":{\"source\":\"iana\"},\"application/vnd.ntt-local.file-transfer\":{\"source\":\"iana\"},\"application/vnd.ntt-local.ogw_remote-access\":{\"source\":\"iana\"},\"application/vnd.ntt-local.sip-ta_remote\":{\"source\":\"iana\"},\"application/vnd.ntt-local.sip-ta_tcp_stream\":{\"source\":\"iana\"},\"application/vnd.oasis.opendocument.chart\":{\"source\":\"iana\",\"extensions\":[\"odc\"]},\"application/vnd.oasis.opendocument.chart-template\":{\"source\":\"iana\",\"extensions\":[\"otc\"]},\"application/vnd.oasis.opendocument.database\":{\"source\":\"iana\",\"extensions\":[\"odb\"]},\"application/vnd.oasis.opendocument.formula\":{\"source\":\"iana\",\"extensions\":[\"odf\"]},\"application/vnd.oasis.opendocument.formula-template\":{\"source\":\"iana\",\"extensions\":[\"odft\"]},\"application/vnd.oasis.opendocument.graphics\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"odg\"]},\"application/vnd.oasis.opendocument.graphics-template\":{\"source\":\"iana\",\"extensions\":[\"otg\"]},\"application/vnd.oasis.opendocument.image\":{\"source\":\"iana\",\"extensions\":[\"odi\"]},\"application/vnd.oasis.opendocument.image-template\":{\"source\":\"iana\",\"extensions\":[\"oti\"]},\"application/vnd.oasis.opendocument.presentation\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"odp\"]},\"application/vnd.oasis.opendocument.presentation-template\":{\"source\":\"iana\",\"extensions\":[\"otp\"]},\"application/vnd.oasis.opendocument.spreadsheet\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"ods\"]},\"application/vnd.oasis.opendocument.spreadsheet-template\":{\"source\":\"iana\",\"extensions\":[\"ots\"]},\"application/vnd.oasis.opendocument.text\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"odt\"]},\"application/vnd.oasis.opendocument.text-master\":{\"source\":\"iana\",\"extensions\":[\"odm\"]},\"application/vnd.oasis.opendocument.text-template\":{\"source\":\"iana\",\"extensions\":[\"ott\"]},\"application/vnd.oasis.opendocument.text-web\":{\"source\":\"iana\",\"extensions\":[\"oth\"]},\"application/vnd.obn\":{\"source\":\"iana\"},\"application/vnd.ocf+cbor\":{\"source\":\"iana\"},\"application/vnd.oci.image.manifest.v1+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oftn.l10n+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oipf.contentaccessdownload+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oipf.contentaccessstreaming+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oipf.cspg-hexbinary\":{\"source\":\"iana\"},\"application/vnd.oipf.dae.svg+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oipf.dae.xhtml+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oipf.mippvcontrolmessage+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oipf.pae.gem\":{\"source\":\"iana\"},\"application/vnd.oipf.spdiscovery+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oipf.spdlist+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oipf.ueprofile+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oipf.userprofile+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.olpc-sugar\":{\"source\":\"iana\",\"extensions\":[\"xo\"]},\"application/vnd.oma-scws-config\":{\"source\":\"iana\"},\"application/vnd.oma-scws-http-request\":{\"source\":\"iana\"},\"application/vnd.oma-scws-http-response\":{\"source\":\"iana\"},\"application/vnd.oma.bcast.associated-procedure-parameter+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oma.bcast.drm-trigger+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oma.bcast.imd+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oma.bcast.ltkm\":{\"source\":\"iana\"},\"application/vnd.oma.bcast.notification+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oma.bcast.provisioningtrigger\":{\"source\":\"iana\"},\"application/vnd.oma.bcast.sgboot\":{\"source\":\"iana\"},\"application/vnd.oma.bcast.sgdd+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oma.bcast.sgdu\":{\"source\":\"iana\"},\"application/vnd.oma.bcast.simple-symbol-container\":{\"source\":\"iana\"},\"application/vnd.oma.bcast.smartcard-trigger+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oma.bcast.sprov+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oma.bcast.stkm\":{\"source\":\"iana\"},\"application/vnd.oma.cab-address-book+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oma.cab-feature-handler+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oma.cab-pcc+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oma.cab-subs-invite+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oma.cab-user-prefs+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oma.dcd\":{\"source\":\"iana\"},\"application/vnd.oma.dcdc\":{\"source\":\"iana\"},\"application/vnd.oma.dd2+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"dd2\"]},\"application/vnd.oma.drm.risd+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oma.group-usage-list+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oma.lwm2m+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oma.lwm2m+tlv\":{\"source\":\"iana\"},\"application/vnd.oma.pal+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oma.poc.detailed-progress-report+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oma.poc.final-report+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oma.poc.groups+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oma.poc.invocation-descriptor+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oma.poc.optimized-progress-report+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oma.push\":{\"source\":\"iana\"},\"application/vnd.oma.scidm.messages+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oma.xcap-directory+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.omads-email+xml\":{\"source\":\"iana\",\"charset\":\"UTF-8\",\"compressible\":true},\"application/vnd.omads-file+xml\":{\"source\":\"iana\",\"charset\":\"UTF-8\",\"compressible\":true},\"application/vnd.omads-folder+xml\":{\"source\":\"iana\",\"charset\":\"UTF-8\",\"compressible\":true},\"application/vnd.omaloc-supl-init\":{\"source\":\"iana\"},\"application/vnd.onepager\":{\"source\":\"iana\"},\"application/vnd.onepagertamp\":{\"source\":\"iana\"},\"application/vnd.onepagertamx\":{\"source\":\"iana\"},\"application/vnd.onepagertat\":{\"source\":\"iana\"},\"application/vnd.onepagertatp\":{\"source\":\"iana\"},\"application/vnd.onepagertatx\":{\"source\":\"iana\"},\"application/vnd.openblox.game+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"obgx\"]},\"application/vnd.openblox.game-binary\":{\"source\":\"iana\"},\"application/vnd.openeye.oeb\":{\"source\":\"iana\"},\"application/vnd.openofficeorg.extension\":{\"source\":\"apache\",\"extensions\":[\"oxt\"]},\"application/vnd.openstreetmap.data+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"osm\"]},\"application/vnd.openxmlformats-officedocument.custom-properties+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.customxmlproperties+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.drawing+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.drawingml.chart+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.extended-properties+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.presentationml.comments+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.presentationml.presentation\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"pptx\"]},\"application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.presentationml.presprops+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.presentationml.slide\":{\"source\":\"iana\",\"extensions\":[\"sldx\"]},\"application/vnd.openxmlformats-officedocument.presentationml.slide+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.presentationml.slideshow\":{\"source\":\"iana\",\"extensions\":[\"ppsx\"]},\"application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.presentationml.tags+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.presentationml.template\":{\"source\":\"iana\",\"extensions\":[\"potx\"]},\"application/vnd.openxmlformats-officedocument.presentationml.template.main+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"xlsx\"]},\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.spreadsheetml.template\":{\"source\":\"iana\",\"extensions\":[\"xltx\"]},\"application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.theme+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.themeoverride+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.vmldrawing\":{\"source\":\"iana\"},\"application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.wordprocessingml.document\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"docx\"]},\"application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.wordprocessingml.template\":{\"source\":\"iana\",\"extensions\":[\"dotx\"]},\"application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-package.core-properties+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.openxmlformats-package.relationships+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oracle.resource+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.orange.indata\":{\"source\":\"iana\"},\"application/vnd.osa.netdeploy\":{\"source\":\"iana\"},\"application/vnd.osgeo.mapguide.package\":{\"source\":\"iana\",\"extensions\":[\"mgp\"]},\"application/vnd.osgi.bundle\":{\"source\":\"iana\"},\"application/vnd.osgi.dp\":{\"source\":\"iana\",\"extensions\":[\"dp\"]},\"application/vnd.osgi.subsystem\":{\"source\":\"iana\",\"extensions\":[\"esa\"]},\"application/vnd.otps.ct-kip+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.oxli.countgraph\":{\"source\":\"iana\"},\"application/vnd.pagerduty+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.palm\":{\"source\":\"iana\",\"extensions\":[\"pdb\",\"pqa\",\"oprc\"]},\"application/vnd.panoply\":{\"source\":\"iana\"},\"application/vnd.paos.xml\":{\"source\":\"iana\"},\"application/vnd.patentdive\":{\"source\":\"iana\"},\"application/vnd.patientecommsdoc\":{\"source\":\"iana\"},\"application/vnd.pawaafile\":{\"source\":\"iana\",\"extensions\":[\"paw\"]},\"application/vnd.pcos\":{\"source\":\"iana\"},\"application/vnd.pg.format\":{\"source\":\"iana\",\"extensions\":[\"str\"]},\"application/vnd.pg.osasli\":{\"source\":\"iana\",\"extensions\":[\"ei6\"]},\"application/vnd.piaccess.application-licence\":{\"source\":\"iana\"},\"application/vnd.picsel\":{\"source\":\"iana\",\"extensions\":[\"efif\"]},\"application/vnd.pmi.widget\":{\"source\":\"iana\",\"extensions\":[\"wg\"]},\"application/vnd.poc.group-advertisement+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.pocketlearn\":{\"source\":\"iana\",\"extensions\":[\"plf\"]},\"application/vnd.powerbuilder6\":{\"source\":\"iana\",\"extensions\":[\"pbd\"]},\"application/vnd.powerbuilder6-s\":{\"source\":\"iana\"},\"application/vnd.powerbuilder7\":{\"source\":\"iana\"},\"application/vnd.powerbuilder7-s\":{\"source\":\"iana\"},\"application/vnd.powerbuilder75\":{\"source\":\"iana\"},\"application/vnd.powerbuilder75-s\":{\"source\":\"iana\"},\"application/vnd.preminet\":{\"source\":\"iana\"},\"application/vnd.previewsystems.box\":{\"source\":\"iana\",\"extensions\":[\"box\"]},\"application/vnd.proteus.magazine\":{\"source\":\"iana\",\"extensions\":[\"mgz\"]},\"application/vnd.psfs\":{\"source\":\"iana\"},\"application/vnd.publishare-delta-tree\":{\"source\":\"iana\",\"extensions\":[\"qps\"]},\"application/vnd.pvi.ptid1\":{\"source\":\"iana\",\"extensions\":[\"ptid\"]},\"application/vnd.pwg-multiplexed\":{\"source\":\"iana\"},\"application/vnd.pwg-xhtml-print+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.qualcomm.brew-app-res\":{\"source\":\"iana\"},\"application/vnd.quarantainenet\":{\"source\":\"iana\"},\"application/vnd.quark.quarkxpress\":{\"source\":\"iana\",\"extensions\":[\"qxd\",\"qxt\",\"qwd\",\"qwt\",\"qxl\",\"qxb\"]},\"application/vnd.quobject-quoxdocument\":{\"source\":\"iana\"},\"application/vnd.radisys.moml+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.radisys.msml+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.radisys.msml-audit+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.radisys.msml-audit-conf+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.radisys.msml-audit-conn+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.radisys.msml-audit-dialog+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.radisys.msml-audit-stream+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.radisys.msml-conf+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.radisys.msml-dialog+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.radisys.msml-dialog-base+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.radisys.msml-dialog-fax-detect+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.radisys.msml-dialog-fax-sendrecv+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.radisys.msml-dialog-group+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.radisys.msml-dialog-speech+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.radisys.msml-dialog-transform+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.rainstor.data\":{\"source\":\"iana\"},\"application/vnd.rapid\":{\"source\":\"iana\"},\"application/vnd.rar\":{\"source\":\"iana\"},\"application/vnd.realvnc.bed\":{\"source\":\"iana\",\"extensions\":[\"bed\"]},\"application/vnd.recordare.musicxml\":{\"source\":\"iana\",\"extensions\":[\"mxl\"]},\"application/vnd.recordare.musicxml+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"musicxml\"]},\"application/vnd.renlearn.rlprint\":{\"source\":\"iana\"},\"application/vnd.restful+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.rig.cryptonote\":{\"source\":\"iana\",\"extensions\":[\"cryptonote\"]},\"application/vnd.rim.cod\":{\"source\":\"apache\",\"extensions\":[\"cod\"]},\"application/vnd.rn-realmedia\":{\"source\":\"apache\",\"extensions\":[\"rm\"]},\"application/vnd.rn-realmedia-vbr\":{\"source\":\"apache\",\"extensions\":[\"rmvb\"]},\"application/vnd.route66.link66+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"link66\"]},\"application/vnd.rs-274x\":{\"source\":\"iana\"},\"application/vnd.ruckus.download\":{\"source\":\"iana\"},\"application/vnd.s3sms\":{\"source\":\"iana\"},\"application/vnd.sailingtracker.track\":{\"source\":\"iana\",\"extensions\":[\"st\"]},\"application/vnd.sar\":{\"source\":\"iana\"},\"application/vnd.sbm.cid\":{\"source\":\"iana\"},\"application/vnd.sbm.mid2\":{\"source\":\"iana\"},\"application/vnd.scribus\":{\"source\":\"iana\"},\"application/vnd.sealed.3df\":{\"source\":\"iana\"},\"application/vnd.sealed.csf\":{\"source\":\"iana\"},\"application/vnd.sealed.doc\":{\"source\":\"iana\"},\"application/vnd.sealed.eml\":{\"source\":\"iana\"},\"application/vnd.sealed.mht\":{\"source\":\"iana\"},\"application/vnd.sealed.net\":{\"source\":\"iana\"},\"application/vnd.sealed.ppt\":{\"source\":\"iana\"},\"application/vnd.sealed.tiff\":{\"source\":\"iana\"},\"application/vnd.sealed.xls\":{\"source\":\"iana\"},\"application/vnd.sealedmedia.softseal.html\":{\"source\":\"iana\"},\"application/vnd.sealedmedia.softseal.pdf\":{\"source\":\"iana\"},\"application/vnd.seemail\":{\"source\":\"iana\",\"extensions\":[\"see\"]},\"application/vnd.sema\":{\"source\":\"iana\",\"extensions\":[\"sema\"]},\"application/vnd.semd\":{\"source\":\"iana\",\"extensions\":[\"semd\"]},\"application/vnd.semf\":{\"source\":\"iana\",\"extensions\":[\"semf\"]},\"application/vnd.shade-save-file\":{\"source\":\"iana\"},\"application/vnd.shana.informed.formdata\":{\"source\":\"iana\",\"extensions\":[\"ifm\"]},\"application/vnd.shana.informed.formtemplate\":{\"source\":\"iana\",\"extensions\":[\"itp\"]},\"application/vnd.shana.informed.interchange\":{\"source\":\"iana\",\"extensions\":[\"iif\"]},\"application/vnd.shana.informed.package\":{\"source\":\"iana\",\"extensions\":[\"ipk\"]},\"application/vnd.shootproof+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.shopkick+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.shp\":{\"source\":\"iana\"},\"application/vnd.shx\":{\"source\":\"iana\"},\"application/vnd.sigrok.session\":{\"source\":\"iana\"},\"application/vnd.simtech-mindmapper\":{\"source\":\"iana\",\"extensions\":[\"twd\",\"twds\"]},\"application/vnd.siren+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.smaf\":{\"source\":\"iana\",\"extensions\":[\"mmf\"]},\"application/vnd.smart.notebook\":{\"source\":\"iana\"},\"application/vnd.smart.teacher\":{\"source\":\"iana\",\"extensions\":[\"teacher\"]},\"application/vnd.snesdev-page-table\":{\"source\":\"iana\"},\"application/vnd.software602.filler.form+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"fo\"]},\"application/vnd.software602.filler.form-xml-zip\":{\"source\":\"iana\"},\"application/vnd.solent.sdkm+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"sdkm\",\"sdkd\"]},\"application/vnd.spotfire.dxp\":{\"source\":\"iana\",\"extensions\":[\"dxp\"]},\"application/vnd.spotfire.sfs\":{\"source\":\"iana\",\"extensions\":[\"sfs\"]},\"application/vnd.sqlite3\":{\"source\":\"iana\"},\"application/vnd.sss-cod\":{\"source\":\"iana\"},\"application/vnd.sss-dtf\":{\"source\":\"iana\"},\"application/vnd.sss-ntf\":{\"source\":\"iana\"},\"application/vnd.stardivision.calc\":{\"source\":\"apache\",\"extensions\":[\"sdc\"]},\"application/vnd.stardivision.draw\":{\"source\":\"apache\",\"extensions\":[\"sda\"]},\"application/vnd.stardivision.impress\":{\"source\":\"apache\",\"extensions\":[\"sdd\"]},\"application/vnd.stardivision.math\":{\"source\":\"apache\",\"extensions\":[\"smf\"]},\"application/vnd.stardivision.writer\":{\"source\":\"apache\",\"extensions\":[\"sdw\",\"vor\"]},\"application/vnd.stardivision.writer-global\":{\"source\":\"apache\",\"extensions\":[\"sgl\"]},\"application/vnd.stepmania.package\":{\"source\":\"iana\",\"extensions\":[\"smzip\"]},\"application/vnd.stepmania.stepchart\":{\"source\":\"iana\",\"extensions\":[\"sm\"]},\"application/vnd.street-stream\":{\"source\":\"iana\"},\"application/vnd.sun.wadl+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"wadl\"]},\"application/vnd.sun.xml.calc\":{\"source\":\"apache\",\"extensions\":[\"sxc\"]},\"application/vnd.sun.xml.calc.template\":{\"source\":\"apache\",\"extensions\":[\"stc\"]},\"application/vnd.sun.xml.draw\":{\"source\":\"apache\",\"extensions\":[\"sxd\"]},\"application/vnd.sun.xml.draw.template\":{\"source\":\"apache\",\"extensions\":[\"std\"]},\"application/vnd.sun.xml.impress\":{\"source\":\"apache\",\"extensions\":[\"sxi\"]},\"application/vnd.sun.xml.impress.template\":{\"source\":\"apache\",\"extensions\":[\"sti\"]},\"application/vnd.sun.xml.math\":{\"source\":\"apache\",\"extensions\":[\"sxm\"]},\"application/vnd.sun.xml.writer\":{\"source\":\"apache\",\"extensions\":[\"sxw\"]},\"application/vnd.sun.xml.writer.global\":{\"source\":\"apache\",\"extensions\":[\"sxg\"]},\"application/vnd.sun.xml.writer.template\":{\"source\":\"apache\",\"extensions\":[\"stw\"]},\"application/vnd.sus-calendar\":{\"source\":\"iana\",\"extensions\":[\"sus\",\"susp\"]},\"application/vnd.svd\":{\"source\":\"iana\",\"extensions\":[\"svd\"]},\"application/vnd.swiftview-ics\":{\"source\":\"iana\"},\"application/vnd.symbian.install\":{\"source\":\"apache\",\"extensions\":[\"sis\",\"sisx\"]},\"application/vnd.syncml+xml\":{\"source\":\"iana\",\"charset\":\"UTF-8\",\"compressible\":true,\"extensions\":[\"xsm\"]},\"application/vnd.syncml.dm+wbxml\":{\"source\":\"iana\",\"charset\":\"UTF-8\",\"extensions\":[\"bdm\"]},\"application/vnd.syncml.dm+xml\":{\"source\":\"iana\",\"charset\":\"UTF-8\",\"compressible\":true,\"extensions\":[\"xdm\"]},\"application/vnd.syncml.dm.notification\":{\"source\":\"iana\"},\"application/vnd.syncml.dmddf+wbxml\":{\"source\":\"iana\"},\"application/vnd.syncml.dmddf+xml\":{\"source\":\"iana\",\"charset\":\"UTF-8\",\"compressible\":true,\"extensions\":[\"ddf\"]},\"application/vnd.syncml.dmtnds+wbxml\":{\"source\":\"iana\"},\"application/vnd.syncml.dmtnds+xml\":{\"source\":\"iana\",\"charset\":\"UTF-8\",\"compressible\":true},\"application/vnd.syncml.ds.notification\":{\"source\":\"iana\"},\"application/vnd.tableschema+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.tao.intent-module-archive\":{\"source\":\"iana\",\"extensions\":[\"tao\"]},\"application/vnd.tcpdump.pcap\":{\"source\":\"iana\",\"extensions\":[\"pcap\",\"cap\",\"dmp\"]},\"application/vnd.think-cell.ppttc+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.tmd.mediaflex.api+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.tml\":{\"source\":\"iana\"},\"application/vnd.tmobile-livetv\":{\"source\":\"iana\",\"extensions\":[\"tmo\"]},\"application/vnd.tri.onesource\":{\"source\":\"iana\"},\"application/vnd.trid.tpt\":{\"source\":\"iana\",\"extensions\":[\"tpt\"]},\"application/vnd.triscape.mxs\":{\"source\":\"iana\",\"extensions\":[\"mxs\"]},\"application/vnd.trueapp\":{\"source\":\"iana\",\"extensions\":[\"tra\"]},\"application/vnd.truedoc\":{\"source\":\"iana\"},\"application/vnd.ubisoft.webplayer\":{\"source\":\"iana\"},\"application/vnd.ufdl\":{\"source\":\"iana\",\"extensions\":[\"ufd\",\"ufdl\"]},\"application/vnd.uiq.theme\":{\"source\":\"iana\",\"extensions\":[\"utz\"]},\"application/vnd.umajin\":{\"source\":\"iana\",\"extensions\":[\"umj\"]},\"application/vnd.unity\":{\"source\":\"iana\",\"extensions\":[\"unityweb\"]},\"application/vnd.uoml+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"uoml\"]},\"application/vnd.uplanet.alert\":{\"source\":\"iana\"},\"application/vnd.uplanet.alert-wbxml\":{\"source\":\"iana\"},\"application/vnd.uplanet.bearer-choice\":{\"source\":\"iana\"},\"application/vnd.uplanet.bearer-choice-wbxml\":{\"source\":\"iana\"},\"application/vnd.uplanet.cacheop\":{\"source\":\"iana\"},\"application/vnd.uplanet.cacheop-wbxml\":{\"source\":\"iana\"},\"application/vnd.uplanet.channel\":{\"source\":\"iana\"},\"application/vnd.uplanet.channel-wbxml\":{\"source\":\"iana\"},\"application/vnd.uplanet.list\":{\"source\":\"iana\"},\"application/vnd.uplanet.list-wbxml\":{\"source\":\"iana\"},\"application/vnd.uplanet.listcmd\":{\"source\":\"iana\"},\"application/vnd.uplanet.listcmd-wbxml\":{\"source\":\"iana\"},\"application/vnd.uplanet.signal\":{\"source\":\"iana\"},\"application/vnd.uri-map\":{\"source\":\"iana\"},\"application/vnd.valve.source.material\":{\"source\":\"iana\"},\"application/vnd.vcx\":{\"source\":\"iana\",\"extensions\":[\"vcx\"]},\"application/vnd.vd-study\":{\"source\":\"iana\"},\"application/vnd.vectorworks\":{\"source\":\"iana\"},\"application/vnd.vel+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.verimatrix.vcas\":{\"source\":\"iana\"},\"application/vnd.veryant.thin\":{\"source\":\"iana\"},\"application/vnd.ves.encrypted\":{\"source\":\"iana\"},\"application/vnd.vidsoft.vidconference\":{\"source\":\"iana\"},\"application/vnd.visio\":{\"source\":\"iana\",\"extensions\":[\"vsd\",\"vst\",\"vss\",\"vsw\"]},\"application/vnd.visionary\":{\"source\":\"iana\",\"extensions\":[\"vis\"]},\"application/vnd.vividence.scriptfile\":{\"source\":\"iana\"},\"application/vnd.vsf\":{\"source\":\"iana\",\"extensions\":[\"vsf\"]},\"application/vnd.wap.sic\":{\"source\":\"iana\"},\"application/vnd.wap.slc\":{\"source\":\"iana\"},\"application/vnd.wap.wbxml\":{\"source\":\"iana\",\"charset\":\"UTF-8\",\"extensions\":[\"wbxml\"]},\"application/vnd.wap.wmlc\":{\"source\":\"iana\",\"extensions\":[\"wmlc\"]},\"application/vnd.wap.wmlscriptc\":{\"source\":\"iana\",\"extensions\":[\"wmlsc\"]},\"application/vnd.webturbo\":{\"source\":\"iana\",\"extensions\":[\"wtb\"]},\"application/vnd.wfa.p2p\":{\"source\":\"iana\"},\"application/vnd.wfa.wsc\":{\"source\":\"iana\"},\"application/vnd.windows.devicepairing\":{\"source\":\"iana\"},\"application/vnd.wmc\":{\"source\":\"iana\"},\"application/vnd.wmf.bootstrap\":{\"source\":\"iana\"},\"application/vnd.wolfram.mathematica\":{\"source\":\"iana\"},\"application/vnd.wolfram.mathematica.package\":{\"source\":\"iana\"},\"application/vnd.wolfram.player\":{\"source\":\"iana\",\"extensions\":[\"nbp\"]},\"application/vnd.wordperfect\":{\"source\":\"iana\",\"extensions\":[\"wpd\"]},\"application/vnd.wqd\":{\"source\":\"iana\",\"extensions\":[\"wqd\"]},\"application/vnd.wrq-hp3000-labelled\":{\"source\":\"iana\"},\"application/vnd.wt.stf\":{\"source\":\"iana\",\"extensions\":[\"stf\"]},\"application/vnd.wv.csp+wbxml\":{\"source\":\"iana\"},\"application/vnd.wv.csp+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.wv.ssp+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.xacml+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.xara\":{\"source\":\"iana\",\"extensions\":[\"xar\"]},\"application/vnd.xfdl\":{\"source\":\"iana\",\"extensions\":[\"xfdl\"]},\"application/vnd.xfdl.webform\":{\"source\":\"iana\"},\"application/vnd.xmi+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/vnd.xmpie.cpkg\":{\"source\":\"iana\"},\"application/vnd.xmpie.dpkg\":{\"source\":\"iana\"},\"application/vnd.xmpie.plan\":{\"source\":\"iana\"},\"application/vnd.xmpie.ppkg\":{\"source\":\"iana\"},\"application/vnd.xmpie.xlim\":{\"source\":\"iana\"},\"application/vnd.yamaha.hv-dic\":{\"source\":\"iana\",\"extensions\":[\"hvd\"]},\"application/vnd.yamaha.hv-script\":{\"source\":\"iana\",\"extensions\":[\"hvs\"]},\"application/vnd.yamaha.hv-voice\":{\"source\":\"iana\",\"extensions\":[\"hvp\"]},\"application/vnd.yamaha.openscoreformat\":{\"source\":\"iana\",\"extensions\":[\"osf\"]},\"application/vnd.yamaha.openscoreformat.osfpvg+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"osfpvg\"]},\"application/vnd.yamaha.remote-setup\":{\"source\":\"iana\"},\"application/vnd.yamaha.smaf-audio\":{\"source\":\"iana\",\"extensions\":[\"saf\"]},\"application/vnd.yamaha.smaf-phrase\":{\"source\":\"iana\",\"extensions\":[\"spf\"]},\"application/vnd.yamaha.through-ngn\":{\"source\":\"iana\"},\"application/vnd.yamaha.tunnel-udpencap\":{\"source\":\"iana\"},\"application/vnd.yaoweme\":{\"source\":\"iana\"},\"application/vnd.yellowriver-custom-menu\":{\"source\":\"iana\",\"extensions\":[\"cmp\"]},\"application/vnd.youtube.yt\":{\"source\":\"iana\"},\"application/vnd.zul\":{\"source\":\"iana\",\"extensions\":[\"zir\",\"zirz\"]},\"application/vnd.zzazz.deck+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"zaz\"]},\"application/voicexml+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"vxml\"]},\"application/voucher-cms+json\":{\"source\":\"iana\",\"compressible\":true},\"application/vq-rtcpxr\":{\"source\":\"iana\"},\"application/wasm\":{\"compressible\":true,\"extensions\":[\"wasm\"]},\"application/watcherinfo+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/webpush-options+json\":{\"source\":\"iana\",\"compressible\":true},\"application/whoispp-query\":{\"source\":\"iana\"},\"application/whoispp-response\":{\"source\":\"iana\"},\"application/widget\":{\"source\":\"iana\",\"extensions\":[\"wgt\"]},\"application/winhlp\":{\"source\":\"apache\",\"extensions\":[\"hlp\"]},\"application/wita\":{\"source\":\"iana\"},\"application/wordperfect5.1\":{\"source\":\"iana\"},\"application/wsdl+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"wsdl\"]},\"application/wspolicy+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"wspolicy\"]},\"application/x-7z-compressed\":{\"source\":\"apache\",\"compressible\":false,\"extensions\":[\"7z\"]},\"application/x-abiword\":{\"source\":\"apache\",\"extensions\":[\"abw\"]},\"application/x-ace-compressed\":{\"source\":\"apache\",\"extensions\":[\"ace\"]},\"application/x-amf\":{\"source\":\"apache\"},\"application/x-apple-diskimage\":{\"source\":\"apache\",\"extensions\":[\"dmg\"]},\"application/x-arj\":{\"compressible\":false,\"extensions\":[\"arj\"]},\"application/x-authorware-bin\":{\"source\":\"apache\",\"extensions\":[\"aab\",\"x32\",\"u32\",\"vox\"]},\"application/x-authorware-map\":{\"source\":\"apache\",\"extensions\":[\"aam\"]},\"application/x-authorware-seg\":{\"source\":\"apache\",\"extensions\":[\"aas\"]},\"application/x-bcpio\":{\"source\":\"apache\",\"extensions\":[\"bcpio\"]},\"application/x-bdoc\":{\"compressible\":false,\"extensions\":[\"bdoc\"]},\"application/x-bittorrent\":{\"source\":\"apache\",\"extensions\":[\"torrent\"]},\"application/x-blorb\":{\"source\":\"apache\",\"extensions\":[\"blb\",\"blorb\"]},\"application/x-bzip\":{\"source\":\"apache\",\"compressible\":false,\"extensions\":[\"bz\"]},\"application/x-bzip2\":{\"source\":\"apache\",\"compressible\":false,\"extensions\":[\"bz2\",\"boz\"]},\"application/x-cbr\":{\"source\":\"apache\",\"extensions\":[\"cbr\",\"cba\",\"cbt\",\"cbz\",\"cb7\"]},\"application/x-cdlink\":{\"source\":\"apache\",\"extensions\":[\"vcd\"]},\"application/x-cfs-compressed\":{\"source\":\"apache\",\"extensions\":[\"cfs\"]},\"application/x-chat\":{\"source\":\"apache\",\"extensions\":[\"chat\"]},\"application/x-chess-pgn\":{\"source\":\"apache\",\"extensions\":[\"pgn\"]},\"application/x-chrome-extension\":{\"extensions\":[\"crx\"]},\"application/x-cocoa\":{\"source\":\"nginx\",\"extensions\":[\"cco\"]},\"application/x-compress\":{\"source\":\"apache\"},\"application/x-conference\":{\"source\":\"apache\",\"extensions\":[\"nsc\"]},\"application/x-cpio\":{\"source\":\"apache\",\"extensions\":[\"cpio\"]},\"application/x-csh\":{\"source\":\"apache\",\"extensions\":[\"csh\"]},\"application/x-deb\":{\"compressible\":false},\"application/x-debian-package\":{\"source\":\"apache\",\"extensions\":[\"deb\",\"udeb\"]},\"application/x-dgc-compressed\":{\"source\":\"apache\",\"extensions\":[\"dgc\"]},\"application/x-director\":{\"source\":\"apache\",\"extensions\":[\"dir\",\"dcr\",\"dxr\",\"cst\",\"cct\",\"cxt\",\"w3d\",\"fgd\",\"swa\"]},\"application/x-doom\":{\"source\":\"apache\",\"extensions\":[\"wad\"]},\"application/x-dtbncx+xml\":{\"source\":\"apache\",\"compressible\":true,\"extensions\":[\"ncx\"]},\"application/x-dtbook+xml\":{\"source\":\"apache\",\"compressible\":true,\"extensions\":[\"dtb\"]},\"application/x-dtbresource+xml\":{\"source\":\"apache\",\"compressible\":true,\"extensions\":[\"res\"]},\"application/x-dvi\":{\"source\":\"apache\",\"compressible\":false,\"extensions\":[\"dvi\"]},\"application/x-envoy\":{\"source\":\"apache\",\"extensions\":[\"evy\"]},\"application/x-eva\":{\"source\":\"apache\",\"extensions\":[\"eva\"]},\"application/x-font-bdf\":{\"source\":\"apache\",\"extensions\":[\"bdf\"]},\"application/x-font-dos\":{\"source\":\"apache\"},\"application/x-font-framemaker\":{\"source\":\"apache\"},\"application/x-font-ghostscript\":{\"source\":\"apache\",\"extensions\":[\"gsf\"]},\"application/x-font-libgrx\":{\"source\":\"apache\"},\"application/x-font-linux-psf\":{\"source\":\"apache\",\"extensions\":[\"psf\"]},\"application/x-font-pcf\":{\"source\":\"apache\",\"extensions\":[\"pcf\"]},\"application/x-font-snf\":{\"source\":\"apache\",\"extensions\":[\"snf\"]},\"application/x-font-speedo\":{\"source\":\"apache\"},\"application/x-font-sunos-news\":{\"source\":\"apache\"},\"application/x-font-type1\":{\"source\":\"apache\",\"extensions\":[\"pfa\",\"pfb\",\"pfm\",\"afm\"]},\"application/x-font-vfont\":{\"source\":\"apache\"},\"application/x-freearc\":{\"source\":\"apache\",\"extensions\":[\"arc\"]},\"application/x-futuresplash\":{\"source\":\"apache\",\"extensions\":[\"spl\"]},\"application/x-gca-compressed\":{\"source\":\"apache\",\"extensions\":[\"gca\"]},\"application/x-glulx\":{\"source\":\"apache\",\"extensions\":[\"ulx\"]},\"application/x-gnumeric\":{\"source\":\"apache\",\"extensions\":[\"gnumeric\"]},\"application/x-gramps-xml\":{\"source\":\"apache\",\"extensions\":[\"gramps\"]},\"application/x-gtar\":{\"source\":\"apache\",\"extensions\":[\"gtar\"]},\"application/x-gzip\":{\"source\":\"apache\"},\"application/x-hdf\":{\"source\":\"apache\",\"extensions\":[\"hdf\"]},\"application/x-httpd-php\":{\"compressible\":true,\"extensions\":[\"php\"]},\"application/x-install-instructions\":{\"source\":\"apache\",\"extensions\":[\"install\"]},\"application/x-iso9660-image\":{\"source\":\"apache\",\"extensions\":[\"iso\"]},\"application/x-java-archive-diff\":{\"source\":\"nginx\",\"extensions\":[\"jardiff\"]},\"application/x-java-jnlp-file\":{\"source\":\"apache\",\"compressible\":false,\"extensions\":[\"jnlp\"]},\"application/x-javascript\":{\"compressible\":true},\"application/x-keepass2\":{\"extensions\":[\"kdbx\"]},\"application/x-latex\":{\"source\":\"apache\",\"compressible\":false,\"extensions\":[\"latex\"]},\"application/x-lua-bytecode\":{\"extensions\":[\"luac\"]},\"application/x-lzh-compressed\":{\"source\":\"apache\",\"extensions\":[\"lzh\",\"lha\"]},\"application/x-makeself\":{\"source\":\"nginx\",\"extensions\":[\"run\"]},\"application/x-mie\":{\"source\":\"apache\",\"extensions\":[\"mie\"]},\"application/x-mobipocket-ebook\":{\"source\":\"apache\",\"extensions\":[\"prc\",\"mobi\"]},\"application/x-mpegurl\":{\"compressible\":false},\"application/x-ms-application\":{\"source\":\"apache\",\"extensions\":[\"application\"]},\"application/x-ms-shortcut\":{\"source\":\"apache\",\"extensions\":[\"lnk\"]},\"application/x-ms-wmd\":{\"source\":\"apache\",\"extensions\":[\"wmd\"]},\"application/x-ms-wmz\":{\"source\":\"apache\",\"extensions\":[\"wmz\"]},\"application/x-ms-xbap\":{\"source\":\"apache\",\"extensions\":[\"xbap\"]},\"application/x-msaccess\":{\"source\":\"apache\",\"extensions\":[\"mdb\"]},\"application/x-msbinder\":{\"source\":\"apache\",\"extensions\":[\"obd\"]},\"application/x-mscardfile\":{\"source\":\"apache\",\"extensions\":[\"crd\"]},\"application/x-msclip\":{\"source\":\"apache\",\"extensions\":[\"clp\"]},\"application/x-msdos-program\":{\"extensions\":[\"exe\"]},\"application/x-msdownload\":{\"source\":\"apache\",\"extensions\":[\"exe\",\"dll\",\"com\",\"bat\",\"msi\"]},\"application/x-msmediaview\":{\"source\":\"apache\",\"extensions\":[\"mvb\",\"m13\",\"m14\"]},\"application/x-msmetafile\":{\"source\":\"apache\",\"extensions\":[\"wmf\",\"wmz\",\"emf\",\"emz\"]},\"application/x-msmoney\":{\"source\":\"apache\",\"extensions\":[\"mny\"]},\"application/x-mspublisher\":{\"source\":\"apache\",\"extensions\":[\"pub\"]},\"application/x-msschedule\":{\"source\":\"apache\",\"extensions\":[\"scd\"]},\"application/x-msterminal\":{\"source\":\"apache\",\"extensions\":[\"trm\"]},\"application/x-mswrite\":{\"source\":\"apache\",\"extensions\":[\"wri\"]},\"application/x-netcdf\":{\"source\":\"apache\",\"extensions\":[\"nc\",\"cdf\"]},\"application/x-ns-proxy-autoconfig\":{\"compressible\":true,\"extensions\":[\"pac\"]},\"application/x-nzb\":{\"source\":\"apache\",\"extensions\":[\"nzb\"]},\"application/x-perl\":{\"source\":\"nginx\",\"extensions\":[\"pl\",\"pm\"]},\"application/x-pilot\":{\"source\":\"nginx\",\"extensions\":[\"prc\",\"pdb\"]},\"application/x-pkcs12\":{\"source\":\"apache\",\"compressible\":false,\"extensions\":[\"p12\",\"pfx\"]},\"application/x-pkcs7-certificates\":{\"source\":\"apache\",\"extensions\":[\"p7b\",\"spc\"]},\"application/x-pkcs7-certreqresp\":{\"source\":\"apache\",\"extensions\":[\"p7r\"]},\"application/x-pki-message\":{\"source\":\"iana\"},\"application/x-rar-compressed\":{\"source\":\"apache\",\"compressible\":false,\"extensions\":[\"rar\"]},\"application/x-redhat-package-manager\":{\"source\":\"nginx\",\"extensions\":[\"rpm\"]},\"application/x-research-info-systems\":{\"source\":\"apache\",\"extensions\":[\"ris\"]},\"application/x-sea\":{\"source\":\"nginx\",\"extensions\":[\"sea\"]},\"application/x-sh\":{\"source\":\"apache\",\"compressible\":true,\"extensions\":[\"sh\"]},\"application/x-shar\":{\"source\":\"apache\",\"extensions\":[\"shar\"]},\"application/x-shockwave-flash\":{\"source\":\"apache\",\"compressible\":false,\"extensions\":[\"swf\"]},\"application/x-silverlight-app\":{\"source\":\"apache\",\"extensions\":[\"xap\"]},\"application/x-sql\":{\"source\":\"apache\",\"extensions\":[\"sql\"]},\"application/x-stuffit\":{\"source\":\"apache\",\"compressible\":false,\"extensions\":[\"sit\"]},\"application/x-stuffitx\":{\"source\":\"apache\",\"extensions\":[\"sitx\"]},\"application/x-subrip\":{\"source\":\"apache\",\"extensions\":[\"srt\"]},\"application/x-sv4cpio\":{\"source\":\"apache\",\"extensions\":[\"sv4cpio\"]},\"application/x-sv4crc\":{\"source\":\"apache\",\"extensions\":[\"sv4crc\"]},\"application/x-t3vm-image\":{\"source\":\"apache\",\"extensions\":[\"t3\"]},\"application/x-tads\":{\"source\":\"apache\",\"extensions\":[\"gam\"]},\"application/x-tar\":{\"source\":\"apache\",\"compressible\":true,\"extensions\":[\"tar\"]},\"application/x-tcl\":{\"source\":\"apache\",\"extensions\":[\"tcl\",\"tk\"]},\"application/x-tex\":{\"source\":\"apache\",\"extensions\":[\"tex\"]},\"application/x-tex-tfm\":{\"source\":\"apache\",\"extensions\":[\"tfm\"]},\"application/x-texinfo\":{\"source\":\"apache\",\"extensions\":[\"texinfo\",\"texi\"]},\"application/x-tgif\":{\"source\":\"apache\",\"extensions\":[\"obj\"]},\"application/x-ustar\":{\"source\":\"apache\",\"extensions\":[\"ustar\"]},\"application/x-virtualbox-hdd\":{\"compressible\":true,\"extensions\":[\"hdd\"]},\"application/x-virtualbox-ova\":{\"compressible\":true,\"extensions\":[\"ova\"]},\"application/x-virtualbox-ovf\":{\"compressible\":true,\"extensions\":[\"ovf\"]},\"application/x-virtualbox-vbox\":{\"compressible\":true,\"extensions\":[\"vbox\"]},\"application/x-virtualbox-vbox-extpack\":{\"compressible\":false,\"extensions\":[\"vbox-extpack\"]},\"application/x-virtualbox-vdi\":{\"compressible\":true,\"extensions\":[\"vdi\"]},\"application/x-virtualbox-vhd\":{\"compressible\":true,\"extensions\":[\"vhd\"]},\"application/x-virtualbox-vmdk\":{\"compressible\":true,\"extensions\":[\"vmdk\"]},\"application/x-wais-source\":{\"source\":\"apache\",\"extensions\":[\"src\"]},\"application/x-web-app-manifest+json\":{\"compressible\":true,\"extensions\":[\"webapp\"]},\"application/x-www-form-urlencoded\":{\"source\":\"iana\",\"compressible\":true},\"application/x-x509-ca-cert\":{\"source\":\"iana\",\"extensions\":[\"der\",\"crt\",\"pem\"]},\"application/x-x509-ca-ra-cert\":{\"source\":\"iana\"},\"application/x-x509-next-ca-cert\":{\"source\":\"iana\"},\"application/x-xfig\":{\"source\":\"apache\",\"extensions\":[\"fig\"]},\"application/x-xliff+xml\":{\"source\":\"apache\",\"compressible\":true,\"extensions\":[\"xlf\"]},\"application/x-xpinstall\":{\"source\":\"apache\",\"compressible\":false,\"extensions\":[\"xpi\"]},\"application/x-xz\":{\"source\":\"apache\",\"extensions\":[\"xz\"]},\"application/x-zmachine\":{\"source\":\"apache\",\"extensions\":[\"z1\",\"z2\",\"z3\",\"z4\",\"z5\",\"z6\",\"z7\",\"z8\"]},\"application/x400-bp\":{\"source\":\"iana\"},\"application/xacml+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/xaml+xml\":{\"source\":\"apache\",\"compressible\":true,\"extensions\":[\"xaml\"]},\"application/xcap-att+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"xav\"]},\"application/xcap-caps+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"xca\"]},\"application/xcap-diff+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"xdf\"]},\"application/xcap-el+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"xel\"]},\"application/xcap-error+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"xer\"]},\"application/xcap-ns+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"xns\"]},\"application/xcon-conference-info+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/xcon-conference-info-diff+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/xenc+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"xenc\"]},\"application/xhtml+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"xhtml\",\"xht\"]},\"application/xhtml-voice+xml\":{\"source\":\"apache\",\"compressible\":true},\"application/xliff+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"xlf\"]},\"application/xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"xml\",\"xsl\",\"xsd\",\"rng\"]},\"application/xml-dtd\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"dtd\"]},\"application/xml-external-parsed-entity\":{\"source\":\"iana\"},\"application/xml-patch+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/xmpp+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/xop+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"xop\"]},\"application/xproc+xml\":{\"source\":\"apache\",\"compressible\":true,\"extensions\":[\"xpl\"]},\"application/xslt+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"xslt\"]},\"application/xspf+xml\":{\"source\":\"apache\",\"compressible\":true,\"extensions\":[\"xspf\"]},\"application/xv+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"mxml\",\"xhvml\",\"xvml\",\"xvm\"]},\"application/yang\":{\"source\":\"iana\",\"extensions\":[\"yang\"]},\"application/yang-data+json\":{\"source\":\"iana\",\"compressible\":true},\"application/yang-data+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/yang-patch+json\":{\"source\":\"iana\",\"compressible\":true},\"application/yang-patch+xml\":{\"source\":\"iana\",\"compressible\":true},\"application/yin+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"yin\"]},\"application/zip\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"zip\"]},\"application/zlib\":{\"source\":\"iana\"},\"application/zstd\":{\"source\":\"iana\"},\"audio/1d-interleaved-parityfec\":{\"source\":\"iana\"},\"audio/32kadpcm\":{\"source\":\"iana\"},\"audio/3gpp\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"3gpp\"]},\"audio/3gpp2\":{\"source\":\"iana\"},\"audio/aac\":{\"source\":\"iana\"},\"audio/ac3\":{\"source\":\"iana\"},\"audio/adpcm\":{\"source\":\"apache\",\"extensions\":[\"adp\"]},\"audio/amr\":{\"source\":\"iana\"},\"audio/amr-wb\":{\"source\":\"iana\"},\"audio/amr-wb+\":{\"source\":\"iana\"},\"audio/aptx\":{\"source\":\"iana\"},\"audio/asc\":{\"source\":\"iana\"},\"audio/atrac-advanced-lossless\":{\"source\":\"iana\"},\"audio/atrac-x\":{\"source\":\"iana\"},\"audio/atrac3\":{\"source\":\"iana\"},\"audio/basic\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"au\",\"snd\"]},\"audio/bv16\":{\"source\":\"iana\"},\"audio/bv32\":{\"source\":\"iana\"},\"audio/clearmode\":{\"source\":\"iana\"},\"audio/cn\":{\"source\":\"iana\"},\"audio/dat12\":{\"source\":\"iana\"},\"audio/dls\":{\"source\":\"iana\"},\"audio/dsr-es201108\":{\"source\":\"iana\"},\"audio/dsr-es202050\":{\"source\":\"iana\"},\"audio/dsr-es202211\":{\"source\":\"iana\"},\"audio/dsr-es202212\":{\"source\":\"iana\"},\"audio/dv\":{\"source\":\"iana\"},\"audio/dvi4\":{\"source\":\"iana\"},\"audio/eac3\":{\"source\":\"iana\"},\"audio/encaprtp\":{\"source\":\"iana\"},\"audio/evrc\":{\"source\":\"iana\"},\"audio/evrc-qcp\":{\"source\":\"iana\"},\"audio/evrc0\":{\"source\":\"iana\"},\"audio/evrc1\":{\"source\":\"iana\"},\"audio/evrcb\":{\"source\":\"iana\"},\"audio/evrcb0\":{\"source\":\"iana\"},\"audio/evrcb1\":{\"source\":\"iana\"},\"audio/evrcnw\":{\"source\":\"iana\"},\"audio/evrcnw0\":{\"source\":\"iana\"},\"audio/evrcnw1\":{\"source\":\"iana\"},\"audio/evrcwb\":{\"source\":\"iana\"},\"audio/evrcwb0\":{\"source\":\"iana\"},\"audio/evrcwb1\":{\"source\":\"iana\"},\"audio/evs\":{\"source\":\"iana\"},\"audio/flexfec\":{\"source\":\"iana\"},\"audio/fwdred\":{\"source\":\"iana\"},\"audio/g711-0\":{\"source\":\"iana\"},\"audio/g719\":{\"source\":\"iana\"},\"audio/g722\":{\"source\":\"iana\"},\"audio/g7221\":{\"source\":\"iana\"},\"audio/g723\":{\"source\":\"iana\"},\"audio/g726-16\":{\"source\":\"iana\"},\"audio/g726-24\":{\"source\":\"iana\"},\"audio/g726-32\":{\"source\":\"iana\"},\"audio/g726-40\":{\"source\":\"iana\"},\"audio/g728\":{\"source\":\"iana\"},\"audio/g729\":{\"source\":\"iana\"},\"audio/g7291\":{\"source\":\"iana\"},\"audio/g729d\":{\"source\":\"iana\"},\"audio/g729e\":{\"source\":\"iana\"},\"audio/gsm\":{\"source\":\"iana\"},\"audio/gsm-efr\":{\"source\":\"iana\"},\"audio/gsm-hr-08\":{\"source\":\"iana\"},\"audio/ilbc\":{\"source\":\"iana\"},\"audio/ip-mr_v2.5\":{\"source\":\"iana\"},\"audio/isac\":{\"source\":\"apache\"},\"audio/l16\":{\"source\":\"iana\"},\"audio/l20\":{\"source\":\"iana\"},\"audio/l24\":{\"source\":\"iana\",\"compressible\":false},\"audio/l8\":{\"source\":\"iana\"},\"audio/lpc\":{\"source\":\"iana\"},\"audio/melp\":{\"source\":\"iana\"},\"audio/melp1200\":{\"source\":\"iana\"},\"audio/melp2400\":{\"source\":\"iana\"},\"audio/melp600\":{\"source\":\"iana\"},\"audio/mhas\":{\"source\":\"iana\"},\"audio/midi\":{\"source\":\"apache\",\"extensions\":[\"mid\",\"midi\",\"kar\",\"rmi\"]},\"audio/mobile-xmf\":{\"source\":\"iana\",\"extensions\":[\"mxmf\"]},\"audio/mp3\":{\"compressible\":false,\"extensions\":[\"mp3\"]},\"audio/mp4\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"m4a\",\"mp4a\"]},\"audio/mp4a-latm\":{\"source\":\"iana\"},\"audio/mpa\":{\"source\":\"iana\"},\"audio/mpa-robust\":{\"source\":\"iana\"},\"audio/mpeg\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"mpga\",\"mp2\",\"mp2a\",\"mp3\",\"m2a\",\"m3a\"]},\"audio/mpeg4-generic\":{\"source\":\"iana\"},\"audio/musepack\":{\"source\":\"apache\"},\"audio/ogg\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"oga\",\"ogg\",\"spx\"]},\"audio/opus\":{\"source\":\"iana\"},\"audio/parityfec\":{\"source\":\"iana\"},\"audio/pcma\":{\"source\":\"iana\"},\"audio/pcma-wb\":{\"source\":\"iana\"},\"audio/pcmu\":{\"source\":\"iana\"},\"audio/pcmu-wb\":{\"source\":\"iana\"},\"audio/prs.sid\":{\"source\":\"iana\"},\"audio/qcelp\":{\"source\":\"iana\"},\"audio/raptorfec\":{\"source\":\"iana\"},\"audio/red\":{\"source\":\"iana\"},\"audio/rtp-enc-aescm128\":{\"source\":\"iana\"},\"audio/rtp-midi\":{\"source\":\"iana\"},\"audio/rtploopback\":{\"source\":\"iana\"},\"audio/rtx\":{\"source\":\"iana\"},\"audio/s3m\":{\"source\":\"apache\",\"extensions\":[\"s3m\"]},\"audio/silk\":{\"source\":\"apache\",\"extensions\":[\"sil\"]},\"audio/smv\":{\"source\":\"iana\"},\"audio/smv-qcp\":{\"source\":\"iana\"},\"audio/smv0\":{\"source\":\"iana\"},\"audio/sp-midi\":{\"source\":\"iana\"},\"audio/speex\":{\"source\":\"iana\"},\"audio/t140c\":{\"source\":\"iana\"},\"audio/t38\":{\"source\":\"iana\"},\"audio/telephone-event\":{\"source\":\"iana\"},\"audio/tetra_acelp\":{\"source\":\"iana\"},\"audio/tetra_acelp_bb\":{\"source\":\"iana\"},\"audio/tone\":{\"source\":\"iana\"},\"audio/uemclip\":{\"source\":\"iana\"},\"audio/ulpfec\":{\"source\":\"iana\"},\"audio/usac\":{\"source\":\"iana\"},\"audio/vdvi\":{\"source\":\"iana\"},\"audio/vmr-wb\":{\"source\":\"iana\"},\"audio/vnd.3gpp.iufp\":{\"source\":\"iana\"},\"audio/vnd.4sb\":{\"source\":\"iana\"},\"audio/vnd.audiokoz\":{\"source\":\"iana\"},\"audio/vnd.celp\":{\"source\":\"iana\"},\"audio/vnd.cisco.nse\":{\"source\":\"iana\"},\"audio/vnd.cmles.radio-events\":{\"source\":\"iana\"},\"audio/vnd.cns.anp1\":{\"source\":\"iana\"},\"audio/vnd.cns.inf1\":{\"source\":\"iana\"},\"audio/vnd.dece.audio\":{\"source\":\"iana\",\"extensions\":[\"uva\",\"uvva\"]},\"audio/vnd.digital-winds\":{\"source\":\"iana\",\"extensions\":[\"eol\"]},\"audio/vnd.dlna.adts\":{\"source\":\"iana\"},\"audio/vnd.dolby.heaac.1\":{\"source\":\"iana\"},\"audio/vnd.dolby.heaac.2\":{\"source\":\"iana\"},\"audio/vnd.dolby.mlp\":{\"source\":\"iana\"},\"audio/vnd.dolby.mps\":{\"source\":\"iana\"},\"audio/vnd.dolby.pl2\":{\"source\":\"iana\"},\"audio/vnd.dolby.pl2x\":{\"source\":\"iana\"},\"audio/vnd.dolby.pl2z\":{\"source\":\"iana\"},\"audio/vnd.dolby.pulse.1\":{\"source\":\"iana\"},\"audio/vnd.dra\":{\"source\":\"iana\",\"extensions\":[\"dra\"]},\"audio/vnd.dts\":{\"source\":\"iana\",\"extensions\":[\"dts\"]},\"audio/vnd.dts.hd\":{\"source\":\"iana\",\"extensions\":[\"dtshd\"]},\"audio/vnd.dts.uhd\":{\"source\":\"iana\"},\"audio/vnd.dvb.file\":{\"source\":\"iana\"},\"audio/vnd.everad.plj\":{\"source\":\"iana\"},\"audio/vnd.hns.audio\":{\"source\":\"iana\"},\"audio/vnd.lucent.voice\":{\"source\":\"iana\",\"extensions\":[\"lvp\"]},\"audio/vnd.ms-playready.media.pya\":{\"source\":\"iana\",\"extensions\":[\"pya\"]},\"audio/vnd.nokia.mobile-xmf\":{\"source\":\"iana\"},\"audio/vnd.nortel.vbk\":{\"source\":\"iana\"},\"audio/vnd.nuera.ecelp4800\":{\"source\":\"iana\",\"extensions\":[\"ecelp4800\"]},\"audio/vnd.nuera.ecelp7470\":{\"source\":\"iana\",\"extensions\":[\"ecelp7470\"]},\"audio/vnd.nuera.ecelp9600\":{\"source\":\"iana\",\"extensions\":[\"ecelp9600\"]},\"audio/vnd.octel.sbc\":{\"source\":\"iana\"},\"audio/vnd.presonus.multitrack\":{\"source\":\"iana\"},\"audio/vnd.qcelp\":{\"source\":\"iana\"},\"audio/vnd.rhetorex.32kadpcm\":{\"source\":\"iana\"},\"audio/vnd.rip\":{\"source\":\"iana\",\"extensions\":[\"rip\"]},\"audio/vnd.rn-realaudio\":{\"compressible\":false},\"audio/vnd.sealedmedia.softseal.mpeg\":{\"source\":\"iana\"},\"audio/vnd.vmx.cvsd\":{\"source\":\"iana\"},\"audio/vnd.wave\":{\"compressible\":false},\"audio/vorbis\":{\"source\":\"iana\",\"compressible\":false},\"audio/vorbis-config\":{\"source\":\"iana\"},\"audio/wav\":{\"compressible\":false,\"extensions\":[\"wav\"]},\"audio/wave\":{\"compressible\":false,\"extensions\":[\"wav\"]},\"audio/webm\":{\"source\":\"apache\",\"compressible\":false,\"extensions\":[\"weba\"]},\"audio/x-aac\":{\"source\":\"apache\",\"compressible\":false,\"extensions\":[\"aac\"]},\"audio/x-aiff\":{\"source\":\"apache\",\"extensions\":[\"aif\",\"aiff\",\"aifc\"]},\"audio/x-caf\":{\"source\":\"apache\",\"compressible\":false,\"extensions\":[\"caf\"]},\"audio/x-flac\":{\"source\":\"apache\",\"extensions\":[\"flac\"]},\"audio/x-m4a\":{\"source\":\"nginx\",\"extensions\":[\"m4a\"]},\"audio/x-matroska\":{\"source\":\"apache\",\"extensions\":[\"mka\"]},\"audio/x-mpegurl\":{\"source\":\"apache\",\"extensions\":[\"m3u\"]},\"audio/x-ms-wax\":{\"source\":\"apache\",\"extensions\":[\"wax\"]},\"audio/x-ms-wma\":{\"source\":\"apache\",\"extensions\":[\"wma\"]},\"audio/x-pn-realaudio\":{\"source\":\"apache\",\"extensions\":[\"ram\",\"ra\"]},\"audio/x-pn-realaudio-plugin\":{\"source\":\"apache\",\"extensions\":[\"rmp\"]},\"audio/x-realaudio\":{\"source\":\"nginx\",\"extensions\":[\"ra\"]},\"audio/x-tta\":{\"source\":\"apache\"},\"audio/x-wav\":{\"source\":\"apache\",\"extensions\":[\"wav\"]},\"audio/xm\":{\"source\":\"apache\",\"extensions\":[\"xm\"]},\"chemical/x-cdx\":{\"source\":\"apache\",\"extensions\":[\"cdx\"]},\"chemical/x-cif\":{\"source\":\"apache\",\"extensions\":[\"cif\"]},\"chemical/x-cmdf\":{\"source\":\"apache\",\"extensions\":[\"cmdf\"]},\"chemical/x-cml\":{\"source\":\"apache\",\"extensions\":[\"cml\"]},\"chemical/x-csml\":{\"source\":\"apache\",\"extensions\":[\"csml\"]},\"chemical/x-pdb\":{\"source\":\"apache\"},\"chemical/x-xyz\":{\"source\":\"apache\",\"extensions\":[\"xyz\"]},\"font/collection\":{\"source\":\"iana\",\"extensions\":[\"ttc\"]},\"font/otf\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"otf\"]},\"font/sfnt\":{\"source\":\"iana\"},\"font/ttf\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"ttf\"]},\"font/woff\":{\"source\":\"iana\",\"extensions\":[\"woff\"]},\"font/woff2\":{\"source\":\"iana\",\"extensions\":[\"woff2\"]},\"image/aces\":{\"source\":\"iana\",\"extensions\":[\"exr\"]},\"image/apng\":{\"compressible\":false,\"extensions\":[\"apng\"]},\"image/avci\":{\"source\":\"iana\"},\"image/avcs\":{\"source\":\"iana\"},\"image/bmp\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"bmp\"]},\"image/cgm\":{\"source\":\"iana\",\"extensions\":[\"cgm\"]},\"image/dicom-rle\":{\"source\":\"iana\",\"extensions\":[\"drle\"]},\"image/emf\":{\"source\":\"iana\",\"extensions\":[\"emf\"]},\"image/fits\":{\"source\":\"iana\",\"extensions\":[\"fits\"]},\"image/g3fax\":{\"source\":\"iana\",\"extensions\":[\"g3\"]},\"image/gif\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"gif\"]},\"image/heic\":{\"source\":\"iana\",\"extensions\":[\"heic\"]},\"image/heic-sequence\":{\"source\":\"iana\",\"extensions\":[\"heics\"]},\"image/heif\":{\"source\":\"iana\",\"extensions\":[\"heif\"]},\"image/heif-sequence\":{\"source\":\"iana\",\"extensions\":[\"heifs\"]},\"image/hej2k\":{\"source\":\"iana\",\"extensions\":[\"hej2\"]},\"image/hsj2\":{\"source\":\"iana\",\"extensions\":[\"hsj2\"]},\"image/ief\":{\"source\":\"iana\",\"extensions\":[\"ief\"]},\"image/jls\":{\"source\":\"iana\",\"extensions\":[\"jls\"]},\"image/jp2\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"jp2\",\"jpg2\"]},\"image/jpeg\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"jpeg\",\"jpg\",\"jpe\"]},\"image/jph\":{\"source\":\"iana\",\"extensions\":[\"jph\"]},\"image/jphc\":{\"source\":\"iana\",\"extensions\":[\"jhc\"]},\"image/jpm\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"jpm\"]},\"image/jpx\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"jpx\",\"jpf\"]},\"image/jxr\":{\"source\":\"iana\",\"extensions\":[\"jxr\"]},\"image/jxra\":{\"source\":\"iana\",\"extensions\":[\"jxra\"]},\"image/jxrs\":{\"source\":\"iana\",\"extensions\":[\"jxrs\"]},\"image/jxs\":{\"source\":\"iana\",\"extensions\":[\"jxs\"]},\"image/jxsc\":{\"source\":\"iana\",\"extensions\":[\"jxsc\"]},\"image/jxsi\":{\"source\":\"iana\",\"extensions\":[\"jxsi\"]},\"image/jxss\":{\"source\":\"iana\",\"extensions\":[\"jxss\"]},\"image/ktx\":{\"source\":\"iana\",\"extensions\":[\"ktx\"]},\"image/naplps\":{\"source\":\"iana\"},\"image/pjpeg\":{\"compressible\":false},\"image/png\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"png\"]},\"image/prs.btif\":{\"source\":\"iana\",\"extensions\":[\"btif\"]},\"image/prs.pti\":{\"source\":\"iana\",\"extensions\":[\"pti\"]},\"image/pwg-raster\":{\"source\":\"iana\"},\"image/sgi\":{\"source\":\"apache\",\"extensions\":[\"sgi\"]},\"image/svg+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"svg\",\"svgz\"]},\"image/t38\":{\"source\":\"iana\",\"extensions\":[\"t38\"]},\"image/tiff\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"tif\",\"tiff\"]},\"image/tiff-fx\":{\"source\":\"iana\",\"extensions\":[\"tfx\"]},\"image/vnd.adobe.photoshop\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"psd\"]},\"image/vnd.airzip.accelerator.azv\":{\"source\":\"iana\",\"extensions\":[\"azv\"]},\"image/vnd.cns.inf2\":{\"source\":\"iana\"},\"image/vnd.dece.graphic\":{\"source\":\"iana\",\"extensions\":[\"uvi\",\"uvvi\",\"uvg\",\"uvvg\"]},\"image/vnd.djvu\":{\"source\":\"iana\",\"extensions\":[\"djvu\",\"djv\"]},\"image/vnd.dvb.subtitle\":{\"source\":\"iana\",\"extensions\":[\"sub\"]},\"image/vnd.dwg\":{\"source\":\"iana\",\"extensions\":[\"dwg\"]},\"image/vnd.dxf\":{\"source\":\"iana\",\"extensions\":[\"dxf\"]},\"image/vnd.fastbidsheet\":{\"source\":\"iana\",\"extensions\":[\"fbs\"]},\"image/vnd.fpx\":{\"source\":\"iana\",\"extensions\":[\"fpx\"]},\"image/vnd.fst\":{\"source\":\"iana\",\"extensions\":[\"fst\"]},\"image/vnd.fujixerox.edmics-mmr\":{\"source\":\"iana\",\"extensions\":[\"mmr\"]},\"image/vnd.fujixerox.edmics-rlc\":{\"source\":\"iana\",\"extensions\":[\"rlc\"]},\"image/vnd.globalgraphics.pgb\":{\"source\":\"iana\"},\"image/vnd.microsoft.icon\":{\"source\":\"iana\",\"extensions\":[\"ico\"]},\"image/vnd.mix\":{\"source\":\"iana\"},\"image/vnd.mozilla.apng\":{\"source\":\"iana\"},\"image/vnd.ms-dds\":{\"extensions\":[\"dds\"]},\"image/vnd.ms-modi\":{\"source\":\"iana\",\"extensions\":[\"mdi\"]},\"image/vnd.ms-photo\":{\"source\":\"apache\",\"extensions\":[\"wdp\"]},\"image/vnd.net-fpx\":{\"source\":\"iana\",\"extensions\":[\"npx\"]},\"image/vnd.radiance\":{\"source\":\"iana\"},\"image/vnd.sealed.png\":{\"source\":\"iana\"},\"image/vnd.sealedmedia.softseal.gif\":{\"source\":\"iana\"},\"image/vnd.sealedmedia.softseal.jpg\":{\"source\":\"iana\"},\"image/vnd.svf\":{\"source\":\"iana\"},\"image/vnd.tencent.tap\":{\"source\":\"iana\",\"extensions\":[\"tap\"]},\"image/vnd.valve.source.texture\":{\"source\":\"iana\",\"extensions\":[\"vtf\"]},\"image/vnd.wap.wbmp\":{\"source\":\"iana\",\"extensions\":[\"wbmp\"]},\"image/vnd.xiff\":{\"source\":\"iana\",\"extensions\":[\"xif\"]},\"image/vnd.zbrush.pcx\":{\"source\":\"iana\",\"extensions\":[\"pcx\"]},\"image/webp\":{\"source\":\"apache\",\"extensions\":[\"webp\"]},\"image/wmf\":{\"source\":\"iana\",\"extensions\":[\"wmf\"]},\"image/x-3ds\":{\"source\":\"apache\",\"extensions\":[\"3ds\"]},\"image/x-cmu-raster\":{\"source\":\"apache\",\"extensions\":[\"ras\"]},\"image/x-cmx\":{\"source\":\"apache\",\"extensions\":[\"cmx\"]},\"image/x-freehand\":{\"source\":\"apache\",\"extensions\":[\"fh\",\"fhc\",\"fh4\",\"fh5\",\"fh7\"]},\"image/x-icon\":{\"source\":\"apache\",\"compressible\":true,\"extensions\":[\"ico\"]},\"image/x-jng\":{\"source\":\"nginx\",\"extensions\":[\"jng\"]},\"image/x-mrsid-image\":{\"source\":\"apache\",\"extensions\":[\"sid\"]},\"image/x-ms-bmp\":{\"source\":\"nginx\",\"compressible\":true,\"extensions\":[\"bmp\"]},\"image/x-pcx\":{\"source\":\"apache\",\"extensions\":[\"pcx\"]},\"image/x-pict\":{\"source\":\"apache\",\"extensions\":[\"pic\",\"pct\"]},\"image/x-portable-anymap\":{\"source\":\"apache\",\"extensions\":[\"pnm\"]},\"image/x-portable-bitmap\":{\"source\":\"apache\",\"extensions\":[\"pbm\"]},\"image/x-portable-graymap\":{\"source\":\"apache\",\"extensions\":[\"pgm\"]},\"image/x-portable-pixmap\":{\"source\":\"apache\",\"extensions\":[\"ppm\"]},\"image/x-rgb\":{\"source\":\"apache\",\"extensions\":[\"rgb\"]},\"image/x-tga\":{\"source\":\"apache\",\"extensions\":[\"tga\"]},\"image/x-xbitmap\":{\"source\":\"apache\",\"extensions\":[\"xbm\"]},\"image/x-xcf\":{\"compressible\":false},\"image/x-xpixmap\":{\"source\":\"apache\",\"extensions\":[\"xpm\"]},\"image/x-xwindowdump\":{\"source\":\"apache\",\"extensions\":[\"xwd\"]},\"message/cpim\":{\"source\":\"iana\"},\"message/delivery-status\":{\"source\":\"iana\"},\"message/disposition-notification\":{\"source\":\"iana\",\"extensions\":[\"disposition-notification\"]},\"message/external-body\":{\"source\":\"iana\"},\"message/feedback-report\":{\"source\":\"iana\"},\"message/global\":{\"source\":\"iana\",\"extensions\":[\"u8msg\"]},\"message/global-delivery-status\":{\"source\":\"iana\",\"extensions\":[\"u8dsn\"]},\"message/global-disposition-notification\":{\"source\":\"iana\",\"extensions\":[\"u8mdn\"]},\"message/global-headers\":{\"source\":\"iana\",\"extensions\":[\"u8hdr\"]},\"message/http\":{\"source\":\"iana\",\"compressible\":false},\"message/imdn+xml\":{\"source\":\"iana\",\"compressible\":true},\"message/news\":{\"source\":\"iana\"},\"message/partial\":{\"source\":\"iana\",\"compressible\":false},\"message/rfc822\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"eml\",\"mime\"]},\"message/s-http\":{\"source\":\"iana\"},\"message/sip\":{\"source\":\"iana\"},\"message/sipfrag\":{\"source\":\"iana\"},\"message/tracking-status\":{\"source\":\"iana\"},\"message/vnd.si.simp\":{\"source\":\"iana\"},\"message/vnd.wfa.wsc\":{\"source\":\"iana\",\"extensions\":[\"wsc\"]},\"model/3mf\":{\"source\":\"iana\",\"extensions\":[\"3mf\"]},\"model/gltf+json\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"gltf\"]},\"model/gltf-binary\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"glb\"]},\"model/iges\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"igs\",\"iges\"]},\"model/mesh\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"msh\",\"mesh\",\"silo\"]},\"model/mtl\":{\"source\":\"iana\",\"extensions\":[\"mtl\"]},\"model/obj\":{\"source\":\"iana\",\"extensions\":[\"obj\"]},\"model/stl\":{\"source\":\"iana\",\"extensions\":[\"stl\"]},\"model/vnd.collada+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"dae\"]},\"model/vnd.dwf\":{\"source\":\"iana\",\"extensions\":[\"dwf\"]},\"model/vnd.flatland.3dml\":{\"source\":\"iana\"},\"model/vnd.gdl\":{\"source\":\"iana\",\"extensions\":[\"gdl\"]},\"model/vnd.gs-gdl\":{\"source\":\"apache\"},\"model/vnd.gs.gdl\":{\"source\":\"iana\"},\"model/vnd.gtw\":{\"source\":\"iana\",\"extensions\":[\"gtw\"]},\"model/vnd.moml+xml\":{\"source\":\"iana\",\"compressible\":true},\"model/vnd.mts\":{\"source\":\"iana\",\"extensions\":[\"mts\"]},\"model/vnd.opengex\":{\"source\":\"iana\",\"extensions\":[\"ogex\"]},\"model/vnd.parasolid.transmit.binary\":{\"source\":\"iana\",\"extensions\":[\"x_b\"]},\"model/vnd.parasolid.transmit.text\":{\"source\":\"iana\",\"extensions\":[\"x_t\"]},\"model/vnd.rosette.annotated-data-model\":{\"source\":\"iana\"},\"model/vnd.usdz+zip\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"usdz\"]},\"model/vnd.valve.source.compiled-map\":{\"source\":\"iana\",\"extensions\":[\"bsp\"]},\"model/vnd.vtu\":{\"source\":\"iana\",\"extensions\":[\"vtu\"]},\"model/vrml\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"wrl\",\"vrml\"]},\"model/x3d+binary\":{\"source\":\"apache\",\"compressible\":false,\"extensions\":[\"x3db\",\"x3dbz\"]},\"model/x3d+fastinfoset\":{\"source\":\"iana\",\"extensions\":[\"x3db\"]},\"model/x3d+vrml\":{\"source\":\"apache\",\"compressible\":false,\"extensions\":[\"x3dv\",\"x3dvz\"]},\"model/x3d+xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"x3d\",\"x3dz\"]},\"model/x3d-vrml\":{\"source\":\"iana\",\"extensions\":[\"x3dv\"]},\"multipart/alternative\":{\"source\":\"iana\",\"compressible\":false},\"multipart/appledouble\":{\"source\":\"iana\"},\"multipart/byteranges\":{\"source\":\"iana\"},\"multipart/digest\":{\"source\":\"iana\"},\"multipart/encrypted\":{\"source\":\"iana\",\"compressible\":false},\"multipart/form-data\":{\"source\":\"iana\",\"compressible\":false},\"multipart/header-set\":{\"source\":\"iana\"},\"multipart/mixed\":{\"source\":\"iana\"},\"multipart/multilingual\":{\"source\":\"iana\"},\"multipart/parallel\":{\"source\":\"iana\"},\"multipart/related\":{\"source\":\"iana\",\"compressible\":false},\"multipart/report\":{\"source\":\"iana\"},\"multipart/signed\":{\"source\":\"iana\",\"compressible\":false},\"multipart/vnd.bint.med-plus\":{\"source\":\"iana\"},\"multipart/voice-message\":{\"source\":\"iana\"},\"multipart/x-mixed-replace\":{\"source\":\"iana\"},\"text/1d-interleaved-parityfec\":{\"source\":\"iana\"},\"text/cache-manifest\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"appcache\",\"manifest\"]},\"text/calendar\":{\"source\":\"iana\",\"extensions\":[\"ics\",\"ifb\"]},\"text/calender\":{\"compressible\":true},\"text/cmd\":{\"compressible\":true},\"text/coffeescript\":{\"extensions\":[\"coffee\",\"litcoffee\"]},\"text/css\":{\"source\":\"iana\",\"charset\":\"UTF-8\",\"compressible\":true,\"extensions\":[\"css\"]},\"text/csv\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"csv\"]},\"text/csv-schema\":{\"source\":\"iana\"},\"text/directory\":{\"source\":\"iana\"},\"text/dns\":{\"source\":\"iana\"},\"text/ecmascript\":{\"source\":\"iana\"},\"text/encaprtp\":{\"source\":\"iana\"},\"text/enriched\":{\"source\":\"iana\"},\"text/flexfec\":{\"source\":\"iana\"},\"text/fwdred\":{\"source\":\"iana\"},\"text/grammar-ref-list\":{\"source\":\"iana\"},\"text/html\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"html\",\"htm\",\"shtml\"]},\"text/jade\":{\"extensions\":[\"jade\"]},\"text/javascript\":{\"source\":\"iana\",\"compressible\":true},\"text/jcr-cnd\":{\"source\":\"iana\"},\"text/jsx\":{\"compressible\":true,\"extensions\":[\"jsx\"]},\"text/less\":{\"compressible\":true,\"extensions\":[\"less\"]},\"text/markdown\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"markdown\",\"md\"]},\"text/mathml\":{\"source\":\"nginx\",\"extensions\":[\"mml\"]},\"text/mdx\":{\"compressible\":true,\"extensions\":[\"mdx\"]},\"text/mizar\":{\"source\":\"iana\"},\"text/n3\":{\"source\":\"iana\",\"charset\":\"UTF-8\",\"compressible\":true,\"extensions\":[\"n3\"]},\"text/parameters\":{\"source\":\"iana\",\"charset\":\"UTF-8\"},\"text/parityfec\":{\"source\":\"iana\"},\"text/plain\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"txt\",\"text\",\"conf\",\"def\",\"list\",\"log\",\"in\",\"ini\"]},\"text/provenance-notation\":{\"source\":\"iana\",\"charset\":\"UTF-8\"},\"text/prs.fallenstein.rst\":{\"source\":\"iana\"},\"text/prs.lines.tag\":{\"source\":\"iana\",\"extensions\":[\"dsc\"]},\"text/prs.prop.logic\":{\"source\":\"iana\"},\"text/raptorfec\":{\"source\":\"iana\"},\"text/red\":{\"source\":\"iana\"},\"text/rfc822-headers\":{\"source\":\"iana\"},\"text/richtext\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"rtx\"]},\"text/rtf\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"rtf\"]},\"text/rtp-enc-aescm128\":{\"source\":\"iana\"},\"text/rtploopback\":{\"source\":\"iana\"},\"text/rtx\":{\"source\":\"iana\"},\"text/sgml\":{\"source\":\"iana\",\"extensions\":[\"sgml\",\"sgm\"]},\"text/shex\":{\"extensions\":[\"shex\"]},\"text/slim\":{\"extensions\":[\"slim\",\"slm\"]},\"text/strings\":{\"source\":\"iana\"},\"text/stylus\":{\"extensions\":[\"stylus\",\"styl\"]},\"text/t140\":{\"source\":\"iana\"},\"text/tab-separated-values\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"tsv\"]},\"text/troff\":{\"source\":\"iana\",\"extensions\":[\"t\",\"tr\",\"roff\",\"man\",\"me\",\"ms\"]},\"text/turtle\":{\"source\":\"iana\",\"charset\":\"UTF-8\",\"extensions\":[\"ttl\"]},\"text/ulpfec\":{\"source\":\"iana\"},\"text/uri-list\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"uri\",\"uris\",\"urls\"]},\"text/vcard\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"vcard\"]},\"text/vnd.a\":{\"source\":\"iana\"},\"text/vnd.abc\":{\"source\":\"iana\"},\"text/vnd.ascii-art\":{\"source\":\"iana\"},\"text/vnd.curl\":{\"source\":\"iana\",\"extensions\":[\"curl\"]},\"text/vnd.curl.dcurl\":{\"source\":\"apache\",\"extensions\":[\"dcurl\"]},\"text/vnd.curl.mcurl\":{\"source\":\"apache\",\"extensions\":[\"mcurl\"]},\"text/vnd.curl.scurl\":{\"source\":\"apache\",\"extensions\":[\"scurl\"]},\"text/vnd.debian.copyright\":{\"source\":\"iana\",\"charset\":\"UTF-8\"},\"text/vnd.dmclientscript\":{\"source\":\"iana\"},\"text/vnd.dvb.subtitle\":{\"source\":\"iana\",\"extensions\":[\"sub\"]},\"text/vnd.esmertec.theme-descriptor\":{\"source\":\"iana\",\"charset\":\"UTF-8\"},\"text/vnd.ficlab.flt\":{\"source\":\"iana\"},\"text/vnd.fly\":{\"source\":\"iana\",\"extensions\":[\"fly\"]},\"text/vnd.fmi.flexstor\":{\"source\":\"iana\",\"extensions\":[\"flx\"]},\"text/vnd.gml\":{\"source\":\"iana\"},\"text/vnd.graphviz\":{\"source\":\"iana\",\"extensions\":[\"gv\"]},\"text/vnd.hgl\":{\"source\":\"iana\"},\"text/vnd.in3d.3dml\":{\"source\":\"iana\",\"extensions\":[\"3dml\"]},\"text/vnd.in3d.spot\":{\"source\":\"iana\",\"extensions\":[\"spot\"]},\"text/vnd.iptc.newsml\":{\"source\":\"iana\"},\"text/vnd.iptc.nitf\":{\"source\":\"iana\"},\"text/vnd.latex-z\":{\"source\":\"iana\"},\"text/vnd.motorola.reflex\":{\"source\":\"iana\"},\"text/vnd.ms-mediapackage\":{\"source\":\"iana\"},\"text/vnd.net2phone.commcenter.command\":{\"source\":\"iana\"},\"text/vnd.radisys.msml-basic-layout\":{\"source\":\"iana\"},\"text/vnd.senx.warpscript\":{\"source\":\"iana\"},\"text/vnd.si.uricatalogue\":{\"source\":\"iana\"},\"text/vnd.sosi\":{\"source\":\"iana\"},\"text/vnd.sun.j2me.app-descriptor\":{\"source\":\"iana\",\"charset\":\"UTF-8\",\"extensions\":[\"jad\"]},\"text/vnd.trolltech.linguist\":{\"source\":\"iana\",\"charset\":\"UTF-8\"},\"text/vnd.wap.si\":{\"source\":\"iana\"},\"text/vnd.wap.sl\":{\"source\":\"iana\"},\"text/vnd.wap.wml\":{\"source\":\"iana\",\"extensions\":[\"wml\"]},\"text/vnd.wap.wmlscript\":{\"source\":\"iana\",\"extensions\":[\"wmls\"]},\"text/vtt\":{\"source\":\"iana\",\"charset\":\"UTF-8\",\"compressible\":true,\"extensions\":[\"vtt\"]},\"text/x-asm\":{\"source\":\"apache\",\"extensions\":[\"s\",\"asm\"]},\"text/x-c\":{\"source\":\"apache\",\"extensions\":[\"c\",\"cc\",\"cxx\",\"cpp\",\"h\",\"hh\",\"dic\"]},\"text/x-component\":{\"source\":\"nginx\",\"extensions\":[\"htc\"]},\"text/x-fortran\":{\"source\":\"apache\",\"extensions\":[\"f\",\"for\",\"f77\",\"f90\"]},\"text/x-gwt-rpc\":{\"compressible\":true},\"text/x-handlebars-template\":{\"extensions\":[\"hbs\"]},\"text/x-java-source\":{\"source\":\"apache\",\"extensions\":[\"java\"]},\"text/x-jquery-tmpl\":{\"compressible\":true},\"text/x-lua\":{\"extensions\":[\"lua\"]},\"text/x-markdown\":{\"compressible\":true,\"extensions\":[\"mkd\"]},\"text/x-nfo\":{\"source\":\"apache\",\"extensions\":[\"nfo\"]},\"text/x-opml\":{\"source\":\"apache\",\"extensions\":[\"opml\"]},\"text/x-org\":{\"compressible\":true,\"extensions\":[\"org\"]},\"text/x-pascal\":{\"source\":\"apache\",\"extensions\":[\"p\",\"pas\"]},\"text/x-processing\":{\"compressible\":true,\"extensions\":[\"pde\"]},\"text/x-sass\":{\"extensions\":[\"sass\"]},\"text/x-scss\":{\"extensions\":[\"scss\"]},\"text/x-setext\":{\"source\":\"apache\",\"extensions\":[\"etx\"]},\"text/x-sfv\":{\"source\":\"apache\",\"extensions\":[\"sfv\"]},\"text/x-suse-ymp\":{\"compressible\":true,\"extensions\":[\"ymp\"]},\"text/x-uuencode\":{\"source\":\"apache\",\"extensions\":[\"uu\"]},\"text/x-vcalendar\":{\"source\":\"apache\",\"extensions\":[\"vcs\"]},\"text/x-vcard\":{\"source\":\"apache\",\"extensions\":[\"vcf\"]},\"text/xml\":{\"source\":\"iana\",\"compressible\":true,\"extensions\":[\"xml\"]},\"text/xml-external-parsed-entity\":{\"source\":\"iana\"},\"text/yaml\":{\"extensions\":[\"yaml\",\"yml\"]},\"video/1d-interleaved-parityfec\":{\"source\":\"iana\"},\"video/3gpp\":{\"source\":\"iana\",\"extensions\":[\"3gp\",\"3gpp\"]},\"video/3gpp-tt\":{\"source\":\"iana\"},\"video/3gpp2\":{\"source\":\"iana\",\"extensions\":[\"3g2\"]},\"video/bmpeg\":{\"source\":\"iana\"},\"video/bt656\":{\"source\":\"iana\"},\"video/celb\":{\"source\":\"iana\"},\"video/dv\":{\"source\":\"iana\"},\"video/encaprtp\":{\"source\":\"iana\"},\"video/flexfec\":{\"source\":\"iana\"},\"video/h261\":{\"source\":\"iana\",\"extensions\":[\"h261\"]},\"video/h263\":{\"source\":\"iana\",\"extensions\":[\"h263\"]},\"video/h263-1998\":{\"source\":\"iana\"},\"video/h263-2000\":{\"source\":\"iana\"},\"video/h264\":{\"source\":\"iana\",\"extensions\":[\"h264\"]},\"video/h264-rcdo\":{\"source\":\"iana\"},\"video/h264-svc\":{\"source\":\"iana\"},\"video/h265\":{\"source\":\"iana\"},\"video/iso.segment\":{\"source\":\"iana\"},\"video/jpeg\":{\"source\":\"iana\",\"extensions\":[\"jpgv\"]},\"video/jpeg2000\":{\"source\":\"iana\"},\"video/jpm\":{\"source\":\"apache\",\"extensions\":[\"jpm\",\"jpgm\"]},\"video/mj2\":{\"source\":\"iana\",\"extensions\":[\"mj2\",\"mjp2\"]},\"video/mp1s\":{\"source\":\"iana\"},\"video/mp2p\":{\"source\":\"iana\"},\"video/mp2t\":{\"source\":\"iana\",\"extensions\":[\"ts\"]},\"video/mp4\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"mp4\",\"mp4v\",\"mpg4\"]},\"video/mp4v-es\":{\"source\":\"iana\"},\"video/mpeg\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"mpeg\",\"mpg\",\"mpe\",\"m1v\",\"m2v\"]},\"video/mpeg4-generic\":{\"source\":\"iana\"},\"video/mpv\":{\"source\":\"iana\"},\"video/nv\":{\"source\":\"iana\"},\"video/ogg\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"ogv\"]},\"video/parityfec\":{\"source\":\"iana\"},\"video/pointer\":{\"source\":\"iana\"},\"video/quicktime\":{\"source\":\"iana\",\"compressible\":false,\"extensions\":[\"qt\",\"mov\"]},\"video/raptorfec\":{\"source\":\"iana\"},\"video/raw\":{\"source\":\"iana\"},\"video/rtp-enc-aescm128\":{\"source\":\"iana\"},\"video/rtploopback\":{\"source\":\"iana\"},\"video/rtx\":{\"source\":\"iana\"},\"video/smpte291\":{\"source\":\"iana\"},\"video/smpte292m\":{\"source\":\"iana\"},\"video/ulpfec\":{\"source\":\"iana\"},\"video/vc1\":{\"source\":\"iana\"},\"video/vc2\":{\"source\":\"iana\"},\"video/vnd.cctv\":{\"source\":\"iana\"},\"video/vnd.dece.hd\":{\"source\":\"iana\",\"extensions\":[\"uvh\",\"uvvh\"]},\"video/vnd.dece.mobile\":{\"source\":\"iana\",\"extensions\":[\"uvm\",\"uvvm\"]},\"video/vnd.dece.mp4\":{\"source\":\"iana\"},\"video/vnd.dece.pd\":{\"source\":\"iana\",\"extensions\":[\"uvp\",\"uvvp\"]},\"video/vnd.dece.sd\":{\"source\":\"iana\",\"extensions\":[\"uvs\",\"uvvs\"]},\"video/vnd.dece.video\":{\"source\":\"iana\",\"extensions\":[\"uvv\",\"uvvv\"]},\"video/vnd.directv.mpeg\":{\"source\":\"iana\"},\"video/vnd.directv.mpeg-tts\":{\"source\":\"iana\"},\"video/vnd.dlna.mpeg-tts\":{\"source\":\"iana\"},\"video/vnd.dvb.file\":{\"source\":\"iana\",\"extensions\":[\"dvb\"]},\"video/vnd.fvt\":{\"source\":\"iana\",\"extensions\":[\"fvt\"]},\"video/vnd.hns.video\":{\"source\":\"iana\"},\"video/vnd.iptvforum.1dparityfec-1010\":{\"source\":\"iana\"},\"video/vnd.iptvforum.1dparityfec-2005\":{\"source\":\"iana\"},\"video/vnd.iptvforum.2dparityfec-1010\":{\"source\":\"iana\"},\"video/vnd.iptvforum.2dparityfec-2005\":{\"source\":\"iana\"},\"video/vnd.iptvforum.ttsavc\":{\"source\":\"iana\"},\"video/vnd.iptvforum.ttsmpeg2\":{\"source\":\"iana\"},\"video/vnd.motorola.video\":{\"source\":\"iana\"},\"video/vnd.motorola.videop\":{\"source\":\"iana\"},\"video/vnd.mpegurl\":{\"source\":\"iana\",\"extensions\":[\"mxu\",\"m4u\"]},\"video/vnd.ms-playready.media.pyv\":{\"source\":\"iana\",\"extensions\":[\"pyv\"]},\"video/vnd.nokia.interleaved-multimedia\":{\"source\":\"iana\"},\"video/vnd.nokia.mp4vr\":{\"source\":\"iana\"},\"video/vnd.nokia.videovoip\":{\"source\":\"iana\"},\"video/vnd.objectvideo\":{\"source\":\"iana\"},\"video/vnd.radgamettools.bink\":{\"source\":\"iana\"},\"video/vnd.radgamettools.smacker\":{\"source\":\"iana\"},\"video/vnd.sealed.mpeg1\":{\"source\":\"iana\"},\"video/vnd.sealed.mpeg4\":{\"source\":\"iana\"},\"video/vnd.sealed.swf\":{\"source\":\"iana\"},\"video/vnd.sealedmedia.softseal.mov\":{\"source\":\"iana\"},\"video/vnd.uvvu.mp4\":{\"source\":\"iana\",\"extensions\":[\"uvu\",\"uvvu\"]},\"video/vnd.vivo\":{\"source\":\"iana\",\"extensions\":[\"viv\"]},\"video/vnd.youtube.yt\":{\"source\":\"iana\"},\"video/vp8\":{\"source\":\"iana\"},\"video/webm\":{\"source\":\"apache\",\"compressible\":false,\"extensions\":[\"webm\"]},\"video/x-f4v\":{\"source\":\"apache\",\"extensions\":[\"f4v\"]},\"video/x-fli\":{\"source\":\"apache\",\"extensions\":[\"fli\"]},\"video/x-flv\":{\"source\":\"apache\",\"compressible\":false,\"extensions\":[\"flv\"]},\"video/x-m4v\":{\"source\":\"apache\",\"extensions\":[\"m4v\"]},\"video/x-matroska\":{\"source\":\"apache\",\"compressible\":false,\"extensions\":[\"mkv\",\"mk3d\",\"mks\"]},\"video/x-mng\":{\"source\":\"apache\",\"extensions\":[\"mng\"]},\"video/x-ms-asf\":{\"source\":\"apache\",\"extensions\":[\"asf\",\"asx\"]},\"video/x-ms-vob\":{\"source\":\"apache\",\"extensions\":[\"vob\"]},\"video/x-ms-wm\":{\"source\":\"apache\",\"extensions\":[\"wm\"]},\"video/x-ms-wmv\":{\"source\":\"apache\",\"compressible\":false,\"extensions\":[\"wmv\"]},\"video/x-ms-wmx\":{\"source\":\"apache\",\"extensions\":[\"wmx\"]},\"video/x-ms-wvx\":{\"source\":\"apache\",\"extensions\":[\"wvx\"]},\"video/x-msvideo\":{\"source\":\"apache\",\"extensions\":[\"avi\"]},\"video/x-sgi-movie\":{\"source\":\"apache\",\"extensions\":[\"movie\"]},\"video/x-smv\":{\"source\":\"apache\",\"extensions\":[\"smv\"]},\"x-conference/x-cooltalk\":{\"source\":\"apache\",\"extensions\":[\"ice\"]},\"x-shader/x-fragment\":{\"compressible\":true},\"x-shader/x-vertex\":{\"compressible\":true}}"); + +/***/ }), + +/***/ "../../node_modules/mime-db/index.js": +/***/ (function(module, exports, __webpack_require__) { + +/*! + * mime-db + * Copyright(c) 2014 Jonathan Ong + * MIT Licensed + */ + +/** + * Module exports. + */ + +module.exports = __webpack_require__("../../node_modules/mime-db/db.json") + + +/***/ }), + +/***/ "../../node_modules/mime-types/index.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/*! + * mime-types + * Copyright(c) 2014 Jonathan Ong + * Copyright(c) 2015 Douglas Christopher Wilson + * MIT Licensed + */ + + + +/** + * Module dependencies. + * @private + */ + +var db = __webpack_require__("../../node_modules/mime-db/index.js") +var extname = __webpack_require__("path").extname + +/** + * Module variables. + * @private + */ + +var EXTRACT_TYPE_REGEXP = /^\s*([^;\s]*)(?:;|\s|$)/ +var TEXT_TYPE_REGEXP = /^text\//i + +/** + * Module exports. + * @public + */ + +exports.charset = charset +exports.charsets = { lookup: charset } +exports.contentType = contentType +exports.extension = extension +exports.extensions = Object.create(null) +exports.lookup = lookup +exports.types = Object.create(null) + +// Populate the extensions/types maps +populateMaps(exports.extensions, exports.types) + +/** + * Get the default charset for a MIME type. + * + * @param {string} type + * @return {boolean|string} + */ + +function charset (type) { + if (!type || typeof type !== 'string') { + return false + } + + // TODO: use media-typer + var match = EXTRACT_TYPE_REGEXP.exec(type) + var mime = match && db[match[1].toLowerCase()] + + if (mime && mime.charset) { + return mime.charset + } + + // default text/* to utf-8 + if (match && TEXT_TYPE_REGEXP.test(match[1])) { + return 'UTF-8' + } + + return false +} + +/** + * Create a full Content-Type header given a MIME type or extension. + * + * @param {string} str + * @return {boolean|string} + */ + +function contentType (str) { + // TODO: should this even be in this module? + if (!str || typeof str !== 'string') { + return false + } + + var mime = str.indexOf('/') === -1 + ? exports.lookup(str) + : str + + if (!mime) { + return false + } + + // TODO: use content-type or other module + if (mime.indexOf('charset') === -1) { + var charset = exports.charset(mime) + if (charset) mime += '; charset=' + charset.toLowerCase() + } + + return mime +} + +/** + * Get the default extension for a MIME type. + * + * @param {string} type + * @return {boolean|string} + */ + +function extension (type) { + if (!type || typeof type !== 'string') { + return false + } + + // TODO: use media-typer + var match = EXTRACT_TYPE_REGEXP.exec(type) + + // get extensions + var exts = match && exports.extensions[match[1].toLowerCase()] + + if (!exts || !exts.length) { + return false + } + + return exts[0] +} + +/** + * Lookup the MIME type for a file path/extension. + * + * @param {string} path + * @return {boolean|string} + */ + +function lookup (path) { + if (!path || typeof path !== 'string') { + return false + } + + // get the extension ("ext" or ".ext" or full path) + var extension = extname('x.' + path) + .toLowerCase() + .substr(1) + + if (!extension) { + return false + } + + return exports.types[extension] || false +} + +/** + * Populate the extensions and types maps. + * @private + */ + +function populateMaps (extensions, types) { + // source preference (least -> most) + var preference = ['nginx', 'apache', undefined, 'iana'] + + Object.keys(db).forEach(function forEachMimeType (type) { + var mime = db[type] + var exts = mime.extensions + + if (!exts || !exts.length) { + return + } + + // mime -> extensions + extensions[type] = exts + + // extension -> mime + for (var i = 0; i < exts.length; i++) { + var extension = exts[i] + + if (types[extension]) { + var from = preference.indexOf(db[types[extension]].source) + var to = preference.indexOf(mime.source) + + if (types[extension] !== 'application/octet-stream' && + (from > to || (from === to && types[extension].substr(0, 12) === 'application/'))) { + // skip the remapping + continue + } + } + + // set the extension -> mime + types[extension] = type + } + }) +} + + /***/ }), /***/ "../../node_modules/mimic-fn/index.js": diff --git a/src/dev/build/lib/integration_tests/download.test.ts b/src/dev/build/lib/integration_tests/download.test.ts index 4c5b7025da098..7046a831d84f0 100644 --- a/src/dev/build/lib/integration_tests/download.test.ts +++ b/src/dev/build/lib/integration_tests/download.test.ts @@ -196,7 +196,7 @@ describe('downloadToDisk', () => { retryDelaySecMultiplier: 0.1, }); await expect(promise).rejects.toMatchInlineSnapshot( - `[Error: Request failed with status code 500]` + `[AxiosError: Request failed with status code 500]` ); expect(logWritter.messages).toMatchInlineSnapshot(` Array [ @@ -269,7 +269,7 @@ describe('downloadToString', () => { maxAttempts: 1, }); await expect(promise).rejects.toMatchInlineSnapshot( - `[Error: Request failed with status code 200]` + `[AxiosError: Request failed with status code 200]` ); expect(logWritter.messages).toMatchInlineSnapshot(` Array [ diff --git a/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.ts index a7a9d135f2f2e..c367c9ea44919 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.ts @@ -18,6 +18,7 @@ export const request = async ({ method = 'get', data, configurationUtilities, + headers, ...rest }: { axios: AxiosInstance; @@ -37,6 +38,8 @@ export const request = async ({ return await axios(url, { ...rest, method, + // Axios doesn't support `null` value for `headers` property. + headers: headers ?? undefined, data: data ?? {}, // use httpAgent and httpsAgent and set axios proxy: false, to be able to handle fail on invalid certs httpAgent, diff --git a/x-pack/plugins/actions/server/builtin_action_types/servicenow/utils.test.ts b/x-pack/plugins/actions/server/builtin_action_types/servicenow/utils.test.ts index 64a80977709e5..54cfa146c7e22 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/servicenow/utils.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/servicenow/utils.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import axios, { AxiosError } from 'axios'; +import axios from 'axios'; import { Logger } from '@kbn/core/server'; import { loggingSystemMock } from '@kbn/core/server/mocks'; @@ -16,6 +16,7 @@ import { throwIfSubActionIsNotSupported, getAxiosInstance, } from './utils'; +import type { ResponseError } from './types'; import { connectorTokenClientMock } from '../lib/connector_token_client.mock'; import { actionsConfigMock } from '../../actions_config.mock'; import { getOAuthJwtAccessToken } from '../lib/get_oauth_jwt_access_token'; @@ -73,7 +74,7 @@ describe('utils', () => { const axiosError = { message: 'An error occurred', response: { data: { error: { message: 'Denied', detail: 'no access' } } }, - } as AxiosError; + } as ResponseError; expect(createServiceError(axiosError, 'Unable to do action').message).toBe( '[Action][ServiceNow]: Unable to do action. Error: An error occurred Reason: Denied: no access' @@ -84,7 +85,7 @@ describe('utils', () => { const axiosError = { message: 'An error occurred', response: { data: { error: null } }, - } as AxiosError; + } as ResponseError; expect(createServiceError(axiosError, 'Unable to do action').message).toBe( '[Action][ServiceNow]: Unable to do action. Error: An error occurred Reason: unknown: no error in error response' diff --git a/x-pack/plugins/actions/server/builtin_action_types/servicenow/utils.ts b/x-pack/plugins/actions/server/builtin_action_types/servicenow/utils.ts index 538967269b1ea..f457220debb6d 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/servicenow/utils.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/servicenow/utils.ts @@ -134,7 +134,11 @@ export const getAxiosInstance = ({ tokenUrl: `${snServiceUrl}/oauth_token.do`, connectorTokenClient, }); - axiosConfig.headers.Authorization = accessToken; + + if (accessToken) { + axiosConfig.headers = { ...axiosConfig.headers, Authorization: accessToken }; + } + return axiosConfig; }, (error) => { diff --git a/x-pack/plugins/actions/server/builtin_action_types/webhook.ts b/x-pack/plugins/actions/server/builtin_action_types/webhook.ts index a36b971635e36..01d50fd623ff6 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/webhook.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/webhook.ts @@ -158,7 +158,7 @@ export async function executor( const axiosInstance = axios.create(); - const result: Result = await promiseResult( + const result: Result> = await promiseResult( request({ axios: axiosInstance, method, diff --git a/x-pack/plugins/apm/scripts/create_apm_users_and_roles/helpers/call_kibana.ts b/x-pack/plugins/apm/scripts/create_apm_users_and_roles/helpers/call_kibana.ts index e87c6ac7c8544..00ca3506a4281 100644 --- a/x-pack/plugins/apm/scripts/create_apm_users_and_roles/helpers/call_kibana.ts +++ b/x-pack/plugins/apm/scripts/create_apm_users_and_roles/helpers/call_kibana.ts @@ -34,7 +34,7 @@ const getBaseUrl = once(async (kibanaHostname: string) => { await axios.request({ url: kibanaHostname, maxRedirects: 0 }); } catch (e) { if (isAxiosError(e)) { - const location = e.response?.headers?.location; + const location = e.response?.headers?.location ?? ''; const hasBasePath = RegExp(/^\/\w{3}$/).test(location); const basePath = hasBasePath ? location : ''; return `${kibanaHostname}${basePath}`; diff --git a/x-pack/plugins/canvas/common/lib/fetch.test.ts b/x-pack/plugins/canvas/common/lib/fetch.test.ts index a76ba12f30a60..1ccd6173e0cb0 100644 --- a/x-pack/plugins/canvas/common/lib/fetch.test.ts +++ b/x-pack/plugins/canvas/common/lib/fetch.test.ts @@ -6,18 +6,23 @@ */ import { fetch, arrayBufferFetch } from './fetch'; +import { AxiosInstance, HeadersDefaults } from 'axios'; describe('fetch', () => { + // WORKAROUND: wrong Axios types, should be fixed in https://github.com/axios/axios/pull/4475 + const getDefaultHeader = (axiosInstance: AxiosInstance, headerName: string) => + (axiosInstance.defaults.headers as HeadersDefaults & Record)[headerName]; + it('test fetch headers', () => { - expect(fetch.defaults.headers.Accept).toBe('application/json'); - expect(fetch.defaults.headers['Content-Type']).toBe('application/json'); - expect(fetch.defaults.headers['kbn-xsrf']).toBe('professionally-crafted-string-of-text'); + expect(getDefaultHeader(fetch, 'Accept')).toBe('application/json'); + expect(getDefaultHeader(fetch, 'Content-Type')).toBe('application/json'); + expect(getDefaultHeader(fetch, 'kbn-xsrf')).toBe('professionally-crafted-string-of-text'); }); it('test arrayBufferFetch headers', () => { - expect(arrayBufferFetch.defaults.headers.Accept).toBe('application/json'); - expect(arrayBufferFetch.defaults.headers['Content-Type']).toBe('application/json'); - expect(arrayBufferFetch.defaults.headers['kbn-xsrf']).toBe( + expect(getDefaultHeader(arrayBufferFetch, 'Accept')).toBe('application/json'); + expect(getDefaultHeader(arrayBufferFetch, 'Content-Type')).toBe('application/json'); + expect(getDefaultHeader(arrayBufferFetch, 'kbn-xsrf')).toBe( 'professionally-crafted-string-of-text' ); expect(arrayBufferFetch.defaults.responseType).toBe('arraybuffer'); diff --git a/x-pack/plugins/fleet/server/telemetry/sender.ts b/x-pack/plugins/fleet/server/telemetry/sender.ts index a2f9bcafbcbb8..8c53fc850741f 100644 --- a/x-pack/plugins/fleet/server/telemetry/sender.ts +++ b/x-pack/plugins/fleet/server/telemetry/sender.ts @@ -168,7 +168,7 @@ export class TelemetryEventsSender { const resp = await axios.post(telemetryUrl, ndjson, { headers: { 'Content-Type': 'application/x-ndjson', - 'X-Elastic-Cluster-ID': clusterUuid, + ...(clusterUuid ? { 'X-Elastic-Cluster-ID': clusterUuid } : undefined), 'X-Elastic-Stack-Version': clusterVersionNumber ? clusterVersionNumber : '7.16.0', }, }); diff --git a/x-pack/plugins/osquery/server/lib/telemetry/sender.ts b/x-pack/plugins/osquery/server/lib/telemetry/sender.ts index ab5af7d60f466..a2acc2fe8ec6f 100644 --- a/x-pack/plugins/osquery/server/lib/telemetry/sender.ts +++ b/x-pack/plugins/osquery/server/lib/telemetry/sender.ts @@ -267,8 +267,8 @@ export class TelemetryEventsSender { const resp = await axios.post(telemetryUrl, ndjson, { headers: { 'Content-Type': 'application/x-ndjson', - 'X-Elastic-Cluster-ID': clusterUuid, - 'X-Elastic-Cluster-Name': clusterName, + ...(clusterUuid ? { 'X-Elastic-Cluster-ID': clusterUuid } : undefined), + ...(clusterName ? { 'X-Elastic-Cluster-Name': clusterName } : undefined), 'X-Elastic-Stack-Version': clusterVersionNumber ? clusterVersionNumber : '8.0.0', ...(licenseId ? { 'X-Elastic-License-ID': licenseId } : {}), }, diff --git a/x-pack/plugins/security_solution/scripts/endpoint/blocklists/index.ts b/x-pack/plugins/security_solution/scripts/endpoint/blocklists/index.ts index 3ed2ea6e7f1b3..9135378c4f007 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/blocklists/index.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/blocklists/index.ts @@ -55,7 +55,7 @@ class BlocklistDataLoaderError extends Error { } } -const handleThrowAxiosHttpError = (err: AxiosError): never => { +const handleThrowAxiosHttpError = (err: AxiosError<{ message?: string }>): never => { let message = err.message; if (err.response) { diff --git a/x-pack/plugins/security_solution/scripts/endpoint/event_filters/index.ts b/x-pack/plugins/security_solution/scripts/endpoint/event_filters/index.ts index 05baa6d4ade04..35dfc767db670 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/event_filters/index.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/event_filters/index.ts @@ -59,7 +59,7 @@ class EventFilterDataLoaderError extends Error { } } -const handleThrowAxiosHttpError = (err: AxiosError): never => { +const handleThrowAxiosHttpError = (err: AxiosError<{ message?: string }>): never => { let message = err.message; if (err.response) { diff --git a/x-pack/plugins/security_solution/scripts/endpoint/host_isolation_exceptions/index.ts b/x-pack/plugins/security_solution/scripts/endpoint/host_isolation_exceptions/index.ts index bbb80eaaa0ab6..1c1ec12dd0235 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/host_isolation_exceptions/index.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/host_isolation_exceptions/index.ts @@ -53,7 +53,7 @@ class HostIsolationExceptionDataLoaderError extends Error { } } -const handleThrowAxiosHttpError = (err: AxiosError): never => { +const handleThrowAxiosHttpError = (err: AxiosError<{ message?: string }>): never => { let message = err.message; if (err.response) { diff --git a/x-pack/plugins/security_solution/server/lib/telemetry/sender.ts b/x-pack/plugins/security_solution/server/lib/telemetry/sender.ts index 218afc7bc69a1..7490038abddd0 100644 --- a/x-pack/plugins/security_solution/server/lib/telemetry/sender.ts +++ b/x-pack/plugins/security_solution/server/lib/telemetry/sender.ts @@ -299,8 +299,8 @@ export class TelemetryEventsSender implements ITelemetryEventsSender { const resp = await axiosInstance.post(telemetryUrl, ndjson, { headers: { 'Content-Type': 'application/x-ndjson', - 'X-Elastic-Cluster-ID': clusterUuid, - 'X-Elastic-Cluster-Name': clusterName, + ...(clusterUuid ? { 'X-Elastic-Cluster-ID': clusterUuid } : undefined), + ...(clusterName ? { 'X-Elastic-Cluster-Name': clusterName } : undefined), 'X-Elastic-Stack-Version': clusterVersionNumber ? clusterVersionNumber : '8.0.0', ...(licenseId ? { 'X-Elastic-License-ID': licenseId } : {}), }, diff --git a/x-pack/plugins/synthetics/server/lib/telemetry/sender.ts b/x-pack/plugins/synthetics/server/lib/telemetry/sender.ts index 7a5239d7e2470..5130ea034f94d 100644 --- a/x-pack/plugins/synthetics/server/lib/telemetry/sender.ts +++ b/x-pack/plugins/synthetics/server/lib/telemetry/sender.ts @@ -174,8 +174,8 @@ export class TelemetryEventsSender { const resp = await axios.post(telemetryUrl, ndjson, { headers: { 'Content-Type': 'application/x-ndjson', - 'X-Elastic-Cluster-ID': clusterUuid, - 'X-Elastic-Cluster-Name': clusterName, + ...(clusterUuid ? { 'X-Elastic-Cluster-ID': clusterUuid } : undefined), + ...(clusterName ? { 'X-Elastic-Cluster-Name': clusterName } : undefined), 'X-Elastic-Stack-Version': clusterVersionNumber ? clusterVersionNumber : '8.2.0', }, }); diff --git a/x-pack/test/performance/services/auth.ts b/x-pack/test/performance/services/auth.ts index 90e20c36e59d9..282369751472e 100644 --- a/x-pack/test/performance/services/auth.ts +++ b/x-pack/test/performance/services/auth.ts @@ -15,7 +15,7 @@ export interface Credentials { } function extractCookieValue(authResponse: AxiosResponse) { - return authResponse.headers['set-cookie'][0].toString().split(';')[0].split('sid=')[1] as string; + return authResponse.headers['set-cookie']?.[0].toString().split(';')[0].split('sid=')[1] ?? ''; } export class AuthService extends FtrService { private readonly kibanaServer = this.ctx.getService('kibanaServer'); diff --git a/x-pack/test/ui_capabilities/common/services/ui_capabilities.ts b/x-pack/test/ui_capabilities/common/services/ui_capabilities.ts index 3c3febcc30686..9cb3da7e8fd5c 100644 --- a/x-pack/test/ui_capabilities/common/services/ui_capabilities.ts +++ b/x-pack/test/ui_capabilities/common/services/ui_capabilities.ts @@ -5,7 +5,7 @@ * 2.0. */ -import axios, { AxiosInstance } from 'axios'; +import axios, { AxiosInstance, AxiosRequestHeaders } from 'axios'; import type { Capabilities as UICapabilities } from '@kbn/core/types'; import { format as formatUrl } from 'url'; import util from 'util'; @@ -61,7 +61,7 @@ export class UICapabilitiesService { this.log.debug( `requesting ${spaceUrlPrefix}/api/core/capabilities to parse the uiCapabilities` ); - const requestHeaders = credentials + const requestHeaders: AxiosRequestHeaders = credentials ? { Authorization: `Basic ${Buffer.from( `${credentials.username}:${credentials.password}` diff --git a/yarn.lock b/yarn.lock index 8b99f612b3b92..b368ab0140d36 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8693,11 +8693,11 @@ axe-core@^4.2.0: integrity sha512-WKTW1+xAzhMS5dJsxWkliixlO/PqC4VhmO9T4juNYcaTg9jzWiJsou6m5pxWYGfigWbwzJWeFY6z47a+4neRXA== axios@^0.21.1: - version "0.21.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8" - integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA== + version "0.21.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" + integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== dependencies: - follow-redirects "^1.10.0" + follow-redirects "^1.14.0" axios@^0.24.0: version "0.24.0" @@ -8713,6 +8713,14 @@ axios@^0.25.0: dependencies: follow-redirects "^1.14.7" +axios@^0.27.2: + version "0.27.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972" + integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ== + dependencies: + follow-redirects "^1.14.9" + form-data "^4.0.0" + axobject-query@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" @@ -14743,10 +14751,10 @@ follow-redirects@1.12.1: resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.12.1.tgz#de54a6205311b93d60398ebc01cf7015682312b6" integrity sha512-tmRv0AVuR7ZyouUHLeNSiO6pqulF7dYa3s19c6t+wz9LD69/uSzdMxJ2S91nTI9U3rt/IldxpzMOFejp6f0hjg== -follow-redirects@^1.0.0, follow-redirects@^1.10.0, follow-redirects@^1.14.4, follow-redirects@^1.14.7: - version "1.14.9" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7" - integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w== +follow-redirects@^1.0.0, follow-redirects@^1.14.0, follow-redirects@^1.14.4, follow-redirects@^1.14.7, follow-redirects@^1.14.9: + version "1.15.0" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.0.tgz#06441868281c86d0dda4ad8bdaead2d02dca89d4" + integrity sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ== font-awesome@4.7.0: version "4.7.0" @@ -25435,7 +25443,7 @@ rxjs-marbles@^5.0.6: dependencies: fast-equals "^2.0.0" -rxjs@^6.3.3, rxjs@^6.4.0, rxjs@^6.5.1, rxjs@^6.6.0, rxjs@^6.6.3: +rxjs@^6.3.3, rxjs@^6.4.0, rxjs@^6.5.1, rxjs@^6.6.0: version "6.6.3" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.3.tgz#8ca84635c4daa900c0d3967a6ee7ac60271ee552" integrity sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ== @@ -29651,17 +29659,6 @@ w3c-xmlserializer@^2.0.0: dependencies: xml-name-validator "^3.0.0" -wait-on@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-5.2.1.tgz#05b66fcb4d7f5da01537f03e7cf96e8836422996" - integrity sha512-H2F986kNWMU9hKlI9l/ppO6tN8ZSJd35yBljMLa1/vjzWP++Qh6aXyt77/u7ySJFZQqBtQxnvm/xgG48AObXcw== - dependencies: - axios "^0.21.1" - joi "^17.3.0" - lodash "^4.17.20" - minimist "^1.2.5" - rxjs "^6.6.3" - walk@^2.3.14: version "2.3.14" resolved "https://registry.yarnpkg.com/walk/-/walk-2.3.14.tgz#60ec8631cfd23276ae1e7363ce11d626452e1ef3" From d46d101b64410f0d0973ad8ef27e4c757ea555e1 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Thu, 12 May 2022 13:56:15 +0300 Subject: [PATCH 3/9] TSVB] Chart is failing when the user tries to add a percentile_rank (#132105) Closes: #131999 --- .../components/aggs/percentile_rank/percentile_rank.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/vis_types/timeseries/public/application/components/aggs/percentile_rank/percentile_rank.tsx b/src/plugins/vis_types/timeseries/public/application/components/aggs/percentile_rank/percentile_rank.tsx index fd689f917030b..4252bb9f0f5aa 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/aggs/percentile_rank/percentile_rank.tsx +++ b/src/plugins/vis_types/timeseries/public/application/components/aggs/percentile_rank/percentile_rank.tsx @@ -112,7 +112,7 @@ export const PercentileRankAgg = (props: PercentileRankAggProps) => { indexPattern={indexPattern} value={model.field ?? ''} onChange={(value) => - props.onChange({ + handleChange({ field: value?.[0], }) } From 66332425ba9ed9eb41800538745f226425f0fabb Mon Sep 17 00:00:00 2001 From: Larry Gregory Date: Thu, 12 May 2022 06:59:16 -0400 Subject: [PATCH 4/9] unskip flaky test (#132015) --- .../apps/saved_objects_management/spaces_integration.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/x-pack/test/functional/apps/saved_objects_management/spaces_integration.ts b/x-pack/test/functional/apps/saved_objects_management/spaces_integration.ts index 509cfbbab666f..62c742e39d02b 100644 --- a/x-pack/test/functional/apps/saved_objects_management/spaces_integration.ts +++ b/x-pack/test/functional/apps/saved_objects_management/spaces_integration.ts @@ -31,8 +31,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { return bools.every((currBool) => currBool === true); }; - // FLAKY: https://github.com/elastic/kibana/issues/115303 - describe.skip('spaces integration', () => { + describe('spaces integration', () => { before(async () => { await spacesService.create({ id: spaceId, name: spaceId }); await kibanaServer.importExport.load( From d6805f9a8a8425298e354eb868cf43250d57e3eb Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Thu, 12 May 2022 13:02:05 +0200 Subject: [PATCH 5/9] fix time shift bug (#132000) --- .../data/common/search/aggs/buckets/date_histogram.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/plugins/data/common/search/aggs/buckets/date_histogram.ts b/src/plugins/data/common/search/aggs/buckets/date_histogram.ts index e1f5d31075d55..1d776bf643e1b 100644 --- a/src/plugins/data/common/search/aggs/buckets/date_histogram.ts +++ b/src/plugins/data/common/search/aggs/buckets/date_histogram.ts @@ -310,7 +310,11 @@ export const getDateHistogramBucketAgg = ({ return; } - if (agg.params.extendToTimeRange && agg.buckets.hasBounds()) { + if ( + agg.params.extendToTimeRange && + agg.buckets.hasBounds() && + !agg.aggConfigs.hasTimeShifts() + ) { const bucketBounds = agg.buckets.getBounds()!; output.params.extended_bounds = omitBy( { From 6df1b28a82fa2f3bfd1bcc1a653a6234af3c7717 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Thu, 12 May 2022 13:36:53 +0200 Subject: [PATCH 6/9] [ML] Explain log rate spikes: Plugin setup (#131317) Sets up the boilerplate code for the aiops plugin and adds a demo page within the ML app to demonstrate single API request data streaming from Kibana server to UI client. --- .github/CODEOWNERS | 5 +- docs/developer/plugin-list.asciidoc | 4 + packages/kbn-optimizer/limits.yml | 1 + tsconfig.base.json | 2 + x-pack/.i18nrc.json | 1 + x-pack/plugins/aiops/README.md | 9 + .../aiops/common/api/example_stream.ts | 68 +++++++ x-pack/plugins/aiops/common/api/index.ts | 19 ++ x-pack/plugins/aiops/common/index.ts | 22 +++ x-pack/plugins/aiops/jest.config.js | 15 ++ x-pack/plugins/aiops/kibana.json | 16 ++ x-pack/plugins/aiops/public/api/index.ts | 15 ++ .../plugins/aiops/public/components/app.tsx | 167 ++++++++++++++++++ .../components/explain_log_rate_spikes.tsx | 34 ++++ .../public/components/get_status_message.tsx | 22 +++ .../aiops/public/components/stream_fetch.ts | 80 +++++++++ .../aiops/public/components/stream_reducer.ts | 86 +++++++++ .../components/use_stream_fetch_reducer.ts | 67 +++++++ x-pack/plugins/aiops/public/index.ts | 18 ++ .../plugins/aiops/public/kibana_services.ts | 19 ++ .../aiops/public/lazy_load_bundle/index.ts | 30 ++++ .../public/lazy_load_bundle/lazy/index.ts | 9 + x-pack/plugins/aiops/public/plugin.ts | 25 +++ x-pack/plugins/aiops/public/types.ts | 21 +++ x-pack/plugins/aiops/server/index.ts | 15 ++ x-pack/plugins/aiops/server/plugin.ts | 36 ++++ x-pack/plugins/aiops/server/routes/index.ts | 129 ++++++++++++++ x-pack/plugins/aiops/server/types.ts | 18 ++ x-pack/plugins/aiops/tsconfig.json | 28 +++ x-pack/plugins/ml/common/constants/locator.ts | 2 + x-pack/plugins/ml/common/types/locator.ts | 4 +- x-pack/plugins/ml/kibana.json | 1 + .../aiops/explain_log_rate_spikes.tsx | 49 +++++ .../ml/public/application/aiops/index.ts | 8 + x-pack/plugins/ml/public/application/app.tsx | 2 + .../components/ml_page/ml_page.tsx | 5 +- .../components/ml_page/side_nav.tsx | 25 ++- .../contexts/kibana/kibana_context.ts | 2 + .../public/application/routing/breadcrumbs.ts | 8 + .../ml/public/application/routing/router.tsx | 1 + .../routes/aiops/explain_log_rate_spikes.tsx | 63 +++++++ .../application/routing/routes/aiops/index.ts | 8 + .../application/routing/routes/index.ts | 1 + .../application/util/dependency_cache.ts | 4 + .../plugins/ml/public/locator/ml_locator.ts | 2 + x-pack/plugins/ml/public/plugin.ts | 3 + x-pack/plugins/ml/tsconfig.json | 1 + .../apis/aiops/example_stream.ts | 104 +++++++++++ .../test/api_integration/apis/aiops/index.ts | 16 ++ x-pack/test/api_integration/apis/index.ts | 1 + 50 files changed, 1286 insertions(+), 5 deletions(-) create mode 100755 x-pack/plugins/aiops/README.md create mode 100644 x-pack/plugins/aiops/common/api/example_stream.ts create mode 100644 x-pack/plugins/aiops/common/api/index.ts create mode 100755 x-pack/plugins/aiops/common/index.ts create mode 100644 x-pack/plugins/aiops/jest.config.js create mode 100755 x-pack/plugins/aiops/kibana.json create mode 100644 x-pack/plugins/aiops/public/api/index.ts create mode 100755 x-pack/plugins/aiops/public/components/app.tsx create mode 100644 x-pack/plugins/aiops/public/components/explain_log_rate_spikes.tsx create mode 100644 x-pack/plugins/aiops/public/components/get_status_message.tsx create mode 100644 x-pack/plugins/aiops/public/components/stream_fetch.ts create mode 100644 x-pack/plugins/aiops/public/components/stream_reducer.ts create mode 100644 x-pack/plugins/aiops/public/components/use_stream_fetch_reducer.ts create mode 100755 x-pack/plugins/aiops/public/index.ts create mode 100644 x-pack/plugins/aiops/public/kibana_services.ts create mode 100644 x-pack/plugins/aiops/public/lazy_load_bundle/index.ts create mode 100644 x-pack/plugins/aiops/public/lazy_load_bundle/lazy/index.ts create mode 100755 x-pack/plugins/aiops/public/plugin.ts create mode 100755 x-pack/plugins/aiops/public/types.ts create mode 100755 x-pack/plugins/aiops/server/index.ts create mode 100755 x-pack/plugins/aiops/server/plugin.ts create mode 100755 x-pack/plugins/aiops/server/routes/index.ts create mode 100755 x-pack/plugins/aiops/server/types.ts create mode 100644 x-pack/plugins/aiops/tsconfig.json create mode 100644 x-pack/plugins/ml/public/application/aiops/explain_log_rate_spikes.tsx create mode 100644 x-pack/plugins/ml/public/application/aiops/index.ts create mode 100644 x-pack/plugins/ml/public/application/routing/routes/aiops/explain_log_rate_spikes.tsx create mode 100644 x-pack/plugins/ml/public/application/routing/routes/aiops/index.ts create mode 100644 x-pack/test/api_integration/apis/aiops/example_stream.ts create mode 100644 x-pack/test/api_integration/apis/aiops/index.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 450daeebd24d1..abd63289e0480 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -187,10 +187,11 @@ /x-pack/test/screenshot_creation/apps/ml_docs @elastic/ml-ui /x-pack/test/screenshot_creation/services/ml_screenshots.ts @elastic/ml-ui -# ML team owns and maintains the transform plugin despite it living in the Data management section. -/x-pack/plugins/transform/ @elastic/ml-ui +# Additional plugins maintained by the ML team. +/x-pack/plugins/aiops/ @elastic/ml-ui /x-pack/plugins/data_visualizer/ @elastic/ml-ui /x-pack/plugins/file_upload/ @elastic/ml-ui +/x-pack/plugins/transform/ @elastic/ml-ui /x-pack/test/accessibility/apps/transform.ts @elastic/ml-ui /x-pack/test/api_integration/apis/transform/ @elastic/ml-ui /x-pack/test/api_integration_basic/apis/transform/ @elastic/ml-ui diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index a91776fde65ba..0d2d69123b5f3 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -376,6 +376,10 @@ The plugin exposes the static DefaultEditorController class to consume. |The Kibana actions plugin provides a framework to create executable actions. You can: +|{kib-repo}blob/{branch}/x-pack/plugins/aiops/README.md[aiops] +|The plugin provides APIs and components for AIOps features, including the “Explain log rate spikes” UI, maintained by the ML team. + + |{kib-repo}blob/{branch}/x-pack/plugins/alerting/README.md[alerting] |The Kibana Alerting plugin provides a common place to set up rules. You can: diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index 7fbe272e01bb0..c9460f7bab4ea 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -1,6 +1,7 @@ pageLoadAssetSize: advancedSettings: 27596 actions: 20000 + aiops: 10000 alerting: 106936 apm: 64385 canvas: 1066647 diff --git a/tsconfig.base.json b/tsconfig.base.json index 78023a603276a..daf7bf78903c1 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -277,6 +277,8 @@ "@kbn/ui-actions-enhanced-examples-plugin/*": ["x-pack/examples/ui_actions_enhanced_examples/*"], "@kbn/actions-plugin": ["x-pack/plugins/actions"], "@kbn/actions-plugin/*": ["x-pack/plugins/actions/*"], + "@kbn/aiops-plugin": ["x-pack/plugins/aiops"], + "@kbn/aiops-plugin/*": ["x-pack/plugins/aiops/*"], "@kbn/alerting-plugin": ["x-pack/plugins/alerting"], "@kbn/alerting-plugin/*": ["x-pack/plugins/alerting/*"], "@kbn/apm-plugin": ["x-pack/plugins/apm"], diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json index b1464f5cfbe2e..738c5242813be 100644 --- a/x-pack/.i18nrc.json +++ b/x-pack/.i18nrc.json @@ -37,6 +37,7 @@ "xpack.logstash": ["plugins/logstash"], "xpack.main": "legacy/plugins/xpack_main", "xpack.maps": ["plugins/maps"], + "xpack.aiops": ["plugins/aiops"], "xpack.ml": ["plugins/ml"], "xpack.monitoring": ["plugins/monitoring"], "xpack.osquery": ["plugins/osquery"], diff --git a/x-pack/plugins/aiops/README.md b/x-pack/plugins/aiops/README.md new file mode 100755 index 0000000000000..9bfd64f9bf3a3 --- /dev/null +++ b/x-pack/plugins/aiops/README.md @@ -0,0 +1,9 @@ +# aiops + +The plugin provides APIs and components for AIOps features, including the “Explain log rate spikes” UI, maintained by the ML team. + +--- + +## Development + +See the [kibana contributing guide](https://github.com/elastic/kibana/blob/main/CONTRIBUTING.md) for instructions setting up your development environment. diff --git a/x-pack/plugins/aiops/common/api/example_stream.ts b/x-pack/plugins/aiops/common/api/example_stream.ts new file mode 100644 index 0000000000000..1210cccf55487 --- /dev/null +++ b/x-pack/plugins/aiops/common/api/example_stream.ts @@ -0,0 +1,68 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { schema, TypeOf } from '@kbn/config-schema'; + +export const aiopsExampleStreamSchema = schema.object({ + /** Boolean flag to enable/disabling simulation of response errors. */ + simulateErrors: schema.maybe(schema.boolean()), + /** Maximum timeout between streaming messages. */ + timeout: schema.maybe(schema.number()), +}); + +export type AiopsExampleStreamSchema = TypeOf; + +export const API_ACTION_NAME = { + UPDATE_PROGRESS: 'update_progress', + ADD_TO_ENTITY: 'add_to_entity', + DELETE_ENTITY: 'delete_entity', +} as const; +export type ApiActionName = typeof API_ACTION_NAME[keyof typeof API_ACTION_NAME]; + +interface ApiActionUpdateProgress { + type: typeof API_ACTION_NAME.UPDATE_PROGRESS; + payload: number; +} + +export function updateProgressAction(payload: number): ApiActionUpdateProgress { + return { + type: API_ACTION_NAME.UPDATE_PROGRESS, + payload, + }; +} + +interface ApiActionAddToEntity { + type: typeof API_ACTION_NAME.ADD_TO_ENTITY; + payload: { + entity: string; + value: number; + }; +} + +export function addToEntityAction(entity: string, value: number): ApiActionAddToEntity { + return { + type: API_ACTION_NAME.ADD_TO_ENTITY, + payload: { + entity, + value, + }, + }; +} + +interface ApiActionDeleteEntity { + type: typeof API_ACTION_NAME.DELETE_ENTITY; + payload: string; +} + +export function deleteEntityAction(payload: string): ApiActionDeleteEntity { + return { + type: API_ACTION_NAME.DELETE_ENTITY, + payload, + }; +} + +export type ApiAction = ApiActionUpdateProgress | ApiActionAddToEntity | ApiActionDeleteEntity; diff --git a/x-pack/plugins/aiops/common/api/index.ts b/x-pack/plugins/aiops/common/api/index.ts new file mode 100644 index 0000000000000..da1e091d3fb54 --- /dev/null +++ b/x-pack/plugins/aiops/common/api/index.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { AiopsExampleStreamSchema } from './example_stream'; + +export const API_ENDPOINT = { + EXAMPLE_STREAM: '/internal/aiops/example_stream', + ANOTHER: '/internal/aiops/another', +} as const; +export type ApiEndpoint = typeof API_ENDPOINT[keyof typeof API_ENDPOINT]; + +export interface ApiEndpointOptions { + [API_ENDPOINT.EXAMPLE_STREAM]: AiopsExampleStreamSchema; + [API_ENDPOINT.ANOTHER]: { anotherOption: string }; +} diff --git a/x-pack/plugins/aiops/common/index.ts b/x-pack/plugins/aiops/common/index.ts new file mode 100755 index 0000000000000..0f4835d67ecc7 --- /dev/null +++ b/x-pack/plugins/aiops/common/index.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +/** + * PLUGIN_ID is used as a unique identifier for the aiops plugin + */ +export const PLUGIN_ID = 'aiops'; + +/** + * PLUGIN_NAME is used as the display name for the aiops plugin + */ +export const PLUGIN_NAME = 'AIOps'; + +/** + * This is an internal hard coded feature flag so we can easily turn on/off the + * "Explain log rate spikes UI" during development until the first release. + */ +export const AIOPS_ENABLED = true; diff --git a/x-pack/plugins/aiops/jest.config.js b/x-pack/plugins/aiops/jest.config.js new file mode 100644 index 0000000000000..4b92cb8dc86cb --- /dev/null +++ b/x-pack/plugins/aiops/jest.config.js @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../..', + roots: ['/x-pack/plugins/aiops'], + coverageDirectory: '/target/kibana-coverage/jest/x-pack/plugins/aiops', + coverageReporters: ['text', 'html'], + collectCoverageFrom: ['/x-pack/plugins/aiops/{common,public,server}/**/*.{js,ts,tsx}'], +}; diff --git a/x-pack/plugins/aiops/kibana.json b/x-pack/plugins/aiops/kibana.json new file mode 100755 index 0000000000000..b74a23bf2bc9e --- /dev/null +++ b/x-pack/plugins/aiops/kibana.json @@ -0,0 +1,16 @@ +{ + "id": "aiops", + "version": "1.0.0", + "kibanaVersion": "kibana", + "owner": { + "name": "Machine Learning UI", + "githubTeam": "ml-ui" + }, + "description": "AIOps plugin maintained by ML team.", + "server": true, + "ui": true, + "requiredPlugins": [], + "optionalPlugins": [], + "requiredBundles": ["kibanaReact"], + "extraPublicDirs": ["common"] +} diff --git a/x-pack/plugins/aiops/public/api/index.ts b/x-pack/plugins/aiops/public/api/index.ts new file mode 100644 index 0000000000000..6aa171df5286c --- /dev/null +++ b/x-pack/plugins/aiops/public/api/index.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { lazyLoadModules } from '../lazy_load_bundle'; + +import type { ExplainLogRateSpikesSpec } from '../components/explain_log_rate_spikes'; + +export async function getExplainLogRateSpikesComponent(): Promise<() => ExplainLogRateSpikesSpec> { + const modules = await lazyLoadModules(); + return () => modules.ExplainLogRateSpikes; +} diff --git a/x-pack/plugins/aiops/public/components/app.tsx b/x-pack/plugins/aiops/public/components/app.tsx new file mode 100755 index 0000000000000..963253b154e27 --- /dev/null +++ b/x-pack/plugins/aiops/public/components/app.tsx @@ -0,0 +1,167 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useEffect, useState } from 'react'; + +import { Chart, Settings, Axis, BarSeries, Position, ScaleType } from '@elastic/charts'; + +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; + +import { + EuiBadge, + EuiButton, + EuiCheckbox, + EuiFlexGroup, + EuiFlexItem, + EuiPage, + EuiPageBody, + EuiPageContent, + EuiPageContentBody, + EuiPageContentHeader, + EuiProgress, + EuiSpacer, + EuiTitle, + EuiText, +} from '@elastic/eui'; + +import { getStatusMessage } from './get_status_message'; +import { initialState, resetStream, streamReducer } from './stream_reducer'; +import { useStreamFetchReducer } from './use_stream_fetch_reducer'; + +export const AiopsApp = () => { + const { notifications } = useKibana(); + + const [simulateErrors, setSimulateErrors] = useState(false); + + const { dispatch, start, cancel, data, isCancelled, isRunning } = useStreamFetchReducer( + '/internal/aiops/example_stream', + streamReducer, + initialState, + { simulateErrors } + ); + + const { errors, progress, entities } = data; + + const onClickHandler = async () => { + if (isRunning) { + cancel(); + } else { + dispatch(resetStream()); + start(); + } + }; + + useEffect(() => { + if (errors.length > 0) { + notifications.toasts.danger({ body: errors[errors.length - 1] }); + } + }, [errors, notifications.toasts]); + + const buttonLabel = isRunning + ? i18n.translate('xpack.aiops.stopbuttonText', { + defaultMessage: 'Stop development', + }) + : i18n.translate('xpack.aiops.startbuttonText', { + defaultMessage: 'Start development', + }); + + return ( + + + + + +

+ +

+
+
+ + + + + + {buttonLabel} + + + + + {progress}% + + + + + + + +
+ + + + + + { + return { + x, + y, + }; + }) + .sort((a, b) => b.y - a.y)} + /> + +
+

{getStatusMessage(isRunning, isCancelled, data.progress)}

+ setSimulateErrors(!simulateErrors)} + compressed + /> +
+
+
+
+
+ ); +}; diff --git a/x-pack/plugins/aiops/public/components/explain_log_rate_spikes.tsx b/x-pack/plugins/aiops/public/components/explain_log_rate_spikes.tsx new file mode 100644 index 0000000000000..21d7b39a2a148 --- /dev/null +++ b/x-pack/plugins/aiops/public/components/explain_log_rate_spikes.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FC } from 'react'; + +import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; +import { I18nProvider } from '@kbn/i18n-react'; + +import { getCoreStart } from '../kibana_services'; + +import { AiopsApp } from './app'; + +/** + * Spec used for lazy loading in the ML plugin + */ +export type ExplainLogRateSpikesSpec = typeof ExplainLogRateSpikes; + +export const ExplainLogRateSpikes: FC = () => { + const coreStart = getCoreStart(); + + return ( + + + + + + + + ); +}; diff --git a/x-pack/plugins/aiops/public/components/get_status_message.tsx b/x-pack/plugins/aiops/public/components/get_status_message.tsx new file mode 100644 index 0000000000000..e63748d03600a --- /dev/null +++ b/x-pack/plugins/aiops/public/components/get_status_message.tsx @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export function getStatusMessage(isRunning: boolean, isCancelled: boolean, progress: number) { + if (!isRunning && !isCancelled && progress === 0) { + return 'Development did not start yet.'; + } else if (isRunning && !isCancelled) { + return 'Development is ongoing, the hype is real!'; + } else if (!isRunning && isCancelled) { + return 'Oh no, development got cancelled!'; + } else if (!isRunning && progress === 100) { + return 'Development clompeted, the release got out the door!'; + } + + // When the process stops but wasn't cancelled by the user and progress is not yet at 100%, + // this indicates there must have been a problem with the stream. + return 'Oh no, looks like there was a bug?!'; +} diff --git a/x-pack/plugins/aiops/public/components/stream_fetch.ts b/x-pack/plugins/aiops/public/components/stream_fetch.ts new file mode 100644 index 0000000000000..37d7c13dd3b55 --- /dev/null +++ b/x-pack/plugins/aiops/public/components/stream_fetch.ts @@ -0,0 +1,80 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type React from 'react'; + +import type { ApiEndpoint, ApiEndpointOptions } from '../../common/api'; + +export async function* streamFetch( + endpoint: E, + abortCtrl: React.MutableRefObject, + options: ApiEndpointOptions[ApiEndpoint], + basePath = '' +) { + const stream = await fetch(`${basePath}${endpoint}`, { + signal: abortCtrl.current.signal, + method: 'POST', + headers: { + // This refers to the format of the request body, + // not the response, which will be a uint8array Buffer. + 'Content-Type': 'application/json', + 'kbn-xsrf': 'stream', + }, + body: JSON.stringify(options), + }); + + if (stream.body !== null) { + // Note that Firefox 99 doesn't support `TextDecoderStream` yet. + // That's why we skip it here and use `TextDecoder` later to decode each chunk. + // Once Firefox supports it, we can use the following alternative: + // const reader = stream.body.pipeThrough(new TextDecoderStream()).getReader(); + const reader = stream.body.getReader(); + + const bufferBounce = 100; + let partial = ''; + let actionBuffer: A[] = []; + let lastCall = 0; + + while (true) { + try { + const { value: uint8array, done } = await reader.read(); + if (done) break; + + const value = new TextDecoder().decode(uint8array); + + const full = `${partial}${value}`; + const parts = full.split('\n'); + const last = parts.pop(); + + partial = last ?? ''; + + const actions = parts.map((p) => JSON.parse(p)); + actionBuffer.push(...actions); + + const now = Date.now(); + + if (now - lastCall >= bufferBounce && actionBuffer.length > 0) { + yield actionBuffer; + actionBuffer = []; + lastCall = now; + } + } catch (error) { + if (error.name !== 'AbortError') { + yield { type: 'error', payload: error.toString() }; + } + break; + } + } + + // The reader might finish with a partially filled actionBuffer so + // we need to clear it once more after the request is done. + if (actionBuffer.length > 0) { + yield actionBuffer; + actionBuffer.length = 0; + } + } +} diff --git a/x-pack/plugins/aiops/public/components/stream_reducer.ts b/x-pack/plugins/aiops/public/components/stream_reducer.ts new file mode 100644 index 0000000000000..3e68e139ceeca --- /dev/null +++ b/x-pack/plugins/aiops/public/components/stream_reducer.ts @@ -0,0 +1,86 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ApiAction, API_ACTION_NAME } from '../../common/api/example_stream'; + +export const UI_ACTION_NAME = { + ERROR: 'error', + RESET: 'reset', +} as const; +export type UiActionName = typeof UI_ACTION_NAME[keyof typeof UI_ACTION_NAME]; + +export interface StreamState { + errors: string[]; + progress: number; + entities: Record; +} +export const initialState: StreamState = { + errors: [], + progress: 0, + entities: {}, +}; + +interface UiActionError { + type: typeof UI_ACTION_NAME.ERROR; + payload: string; +} +interface UiActionResetStream { + type: typeof UI_ACTION_NAME.RESET; +} + +export function resetStream(): UiActionResetStream { + return { type: UI_ACTION_NAME.RESET }; +} + +type UiAction = UiActionResetStream | UiActionError; +export type ReducerAction = ApiAction | UiAction; +export function streamReducer( + state: StreamState, + action: ReducerAction | ReducerAction[] +): StreamState { + if (Array.isArray(action)) { + return action.reduce(streamReducer, state); + } + + switch (action.type) { + case API_ACTION_NAME.UPDATE_PROGRESS: + return { + ...state, + progress: action.payload, + }; + case API_ACTION_NAME.DELETE_ENTITY: + const deleteFromEntities = { ...state.entities }; + delete deleteFromEntities[action.payload]; + return { + ...state, + entities: deleteFromEntities, + }; + case API_ACTION_NAME.ADD_TO_ENTITY: + const addToEntities = { ...state.entities }; + if (addToEntities[action.payload.entity] === undefined) { + addToEntities[action.payload.entity] = action.payload.value; + } else { + addToEntities[action.payload.entity] += action.payload.value; + } + return { + ...state, + entities: addToEntities, + }; + case UI_ACTION_NAME.RESET: + return initialState; + case UI_ACTION_NAME.ERROR: + return { + ...state, + errors: [...state.errors, action.payload], + }; + default: + return { + ...state, + errors: [...state.errors, 'UNKNOWN_ACTION_ERROR'], + }; + } +} diff --git a/x-pack/plugins/aiops/public/components/use_stream_fetch_reducer.ts b/x-pack/plugins/aiops/public/components/use_stream_fetch_reducer.ts new file mode 100644 index 0000000000000..77ac09e0ff429 --- /dev/null +++ b/x-pack/plugins/aiops/public/components/use_stream_fetch_reducer.ts @@ -0,0 +1,67 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useReducer, useRef, useState, Reducer, ReducerAction, ReducerState } from 'react'; + +import { useKibana } from '@kbn/kibana-react-plugin/public'; + +import type { ApiEndpoint, ApiEndpointOptions } from '../../common/api'; + +import { streamFetch } from './stream_fetch'; + +export const useStreamFetchReducer = , E = ApiEndpoint>( + endpoint: E, + reducer: R, + initialState: ReducerState, + options: ApiEndpointOptions[ApiEndpoint] +) => { + const kibana = useKibana(); + + const [isCancelled, setIsCancelled] = useState(false); + const [isRunning, setIsRunning] = useState(false); + + const [data, dispatch] = useReducer(reducer, initialState); + + const abortCtrl = useRef(new AbortController()); + + const start = async () => { + if (isRunning) { + throw new Error('Restart not supported yet'); + } + + setIsRunning(true); + setIsCancelled(false); + + abortCtrl.current = new AbortController(); + + for await (const actions of streamFetch( + endpoint, + abortCtrl, + options, + kibana.services.http?.basePath.get() + )) { + dispatch(actions as ReducerAction); + } + + setIsRunning(false); + }; + + const cancel = () => { + abortCtrl.current.abort(); + setIsCancelled(true); + setIsRunning(false); + }; + + return { + cancel, + data, + dispatch, + isCancelled, + isRunning, + start, + }; +}; diff --git a/x-pack/plugins/aiops/public/index.ts b/x-pack/plugins/aiops/public/index.ts new file mode 100755 index 0000000000000..30bcaf5afabdc --- /dev/null +++ b/x-pack/plugins/aiops/public/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { AiopsPlugin } from './plugin'; + +// This exports static code and TypeScript types, +// as well as, Kibana Platform `plugin()` initializer. +export function plugin() { + return new AiopsPlugin(); +} + +export type { AiopsPluginSetup, AiopsPluginStart } from './types'; + +export type { ExplainLogRateSpikesSpec } from './components/explain_log_rate_spikes'; diff --git a/x-pack/plugins/aiops/public/kibana_services.ts b/x-pack/plugins/aiops/public/kibana_services.ts new file mode 100644 index 0000000000000..9a43d2de5e5a1 --- /dev/null +++ b/x-pack/plugins/aiops/public/kibana_services.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { CoreStart } from '@kbn/core/public'; +import { AppPluginStartDependencies } from './types'; + +let coreStart: CoreStart; +let pluginsStart: AppPluginStartDependencies; +export function setStartServices(core: CoreStart, plugins: AppPluginStartDependencies) { + coreStart = core; + pluginsStart = plugins; +} + +export const getCoreStart = () => coreStart; +export const getPluginsStart = () => pluginsStart; diff --git a/x-pack/plugins/aiops/public/lazy_load_bundle/index.ts b/x-pack/plugins/aiops/public/lazy_load_bundle/index.ts new file mode 100644 index 0000000000000..0072336080175 --- /dev/null +++ b/x-pack/plugins/aiops/public/lazy_load_bundle/index.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { ExplainLogRateSpikesSpec } from '../components/explain_log_rate_spikes'; + +let loadModulesPromise: Promise; + +interface LazyLoadedModules { + ExplainLogRateSpikes: ExplainLogRateSpikesSpec; +} + +export async function lazyLoadModules(): Promise { + if (typeof loadModulesPromise !== 'undefined') { + return loadModulesPromise; + } + + loadModulesPromise = new Promise(async (resolve, reject) => { + try { + const lazyImports = await import('./lazy'); + resolve({ ...lazyImports }); + } catch (error) { + reject(error); + } + }); + return loadModulesPromise; +} diff --git a/x-pack/plugins/aiops/public/lazy_load_bundle/lazy/index.ts b/x-pack/plugins/aiops/public/lazy_load_bundle/lazy/index.ts new file mode 100644 index 0000000000000..967525de9bd6e --- /dev/null +++ b/x-pack/plugins/aiops/public/lazy_load_bundle/lazy/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export type { ExplainLogRateSpikesSpec } from '../../components/explain_log_rate_spikes'; +export { ExplainLogRateSpikes } from '../../components/explain_log_rate_spikes'; diff --git a/x-pack/plugins/aiops/public/plugin.ts b/x-pack/plugins/aiops/public/plugin.ts new file mode 100755 index 0000000000000..3c3cff39abb80 --- /dev/null +++ b/x-pack/plugins/aiops/public/plugin.ts @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { CoreSetup, CoreStart, Plugin } from '@kbn/core/public'; + +import { getExplainLogRateSpikesComponent } from './api'; +import { setStartServices } from './kibana_services'; +import { AiopsPluginSetup, AiopsPluginStart } from './types'; + +export class AiopsPlugin implements Plugin { + public setup(core: CoreSetup) {} + + public start(core: CoreStart) { + setStartServices(core, {}); + return { + getExplainLogRateSpikesComponent, + }; + } + + public stop() {} +} diff --git a/x-pack/plugins/aiops/public/types.ts b/x-pack/plugins/aiops/public/types.ts new file mode 100755 index 0000000000000..fae18dc1d3106 --- /dev/null +++ b/x-pack/plugins/aiops/public/types.ts @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { AiopsPlugin } from './plugin'; + +/** + * aiops plugin public setup contract + */ +export type AiopsPluginSetup = ReturnType; + +/** + * aiops plugin public start contract + */ +export type AiopsPluginStart = ReturnType; + +// eslint-disable-next-line +export type AppPluginStartDependencies = {}; diff --git a/x-pack/plugins/aiops/server/index.ts b/x-pack/plugins/aiops/server/index.ts new file mode 100755 index 0000000000000..8dca6eb397d5e --- /dev/null +++ b/x-pack/plugins/aiops/server/index.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { PluginInitializerContext } from '@kbn/core/server'; +import { AiopsPlugin } from './plugin'; + +export function plugin(initializerContext: PluginInitializerContext) { + return new AiopsPlugin(initializerContext); +} + +export type { AiopsPluginSetup, AiopsPluginStart } from './types'; diff --git a/x-pack/plugins/aiops/server/plugin.ts b/x-pack/plugins/aiops/server/plugin.ts new file mode 100755 index 0000000000000..c6b1b8b22a187 --- /dev/null +++ b/x-pack/plugins/aiops/server/plugin.ts @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { PluginInitializerContext, CoreSetup, CoreStart, Plugin, Logger } from '@kbn/core/server'; + +import { AiopsPluginSetup, AiopsPluginStart } from './types'; +import { defineRoutes } from './routes'; + +export class AiopsPlugin implements Plugin { + private readonly logger: Logger; + + constructor(initializerContext: PluginInitializerContext) { + this.logger = initializerContext.logger.get(); + } + + public setup(core: CoreSetup) { + this.logger.debug('aiops: Setup'); + const router = core.http.createRouter(); + + // Register server side APIs + defineRoutes(router, this.logger); + + return {}; + } + + public start(core: CoreStart) { + this.logger.debug('aiops: Started'); + return {}; + } + + public stop() {} +} diff --git a/x-pack/plugins/aiops/server/routes/index.ts b/x-pack/plugins/aiops/server/routes/index.ts new file mode 100755 index 0000000000000..e87c27e2af81e --- /dev/null +++ b/x-pack/plugins/aiops/server/routes/index.ts @@ -0,0 +1,129 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { Readable } from 'stream'; + +import type { IRouter, Logger } from '@kbn/core/server'; + +import { AIOPS_ENABLED } from '../../common'; +import type { ApiAction } from '../../common/api/example_stream'; +import { + aiopsExampleStreamSchema, + updateProgressAction, + addToEntityAction, + deleteEntityAction, +} from '../../common/api/example_stream'; + +// We need this otherwise Kibana server will crash with a 'ERR_METHOD_NOT_IMPLEMENTED' error. +class ResponseStream extends Readable { + _read(): void {} +} + +const delimiter = '\n'; + +export function defineRoutes(router: IRouter, logger: Logger) { + if (AIOPS_ENABLED) { + router.post( + { + path: '/internal/aiops/example_stream', + validate: { + body: aiopsExampleStreamSchema, + }, + }, + async (context, request, response) => { + const maxTimeoutMs = request.body.timeout ?? 250; + const simulateError = request.body.simulateErrors ?? false; + + let shouldStop = false; + request.events.aborted$.subscribe(() => { + shouldStop = true; + }); + request.events.completed$.subscribe(() => { + shouldStop = true; + }); + + const stream = new ResponseStream(); + + function streamPush(d: ApiAction) { + try { + const line = JSON.stringify(d); + stream.push(`${line}${delimiter}`); + } catch (error) { + logger.error('Could not serialize or stream a message.'); + logger.error(error); + } + } + + const entities = [ + 'kimchy', + 's1monw', + 'martijnvg', + 'jasontedor', + 'nik9000', + 'javanna', + 'rjernst', + 'jrodewig', + ]; + + const actions = [...Array(19).fill('add'), 'delete']; + + if (simulateError) { + actions.push('server-only-error'); + actions.push('server-to-client-error'); + actions.push('client-error'); + } + + let progress = 0; + + async function pushStreamUpdate() { + setTimeout(() => { + try { + progress++; + + if (progress > 100 || shouldStop) { + stream.push(null); + return; + } + + streamPush(updateProgressAction(progress)); + + const randomEntity = entities[Math.floor(Math.random() * entities.length)]; + const randomAction = actions[Math.floor(Math.random() * actions.length)]; + + if (randomAction === 'add') { + const randomCommits = Math.floor(Math.random() * 100); + streamPush(addToEntityAction(randomEntity, randomCommits)); + } else if (randomAction === 'delete') { + streamPush(deleteEntityAction(randomEntity)); + } else if (randomAction === 'server-to-client-error') { + // Throw an error. It should not crash Kibana! + throw new Error('There was a (simulated) server side error!'); + } else if (randomAction === 'client-error') { + // Return not properly encoded JSON to the client. + stream.push(`{body:'Not valid JSON${delimiter}`); + } + + pushStreamUpdate(); + } catch (error) { + stream.push( + `${JSON.stringify({ type: 'error', payload: error.toString() })}${delimiter}` + ); + stream.push(null); + } + }, Math.floor(Math.random() * maxTimeoutMs)); + } + + // do not call this using `await` so it will run asynchronously while we return the stream already. + pushStreamUpdate(); + + return response.ok({ + body: stream, + }); + } + ); + } +} diff --git a/x-pack/plugins/aiops/server/types.ts b/x-pack/plugins/aiops/server/types.ts new file mode 100755 index 0000000000000..526e7280e9495 --- /dev/null +++ b/x-pack/plugins/aiops/server/types.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +/** + * aiops plugin server setup contract + */ +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface AiopsPluginSetup {} + +/** + * aiops plugin server start contract + */ +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface AiopsPluginStart {} diff --git a/x-pack/plugins/aiops/tsconfig.json b/x-pack/plugins/aiops/tsconfig.json new file mode 100644 index 0000000000000..2545c0e21ed03 --- /dev/null +++ b/x-pack/plugins/aiops/tsconfig.json @@ -0,0 +1,28 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "../../../typings/**/*", + "common/**/*", + "public/**/*", + "scripts/**/*", + "server/**/*", + "types/**/*" + ], + "references": [ + { "path": "../../../src/core/tsconfig.json" }, + { "path": "../../../src/plugins/kibana_utils/tsconfig.json" }, + { "path": "../../../src/plugins/kibana_react/tsconfig.json" }, + { "path": "../../../src/plugins/data/tsconfig.json" }, + { "path": "../../../src/plugins/usage_collection/tsconfig.json" }, + { "path": "../../../src/plugins/custom_integrations/tsconfig.json" }, + { "path": "../../../src/plugins/navigation/tsconfig.json" }, + { "path": "../../../src/plugins/unified_search/tsconfig.json" }, + { "path": "../security/tsconfig.json" }, + ] +} diff --git a/x-pack/plugins/ml/common/constants/locator.ts b/x-pack/plugins/ml/common/constants/locator.ts index 0a1c2638e684a..0c19c5b59766c 100644 --- a/x-pack/plugins/ml/common/constants/locator.ts +++ b/x-pack/plugins/ml/common/constants/locator.ts @@ -51,6 +51,8 @@ export const ML_PAGES = { FILTER_LISTS_EDIT: 'settings/filter_lists/edit_filter_list', ACCESS_DENIED: 'access-denied', OVERVIEW: 'overview', + AIOPS: 'aiops', + AIOPS_EXPLAIN_LOG_RATE_SPIKES: 'aiops/explain_log_rate_spikes', } as const; export type MlPages = typeof ML_PAGES[keyof typeof ML_PAGES]; diff --git a/x-pack/plugins/ml/common/types/locator.ts b/x-pack/plugins/ml/common/types/locator.ts index 33ec94b825303..a440aaa349bcc 100644 --- a/x-pack/plugins/ml/common/types/locator.ts +++ b/x-pack/plugins/ml/common/types/locator.ts @@ -60,7 +60,9 @@ export type MlGenericUrlState = MLPageState< | typeof ML_PAGES.ACCESS_DENIED | typeof ML_PAGES.DATA_VISUALIZER | typeof ML_PAGES.DATA_VISUALIZER_FILE - | typeof ML_PAGES.DATA_VISUALIZER_INDEX_SELECT, + | typeof ML_PAGES.DATA_VISUALIZER_INDEX_SELECT + | typeof ML_PAGES.AIOPS + | typeof ML_PAGES.AIOPS_EXPLAIN_LOG_RATE_SPIKES, MlGenericUrlPageState | undefined >; diff --git a/x-pack/plugins/ml/kibana.json b/x-pack/plugins/ml/kibana.json index eb00ca117f01a..f62cec0ec0fca 100644 --- a/x-pack/plugins/ml/kibana.json +++ b/x-pack/plugins/ml/kibana.json @@ -7,6 +7,7 @@ "ml" ], "requiredPlugins": [ + "aiops", "cloud", "data", "dataViews", diff --git a/x-pack/plugins/ml/public/application/aiops/explain_log_rate_spikes.tsx b/x-pack/plugins/ml/public/application/aiops/explain_log_rate_spikes.tsx new file mode 100644 index 0000000000000..473525d40ca9a --- /dev/null +++ b/x-pack/plugins/ml/public/application/aiops/explain_log_rate_spikes.tsx @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FC, useEffect, useState } from 'react'; +import { FormattedMessage } from '@kbn/i18n-react'; +import type { ExplainLogRateSpikesSpec } from '@kbn/aiops-plugin/public'; +import { useMlKibana, useTimefilter } from '../contexts/kibana'; +import { HelpMenu } from '../components/help_menu'; + +import { MlPageHeader } from '../components/page_header'; + +export const ExplainLogRateSpikesPage: FC = () => { + useTimefilter({ timeRangeSelector: false, autoRefreshSelector: false }); + const { + services: { docLinks, aiops }, + } = useMlKibana(); + + const [ExplainLogRateSpikes, setExplainLogRateSpikes] = useState( + null + ); + + useEffect(() => { + if (aiops !== undefined) { + const { getExplainLogRateSpikesComponent } = aiops; + getExplainLogRateSpikesComponent().then(setExplainLogRateSpikes); + } + }, []); + + return ( + <> + {ExplainLogRateSpikes !== null ? ( + <> + + + + + + ) : null} + + + ); +}; diff --git a/x-pack/plugins/ml/public/application/aiops/index.ts b/x-pack/plugins/ml/public/application/aiops/index.ts new file mode 100644 index 0000000000000..fa47ae09822e2 --- /dev/null +++ b/x-pack/plugins/ml/public/application/aiops/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { ExplainLogRateSpikesPage } from './explain_log_rate_spikes'; diff --git a/x-pack/plugins/ml/public/application/app.tsx b/x-pack/plugins/ml/public/application/app.tsx index 833a4fade128b..50417aafab9b6 100644 --- a/x-pack/plugins/ml/public/application/app.tsx +++ b/x-pack/plugins/ml/public/application/app.tsx @@ -82,6 +82,7 @@ const App: FC = ({ coreStart, deps, appMountParams }) => { maps: deps.maps, triggersActionsUi: deps.triggersActionsUi, dataVisualizer: deps.dataVisualizer, + aiops: deps.aiops, usageCollection: deps.usageCollection, fieldFormats: deps.fieldFormats, dashboard: deps.dashboard, @@ -135,6 +136,7 @@ export const renderApp = ( dashboard: deps.dashboard, maps: deps.maps, dataVisualizer: deps.dataVisualizer, + aiops: deps.aiops, dataViews: deps.data.dataViews, }); diff --git a/x-pack/plugins/ml/public/application/components/ml_page/ml_page.tsx b/x-pack/plugins/ml/public/application/components/ml_page/ml_page.tsx index 301939fb6fdbc..d41ca59255467 100644 --- a/x-pack/plugins/ml/public/application/components/ml_page/ml_page.tsx +++ b/x-pack/plugins/ml/public/application/components/ml_page/ml_page.tsx @@ -71,7 +71,10 @@ export const MlPage: FC<{ pageDeps: PageDependencies }> = React.memo(({ pageDeps ); const routeList = useMemo( - () => Object.values(routes).map((routeFactory) => routeFactory(navigateToPath, basePath.get())), + () => + Object.values(routes) + .map((routeFactory) => routeFactory(navigateToPath, basePath.get())) + .filter((d) => !d.disabled), [] ); diff --git a/x-pack/plugins/ml/public/application/components/ml_page/side_nav.tsx b/x-pack/plugins/ml/public/application/components/ml_page/side_nav.tsx index e5c67de96f494..84474e85330d6 100644 --- a/x-pack/plugins/ml/public/application/components/ml_page/side_nav.tsx +++ b/x-pack/plugins/ml/public/application/components/ml_page/side_nav.tsx @@ -8,6 +8,7 @@ import { i18n } from '@kbn/i18n'; import type { EuiSideNavItemType } from '@elastic/eui'; import { useCallback, useMemo } from 'react'; +import { AIOPS_ENABLED } from '@kbn/aiops-plugin/common'; import type { MlLocatorParams } from '../../../../common/types/locator'; import { useUrlState } from '../../util/url_state'; import { useMlLocator, useNavigateToPath } from '../../contexts/kibana'; @@ -64,7 +65,7 @@ export function useSideNavItems(activeRoute: MlRoute | undefined) { const tabsDefinition: Tab[] = useMemo((): Tab[] => { const disableLinks = mlFeaturesDisabled; - return [ + const mlTabs: Tab[] = [ { id: 'main_section', name: '', @@ -218,6 +219,28 @@ export function useSideNavItems(activeRoute: MlRoute | undefined) { ], }, ]; + + if (AIOPS_ENABLED) { + mlTabs.push({ + id: 'aiops_section', + name: i18n.translate('xpack.ml.navMenu.aiopsTabLinkText', { + defaultMessage: 'AIOps', + }), + items: [ + { + id: 'explainlogratespikes', + pathId: ML_PAGES.AIOPS_EXPLAIN_LOG_RATE_SPIKES, + name: i18n.translate('xpack.ml.navMenu.explainLogRateSpikesLinkText', { + defaultMessage: 'Explain log rate spikes', + }), + disabled: disableLinks, + testSubj: 'mlMainTab explainLogRateSpikes', + }, + ], + }); + } + + return mlTabs; }, [mlFeaturesDisabled, canViewMlNodes]); const getTabItem: (tab: Tab) => EuiSideNavItemType = useCallback( diff --git a/x-pack/plugins/ml/public/application/contexts/kibana/kibana_context.ts b/x-pack/plugins/ml/public/application/contexts/kibana/kibana_context.ts index bfb27e6d4dbbc..fdfcd9106e8e0 100644 --- a/x-pack/plugins/ml/public/application/contexts/kibana/kibana_context.ts +++ b/x-pack/plugins/ml/public/application/contexts/kibana/kibana_context.ts @@ -16,6 +16,7 @@ import type { IStorageWrapper } from '@kbn/kibana-utils-plugin/public'; import type { EmbeddableStart } from '@kbn/embeddable-plugin/public'; import type { MapsStartApi } from '@kbn/maps-plugin/public'; import type { DataVisualizerPluginStart } from '@kbn/data-visualizer-plugin/public'; +import type { AiopsPluginStart } from '@kbn/aiops-plugin/public'; import type { TriggersAndActionsUIPublicPluginStart } from '@kbn/triggers-actions-ui-plugin/public'; import type { FieldFormatsRegistry } from '@kbn/field-formats-plugin/common'; import type { DashboardSetup } from '@kbn/dashboard-plugin/public'; @@ -32,6 +33,7 @@ interface StartPlugins { maps?: MapsStartApi; triggersActionsUi?: TriggersAndActionsUIPublicPluginStart; dataVisualizer?: DataVisualizerPluginStart; + aiops?: AiopsPluginStart; usageCollection?: UsageCollectionSetup; fieldFormats: FieldFormatsRegistry; dashboard: DashboardSetup; diff --git a/x-pack/plugins/ml/public/application/routing/breadcrumbs.ts b/x-pack/plugins/ml/public/application/routing/breadcrumbs.ts index e563831d16376..54aedb4a71857 100644 --- a/x-pack/plugins/ml/public/application/routing/breadcrumbs.ts +++ b/x-pack/plugins/ml/public/application/routing/breadcrumbs.ts @@ -55,6 +55,13 @@ export const DATA_VISUALIZER_BREADCRUMB: ChromeBreadcrumb = Object.freeze({ href: '/datavisualizer', }); +export const AIOPS_BREADCRUMB: ChromeBreadcrumb = Object.freeze({ + text: i18n.translate('xpack.ml.aiopsBreadcrumbLabel', { + defaultMessage: 'AIOps', + }), + href: '/aiops', +}); + export const CREATE_JOB_BREADCRUMB: ChromeBreadcrumb = Object.freeze({ text: i18n.translate('xpack.ml.createJobsBreadcrumbLabel', { defaultMessage: 'Create job', @@ -83,6 +90,7 @@ const breadcrumbs = { DATA_FRAME_ANALYTICS_BREADCRUMB, TRAINED_MODELS, DATA_VISUALIZER_BREADCRUMB, + AIOPS_BREADCRUMB, CREATE_JOB_BREADCRUMB, CALENDAR_MANAGEMENT_BREADCRUMB, FILTER_LISTS_BREADCRUMB, diff --git a/x-pack/plugins/ml/public/application/routing/router.tsx b/x-pack/plugins/ml/public/application/routing/router.tsx index e4e7daa9ee0e1..a761bce2ce38a 100644 --- a/x-pack/plugins/ml/public/application/routing/router.tsx +++ b/x-pack/plugins/ml/public/application/routing/router.tsx @@ -48,6 +48,7 @@ export interface MlRoute { enableDatePicker?: boolean; 'data-test-subj'?: string; actionMenu?: React.ReactNode; + disabled?: boolean; } export interface PageProps { diff --git a/x-pack/plugins/ml/public/application/routing/routes/aiops/explain_log_rate_spikes.tsx b/x-pack/plugins/ml/public/application/routing/routes/aiops/explain_log_rate_spikes.tsx new file mode 100644 index 0000000000000..ca670df258a6a --- /dev/null +++ b/x-pack/plugins/ml/public/application/routing/routes/aiops/explain_log_rate_spikes.tsx @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FC } from 'react'; +import { parse } from 'query-string'; + +import { i18n } from '@kbn/i18n'; + +import { AIOPS_ENABLED } from '@kbn/aiops-plugin/common'; + +import { NavigateToPath } from '../../../contexts/kibana'; + +import { MlRoute, PageLoader, PageProps } from '../../router'; +import { useResolver } from '../../use_resolver'; +import { ExplainLogRateSpikesPage as Page } from '../../../aiops/explain_log_rate_spikes'; + +import { checkBasicLicense } from '../../../license'; +import { checkGetJobsCapabilitiesResolver } from '../../../capabilities/check_capabilities'; +import { cacheDataViewsContract } from '../../../util/index_utils'; +import { getBreadcrumbWithUrlForApp } from '../../breadcrumbs'; + +export const explainLogRateSpikesRouteFactory = ( + navigateToPath: NavigateToPath, + basePath: string +): MlRoute => ({ + id: 'explain_log_rate_spikes', + path: '/aiops/explain_log_rate_spikes', + title: i18n.translate('xpack.ml.aiops.explainLogRateSpikes.docTitle', { + defaultMessage: 'Explain log rate spikes', + }), + render: (props, deps) => , + breadcrumbs: [ + getBreadcrumbWithUrlForApp('ML_BREADCRUMB', navigateToPath, basePath), + getBreadcrumbWithUrlForApp('AIOPS_BREADCRUMB', navigateToPath, basePath), + { + text: i18n.translate('xpack.ml.AiopsBreadcrumbs.explainLogRateSpikesLabel', { + defaultMessage: 'Explain log rate spikes', + }), + }, + ], + disabled: !AIOPS_ENABLED, +}); + +const PageWrapper: FC = ({ location, deps }) => { + const { redirectToMlAccessDeniedPage } = deps; + + const { index, savedSearchId }: Record = parse(location.search, { sort: false }); + const { context } = useResolver(index, savedSearchId, deps.config, deps.dataViewsContract, { + checkBasicLicense, + cacheDataViewsContract: () => cacheDataViewsContract(deps.dataViewsContract), + checkGetJobsCapabilities: () => checkGetJobsCapabilitiesResolver(redirectToMlAccessDeniedPage), + }); + + return ( + + + + ); +}; diff --git a/x-pack/plugins/ml/public/application/routing/routes/aiops/index.ts b/x-pack/plugins/ml/public/application/routing/routes/aiops/index.ts new file mode 100644 index 0000000000000..f2b192a4cd097 --- /dev/null +++ b/x-pack/plugins/ml/public/application/routing/routes/aiops/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './explain_log_rate_spikes'; diff --git a/x-pack/plugins/ml/public/application/routing/routes/index.ts b/x-pack/plugins/ml/public/application/routing/routes/index.ts index 31a8d863e3086..12ddc39e0e23e 100644 --- a/x-pack/plugins/ml/public/application/routing/routes/index.ts +++ b/x-pack/plugins/ml/public/application/routing/routes/index.ts @@ -11,6 +11,7 @@ export * from './new_job'; export * from './datavisualizer'; export * from './settings'; export * from './data_frame_analytics'; +export * from './aiops'; export { timeSeriesExplorerRouteFactory } from './timeseriesexplorer'; export * from './explorer'; export * from './access_denied'; diff --git a/x-pack/plugins/ml/public/application/util/dependency_cache.ts b/x-pack/plugins/ml/public/application/util/dependency_cache.ts index 3680f8b63b0c9..00895cdb3990e 100644 --- a/x-pack/plugins/ml/public/application/util/dependency_cache.ts +++ b/x-pack/plugins/ml/public/application/util/dependency_cache.ts @@ -27,6 +27,7 @@ import type { DataViewsContract } from '@kbn/data-views-plugin/public'; import type { SecurityPluginSetup } from '@kbn/security-plugin/public'; import type { MapsStartApi } from '@kbn/maps-plugin/public'; import type { DataVisualizerPluginStart } from '@kbn/data-visualizer-plugin/public'; +import type { AiopsPluginStart } from '@kbn/aiops-plugin/public'; export interface DependencyCache { timefilter: DataPublicPluginSetup['query']['timefilter'] | null; @@ -48,6 +49,7 @@ export interface DependencyCache { dashboard: DashboardStart | null; maps: MapsStartApi | null; dataVisualizer: DataVisualizerPluginStart | null; + aiops: AiopsPluginStart | null; dataViews: DataViewsContract | null; } @@ -71,6 +73,7 @@ const cache: DependencyCache = { dashboard: null, maps: null, dataVisualizer: null, + aiops: null, dataViews: null, }; @@ -93,6 +96,7 @@ export function setDependencyCache(deps: Partial) { cache.i18n = deps.i18n || null; cache.dashboard = deps.dashboard || null; cache.dataVisualizer = deps.dataVisualizer || null; + cache.aiops = deps.aiops || null; cache.dataViews = deps.dataViews || null; } diff --git a/x-pack/plugins/ml/public/locator/ml_locator.ts b/x-pack/plugins/ml/public/locator/ml_locator.ts index b1ea2549c3347..01d63aa0ebf3f 100644 --- a/x-pack/plugins/ml/public/locator/ml_locator.ts +++ b/x-pack/plugins/ml/public/locator/ml_locator.ts @@ -83,6 +83,8 @@ export class MlLocatorDefinition implements LocatorDefinition { case ML_PAGES.DATA_VISUALIZER_FILE: case ML_PAGES.DATA_VISUALIZER_INDEX_VIEWER: case ML_PAGES.DATA_VISUALIZER_INDEX_SELECT: + case ML_PAGES.AIOPS: + case ML_PAGES.AIOPS_EXPLAIN_LOG_RATE_SPIKES: case ML_PAGES.OVERVIEW: case ML_PAGES.SETTINGS: case ML_PAGES.FILTER_LISTS_MANAGE: diff --git a/x-pack/plugins/ml/public/plugin.ts b/x-pack/plugins/ml/public/plugin.ts index 1ef7c73d2189a..79f386d521da1 100644 --- a/x-pack/plugins/ml/public/plugin.ts +++ b/x-pack/plugins/ml/public/plugin.ts @@ -37,6 +37,7 @@ import { TriggersAndActionsUIPublicPluginStart, } from '@kbn/triggers-actions-ui-plugin/public'; import type { DataVisualizerPluginStart } from '@kbn/data-visualizer-plugin/public'; +import type { AiopsPluginStart } from '@kbn/aiops-plugin/public'; import type { PluginSetupContract as AlertingSetup } from '@kbn/alerting-plugin/public'; import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public'; import type { FieldFormatsSetup, FieldFormatsStart } from '@kbn/field-formats-plugin/public'; @@ -59,6 +60,7 @@ export interface MlStartDependencies { maps?: MapsStartApi; triggersActionsUi?: TriggersAndActionsUIPublicPluginStart; dataVisualizer: DataVisualizerPluginStart; + aiops: AiopsPluginStart; fieldFormats: FieldFormatsStart; dashboard: DashboardStart; charts: ChartsPluginStart; @@ -125,6 +127,7 @@ export class MlPlugin implements Plugin { kibanaVersion, triggersActionsUi: pluginsStart.triggersActionsUi, dataVisualizer: pluginsStart.dataVisualizer, + aiops: pluginsStart.aiops, usageCollection: pluginsSetup.usageCollection, fieldFormats: pluginsStart.fieldFormats, }, diff --git a/x-pack/plugins/ml/tsconfig.json b/x-pack/plugins/ml/tsconfig.json index a937586369ef4..bd89d383adcef 100644 --- a/x-pack/plugins/ml/tsconfig.json +++ b/x-pack/plugins/ml/tsconfig.json @@ -24,6 +24,7 @@ { "path": "../cloud/tsconfig.json" }, { "path": "../features/tsconfig.json" }, { "path": "../data_visualizer/tsconfig.json"}, + { "path": "../aiops/tsconfig.json"}, { "path": "../license_management/tsconfig.json" }, { "path": "../licensing/tsconfig.json" }, { "path": "../maps/tsconfig.json" }, diff --git a/x-pack/test/api_integration/apis/aiops/example_stream.ts b/x-pack/test/api_integration/apis/aiops/example_stream.ts new file mode 100644 index 0000000000000..693a6de2c6716 --- /dev/null +++ b/x-pack/test/api_integration/apis/aiops/example_stream.ts @@ -0,0 +1,104 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import fetch from 'node-fetch'; +import { format as formatUrl } from 'url'; + +import expect from '@kbn/expect'; + +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default ({ getService }: FtrProviderContext) => { + const supertest = getService('supertest'); + const config = getService('config'); + const kibanaServerUrl = formatUrl(config.get('servers.kibana')); + + describe('POST /internal/aiops/example_stream', () => { + it('should return full data without streaming', async () => { + const resp = await supertest + .post(`/internal/aiops/example_stream`) + .set('kbn-xsrf', 'kibana') + .send({ + timeout: 1, + }) + .expect(200); + + expect(Buffer.isBuffer(resp.body)).to.be(true); + + const chunks: string[] = resp.body.toString().split('\n'); + + expect(chunks.length).to.be(201); + + const lastChunk = chunks.pop(); + expect(lastChunk).to.be(''); + + let data: any[] = []; + + expect(() => { + data = chunks.map((c) => JSON.parse(c)); + }).not.to.throwError(); + + data.forEach((d) => { + expect(typeof d.type).to.be('string'); + }); + + const progressData = data.filter((d) => d.type === 'update_progress'); + expect(progressData.length).to.be(100); + expect(progressData[0].payload).to.be(1); + expect(progressData[progressData.length - 1].payload).to.be(100); + }); + + it('should return data in chunks with streaming', async () => { + const response = await fetch(`${kibanaServerUrl}/internal/aiops/example_stream`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'kbn-xsrf': 'stream', + }, + body: JSON.stringify({ timeout: 1 }), + }); + + const stream = response.body; + + expect(stream).not.to.be(null); + + if (stream !== null) { + let partial = ''; + let threw = false; + const progressData: any[] = []; + + try { + for await (const value of stream) { + const full = `${partial}${value}`; + const parts = full.split('\n'); + const last = parts.pop(); + + partial = last ?? ''; + + const actions = parts.map((p) => JSON.parse(p)); + + actions.forEach((action) => { + expect(typeof action.type).to.be('string'); + + if (action.type === 'update_progress') { + progressData.push(action); + } + }); + } + } catch (e) { + threw = true; + } + + expect(threw).to.be(false); + + expect(progressData.length).to.be(100); + expect(progressData[0].payload).to.be(1); + expect(progressData[progressData.length - 1].payload).to.be(100); + } + }); + }); +}; diff --git a/x-pack/test/api_integration/apis/aiops/index.ts b/x-pack/test/api_integration/apis/aiops/index.ts new file mode 100644 index 0000000000000..04b4181906dbf --- /dev/null +++ b/x-pack/test/api_integration/apis/aiops/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ loadTestFile }: FtrProviderContext) { + describe('AIOps', function () { + this.tags(['ml']); + + loadTestFile(require.resolve('./example_stream')); + }); +} diff --git a/x-pack/test/api_integration/apis/index.ts b/x-pack/test/api_integration/apis/index.ts index 645cc81560682..b3566ff30aea2 100644 --- a/x-pack/test/api_integration/apis/index.ts +++ b/x-pack/test/api_integration/apis/index.ts @@ -31,6 +31,7 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./searchprofiler')); loadTestFile(require.resolve('./painless_lab')); loadTestFile(require.resolve('./file_upload')); + loadTestFile(require.resolve('./aiops')); loadTestFile(require.resolve('./ml')); loadTestFile(require.resolve('./watcher')); loadTestFile(require.resolve('./logs_ui')); From b70b89994fff3dc76cb49c62332eccc2093cccac Mon Sep 17 00:00:00 2001 From: Stratoula Kalafateli Date: Thu, 12 May 2022 14:52:32 +0300 Subject: [PATCH 7/9] [Visualize] Fixes metric label font size (#132100) --- .../public/__snapshots__/to_ast.test.ts.snap | 38 +++++++++++++++++++ src/plugins/vis_types/metric/public/to_ast.ts | 2 + 2 files changed, 40 insertions(+) diff --git a/src/plugins/vis_types/metric/public/__snapshots__/to_ast.test.ts.snap b/src/plugins/vis_types/metric/public/__snapshots__/to_ast.test.ts.snap index 233e38874e6da..ef6102571f324 100644 --- a/src/plugins/vis_types/metric/public/__snapshots__/to_ast.test.ts.snap +++ b/src/plugins/vis_types/metric/public/__snapshots__/to_ast.test.ts.snap @@ -59,6 +59,25 @@ Object { "type": "expression", }, ], + "labelFont": Array [ + Object { + "chain": Array [ + Object { + "arguments": Object { + "align": Array [ + "center", + ], + "size": Array [ + "14", + ], + }, + "function": "font", + "type": "function", + }, + ], + "type": "expression", + }, + ], "percentageMode": Array [ true, ], @@ -133,6 +152,25 @@ Object { "type": "expression", }, ], + "labelFont": Array [ + Object { + "chain": Array [ + Object { + "arguments": Object { + "align": Array [ + "center", + ], + "size": Array [ + "14", + ], + }, + "function": "font", + "type": "function", + }, + ], + "type": "expression", + }, + ], "showLabels": Array [ false, ], diff --git a/src/plugins/vis_types/metric/public/to_ast.ts b/src/plugins/vis_types/metric/public/to_ast.ts index 322ea561abeb4..d206d046cde6a 100644 --- a/src/plugins/vis_types/metric/public/to_ast.ts +++ b/src/plugins/vis_types/metric/public/to_ast.ts @@ -83,6 +83,8 @@ export const toExpressionAst: VisToExpressionAst = (vis, params) => { ) ); + metricVis.addArgument('labelFont', buildExpression(`font size="14" align="center"`)); + if (colorsRange && colorsRange.length > 1) { const stopsWithColors = getStopsWithColorsFromRanges(colorsRange, colorSchema, invertColors); const palette = buildExpressionFunction('palette', { From 94b894a63f68a1f86165ad643f9f45515f0d8527 Mon Sep 17 00:00:00 2001 From: Dominique Clarke Date: Thu, 12 May 2022 08:08:42 -0400 Subject: [PATCH 8/9] [Synthetics] fix script_type for monitor management telemetry (#131855) * synthetics - fix script_type for monitor management telemetry * adjust tests Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../synthetics_service/add_monitor.ts | 8 +- .../synthetics_service/delete_monitor.ts | 10 ++- .../synthetics_service/edit_monitor.ts | 23 +++-- .../telemetry/monitor_upgrade_sender.test.ts | 90 +++++++++++-------- .../telemetry/monitor_upgrade_sender.ts | 18 ++-- 5 files changed, 93 insertions(+), 56 deletions(-) diff --git a/x-pack/plugins/synthetics/server/rest_api/synthetics_service/add_monitor.ts b/x-pack/plugins/synthetics/server/rest_api/synthetics_service/add_monitor.ts index 598328349227d..0dfc01df069ff 100644 --- a/x-pack/plugins/synthetics/server/rest_api/synthetics_service/add_monitor.ts +++ b/x-pack/plugins/synthetics/server/rest_api/synthetics_service/add_monitor.ts @@ -7,6 +7,7 @@ import { schema } from '@kbn/config-schema'; import { SavedObject } from '@kbn/core/server'; import { + ConfigKey, MonitorFields, SyntheticsMonitor, EncryptedSyntheticsMonitor, @@ -57,7 +58,12 @@ export const addSyntheticsMonitorRoute: UMRestApiRouteFactory = () => ({ sendTelemetryEvents( server.logger, server.telemetry, - formatTelemetryEvent({ monitor: newMonitor, errors, kibanaVersion: server.kibanaVersion }) + formatTelemetryEvent({ + monitor: newMonitor, + errors, + isInlineScript: Boolean((monitor as MonitorFields)[ConfigKey.SOURCE_INLINE]), + kibanaVersion: server.kibanaVersion, + }) ); if (errors && errors.length > 0) { diff --git a/x-pack/plugins/synthetics/server/rest_api/synthetics_service/delete_monitor.ts b/x-pack/plugins/synthetics/server/rest_api/synthetics_service/delete_monitor.ts index dc6fc759e81a4..980d26d2f39ad 100644 --- a/x-pack/plugins/synthetics/server/rest_api/synthetics_service/delete_monitor.ts +++ b/x-pack/plugins/synthetics/server/rest_api/synthetics_service/delete_monitor.ts @@ -7,6 +7,8 @@ import { schema } from '@kbn/config-schema'; import { SavedObjectsErrorHelpers } from '@kbn/core/server'; import { + ConfigKey, + MonitorFields, EncryptedSyntheticsMonitor, SyntheticsMonitorWithSecrets, } from '../../../common/runtime_types'; @@ -66,7 +68,13 @@ export const deleteSyntheticsMonitorRoute: UMRestApiRouteFactory = () => ({ sendTelemetryEvents( logger, telemetry, - formatTelemetryDeleteEvent(monitor, kibanaVersion, new Date().toISOString(), errors) + formatTelemetryDeleteEvent( + monitor, + kibanaVersion, + new Date().toISOString(), + Boolean((normalizedMonitor.attributes as MonitorFields)[ConfigKey.SOURCE_INLINE]), + errors + ) ); if (errors && errors.length > 0) { diff --git a/x-pack/plugins/synthetics/server/rest_api/synthetics_service/edit_monitor.ts b/x-pack/plugins/synthetics/server/rest_api/synthetics_service/edit_monitor.ts index 55be289f7162a..99f9d542dc895 100644 --- a/x-pack/plugins/synthetics/server/rest_api/synthetics_service/edit_monitor.ts +++ b/x-pack/plugins/synthetics/server/rest_api/synthetics_service/edit_monitor.ts @@ -79,24 +79,25 @@ export const editSyntheticsMonitorRoute: UMRestApiRouteFactory = () => ({ return response.badRequest({ body: { message, attributes: { details, ...payload } } }); } - const monitorWithRevision = formatSecrets({ + const monitorWithRevision = { ...editedMonitor, revision: (previousMonitor.attributes[ConfigKey.REVISION] || 0) + 1, - }); + }; + const formattedMonitor = formatSecrets(monitorWithRevision); - const editMonitor: SavedObjectsUpdateResponse = + const updatedMonitor: SavedObjectsUpdateResponse = await savedObjectsClient.update( syntheticsMonitorType, monitorId, - monitor.type === 'browser' ? { ...monitorWithRevision, urls: '' } : monitorWithRevision + monitor.type === 'browser' ? { ...formattedMonitor, urls: '' } : formattedMonitor ); const errors = await syntheticsService.pushConfigs([ { ...editedMonitor, - id: editMonitor.id, + id: updatedMonitor.id, fields: { - config_id: editMonitor.id, + config_id: updatedMonitor.id, }, fields_under_root: true, }, @@ -105,7 +106,13 @@ export const editSyntheticsMonitorRoute: UMRestApiRouteFactory = () => ({ sendTelemetryEvents( logger, telemetry, - formatTelemetryUpdateEvent(editMonitor, previousMonitor, kibanaVersion, errors) + formatTelemetryUpdateEvent( + updatedMonitor, + previousMonitor, + kibanaVersion, + Boolean((monitor as MonitorFields)[ConfigKey.SOURCE_INLINE]), + errors + ) ); // Return service sync errors in OK response @@ -115,7 +122,7 @@ export const editSyntheticsMonitorRoute: UMRestApiRouteFactory = () => ({ }); } - return editMonitor; + return updatedMonitor; } catch (updateErr) { if (SavedObjectsErrorHelpers.isNotFoundError(updateErr)) { return getMonitorNotFoundResponse(response, monitorId); diff --git a/x-pack/plugins/synthetics/server/rest_api/synthetics_service/telemetry/monitor_upgrade_sender.test.ts b/x-pack/plugins/synthetics/server/rest_api/synthetics_service/telemetry/monitor_upgrade_sender.test.ts index 9d8161b02b634..95db598fa0e65 100644 --- a/x-pack/plugins/synthetics/server/rest_api/synthetics_service/telemetry/monitor_upgrade_sender.test.ts +++ b/x-pack/plugins/synthetics/server/rest_api/synthetics_service/telemetry/monitor_upgrade_sender.test.ts @@ -83,40 +83,10 @@ const createTestConfig = (extraConfigs: Record, updatedAt?: string) describe('monitor upgrade telemetry helpers', () => { it('formats telemetry events', () => { - const actual = formatTelemetryEvent({ monitor: testConfig, kibanaVersion, errors }); - expect(actual).toEqual({ - stackVersion: kibanaVersion, - configId: sha256.create().update(testConfig.id).hex(), - locations: ['us_central', 'other'], - locationsCount: 2, - monitorNameLength: testConfig.attributes[ConfigKey.NAME].length, - updatedAt: testConfig.updated_at, - type: testConfig.attributes[ConfigKey.MONITOR_TYPE], - scriptType: undefined, - monitorInterval: 180000, - lastUpdatedAt: undefined, - deletedAt: undefined, - errors, - durationSinceLastUpdated: undefined, - revision: 1, - }); - }); - - it.each([ - [ConfigKey.SOURCE_INLINE, 'recorder', true], - [ConfigKey.SOURCE_INLINE, 'inline', false], - [ConfigKey.SOURCE_ZIP_URL, 'zip', false], - ])('handles formatting scriptType for browser monitors', (config, scriptType, isRecorder) => { const actual = formatTelemetryEvent({ - monitor: createTestConfig({ - [config]: 'test', - [ConfigKey.METADATA]: { - script_source: { - is_generated_script: isRecorder, - }, - }, - }), + monitor: testConfig, kibanaVersion, + isInlineScript: false, errors, }); expect(actual).toEqual({ @@ -127,7 +97,7 @@ describe('monitor upgrade telemetry helpers', () => { monitorNameLength: testConfig.attributes[ConfigKey.NAME].length, updatedAt: testConfig.updated_at, type: testConfig.attributes[ConfigKey.MONITOR_TYPE], - scriptType, + scriptType: undefined, monitorInterval: 180000, lastUpdatedAt: undefined, deletedAt: undefined, @@ -137,11 +107,51 @@ describe('monitor upgrade telemetry helpers', () => { }); }); + it.each([ + [ConfigKey.SOURCE_INLINE, 'recorder', true, true], + [ConfigKey.SOURCE_INLINE, 'inline', false, true], + [ConfigKey.SOURCE_ZIP_URL, 'zip', false, false], + ])( + 'handles formatting scriptType for browser monitors', + (config, scriptType, isRecorder, isInlineScript) => { + const actual = formatTelemetryEvent({ + monitor: createTestConfig({ + [config]: 'test', + [ConfigKey.METADATA]: { + script_source: { + is_generated_script: isRecorder, + }, + }, + }), + isInlineScript, + kibanaVersion, + errors, + }); + expect(actual).toEqual({ + stackVersion: kibanaVersion, + configId: sha256.create().update(testConfig.id).hex(), + locations: ['us_central', 'other'], + locationsCount: 2, + monitorNameLength: testConfig.attributes[ConfigKey.NAME].length, + updatedAt: testConfig.updated_at, + type: testConfig.attributes[ConfigKey.MONITOR_TYPE], + scriptType, + monitorInterval: 180000, + lastUpdatedAt: undefined, + deletedAt: undefined, + errors, + durationSinceLastUpdated: undefined, + revision: 1, + }); + } + ); + it('handles formatting update events', () => { const actual = formatTelemetryUpdateEvent( createTestConfig({}, '2011-10-05T16:48:00.000Z'), testConfig, kibanaVersion, + false, errors ); expect(actual).toEqual({ @@ -167,6 +177,7 @@ describe('monitor upgrade telemetry helpers', () => { testConfig, kibanaVersion, '2011-10-05T16:48:00.000Z', + false, errors ); expect(actual).toEqual({ @@ -198,12 +209,13 @@ describe('sendTelemetryEvents', () => { }); it('should queue telemetry events with generic error', () => { - const event = formatTelemetryEvent({ monitor: testConfig, kibanaVersion, errors }); - sendTelemetryEvents( - loggerMock, - eventsTelemetryMock, - formatTelemetryEvent({ monitor: testConfig, kibanaVersion, errors }) - ); + const event = formatTelemetryEvent({ + monitor: testConfig, + kibanaVersion, + isInlineScript: true, + errors, + }); + sendTelemetryEvents(loggerMock, eventsTelemetryMock, event); expect(eventsTelemetryMock.queueTelemetryEvents).toHaveBeenCalledWith(MONITOR_UPDATE_CHANNEL, [ event, diff --git a/x-pack/plugins/synthetics/server/rest_api/synthetics_service/telemetry/monitor_upgrade_sender.ts b/x-pack/plugins/synthetics/server/rest_api/synthetics_service/telemetry/monitor_upgrade_sender.ts index 526e40ef2f230..55c97fd3c1006 100644 --- a/x-pack/plugins/synthetics/server/rest_api/synthetics_service/telemetry/monitor_upgrade_sender.ts +++ b/x-pack/plugins/synthetics/server/rest_api/synthetics_service/telemetry/monitor_upgrade_sender.ts @@ -44,6 +44,7 @@ export function sendTelemetryEvents( export function formatTelemetryEvent({ monitor, kibanaVersion, + isInlineScript, lastUpdatedAt, durationSinceLastUpdated, deletedAt, @@ -51,6 +52,7 @@ export function formatTelemetryEvent({ }: { monitor: SavedObject; kibanaVersion: string; + isInlineScript: boolean; lastUpdatedAt?: string; durationSinceLastUpdated?: number; deletedAt?: string; @@ -71,7 +73,7 @@ export function formatTelemetryEvent({ monitorNameLength: attributes[ConfigKey.NAME].length, monitorInterval: scheduleToMilli(attributes[ConfigKey.SCHEDULE]), stackVersion: kibanaVersion, - scriptType: getScriptType(attributes as Partial), + scriptType: getScriptType(attributes as Partial, isInlineScript), errors: errors && errors?.length ? errors.map((e) => ({ @@ -92,6 +94,7 @@ export function formatTelemetryUpdateEvent( currentMonitor: SavedObjectsUpdateResponse, previousMonitor: SavedObject, kibanaVersion: string, + isInlineScript: boolean, errors?: ServiceLocationErrors | null ) { let durationSinceLastUpdated: number = 0; @@ -106,6 +109,7 @@ export function formatTelemetryUpdateEvent( kibanaVersion, durationSinceLastUpdated, lastUpdatedAt: previousMonitor.updated_at, + isInlineScript, errors, }); } @@ -114,6 +118,7 @@ export function formatTelemetryDeleteEvent( previousMonitor: SavedObject, kibanaVersion: string, deletedAt: string, + isInlineScript: boolean, errors?: ServiceLocationErrors | null ) { let durationSinceLastUpdated: number = 0; @@ -128,21 +133,20 @@ export function formatTelemetryDeleteEvent( durationSinceLastUpdated, lastUpdatedAt: previousMonitor.updated_at, deletedAt, + isInlineScript, errors, }); } function getScriptType( - attributes: Partial + attributes: Partial, + isInlineScript: boolean ): 'inline' | 'recorder' | 'zip' | undefined { if (attributes[ConfigKey.SOURCE_ZIP_URL]) { return 'zip'; - } else if ( - attributes[ConfigKey.SOURCE_INLINE] && - attributes[ConfigKey.METADATA]?.script_source?.is_generated_script - ) { + } else if (isInlineScript && attributes[ConfigKey.METADATA]?.script_source?.is_generated_script) { return 'recorder'; - } else if (attributes[ConfigKey.SOURCE_INLINE]) { + } else if (isInlineScript) { return 'inline'; } From c9372dc3a30e90d68410b30fd4a4120e8fea7a00 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 12 May 2022 06:42:38 -0600 Subject: [PATCH 9/9] [maps] fix marker size scale issue for counts (#132057) * [maps] fix marker size scale issue for counts * fix test names Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../pluck_style_meta_from_features.test.ts | 67 +++++++++++- .../pluck_style_meta_from_features.ts | 10 +- .../mvt_vector_layer/pluck_style_meta.test.ts | 102 ++++++++++++++++++ ...uck_style_meta.tsx => pluck_style_meta.ts} | 13 ++- 4 files changed, 181 insertions(+), 11 deletions(-) create mode 100644 x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/pluck_style_meta.test.ts rename x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/{pluck_style_meta.tsx => pluck_style_meta.ts} (92%) diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/pluck_style_meta_from_features.test.ts b/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/pluck_style_meta_from_features.test.ts index 5c609f66e3f53..31aea302b70b1 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/pluck_style_meta_from_features.test.ts +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/pluck_style_meta_from_features.test.ts @@ -188,7 +188,7 @@ describe('pluckStyleMetaFromFeatures', () => { }); }); - test('Should extract scaled field range', async () => { + test('Should extract range', async () => { const features = [ { type: 'Feature', @@ -197,7 +197,7 @@ describe('pluckStyleMetaFromFeatures', () => { coordinates: [0, 0], }, properties: { - myDynamicField: 1, + myDynamicField: 3, }, }, { @@ -242,9 +242,9 @@ describe('pluckStyleMetaFromFeatures', () => { myDynamicField: { categories: [], range: { - delta: 9, + delta: 7, max: 10, - min: 1, + min: 3, }, }, }, @@ -255,6 +255,65 @@ describe('pluckStyleMetaFromFeatures', () => { }, }); }); + + test('Should extract range with "min = 1" for count field', async () => { + const features = [ + { + type: 'Feature', + geometry: { + type: 'Point', + coordinates: [0, 0], + }, + properties: { + count: 3, + }, + }, + { + type: 'Feature', + geometry: { + type: 'Point', + coordinates: [0, 0], + }, + properties: { + count: 10, + }, + }, + ] as Feature[]; + const dynamicColorOptions = { + type: COLOR_MAP_TYPE.ORDINAL, + field: { + origin: FIELD_ORIGIN.SOURCE, + name: 'count', + }, + } as ColorDynamicOptions; + const field = new InlineField({ + fieldName: dynamicColorOptions.field!.name, + source: {} as unknown as IVectorSource, + origin: dynamicColorOptions.field!.origin, + dataType: 'number', + }); + field.isCount = () => { + return true; + }; + const dynamicColorProperty = new DynamicColorProperty( + dynamicColorOptions, + VECTOR_STYLES.FILL_COLOR, + field, + {} as unknown as IVectorLayer, + () => { + return null; + } // getFieldFormatter + ); + + const styleMeta = await pluckStyleMetaFromFeatures(features, Object.values(VECTOR_SHAPE_TYPE), [ + dynamicColorProperty, + ]); + expect(styleMeta.fieldMeta.count.range).toEqual({ + delta: 9, + max: 10, + min: 1, + }); + }); }); describe('pluckCategoricalStyleMetaFromFeatures', () => { diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/pluck_style_meta_from_features.ts b/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/pluck_style_meta_from_features.ts index 2ea0fef1bf648..7867161a14e21 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/pluck_style_meta_from_features.ts +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/pluck_style_meta_from_features.ts @@ -113,18 +113,22 @@ function pluckOrdinalStyleMetaFromFeatures( property: IDynamicStyleProperty, features: Feature[] ): RangeFieldMeta | null { - if (!property.isOrdinal()) { + const field = property.getField(); + if (!field || !property.isOrdinal()) { return null; } const name = property.getFieldName(); - let min = Infinity; + const isCount = field.isCount(); + let min = isCount ? 1 : Infinity; let max = -Infinity; for (let i = 0; i < features.length; i++) { const feature = features[i]; const newValue = feature.properties ? parseFloat(feature.properties[name]) : NaN; if (!isNaN(newValue)) { - min = Math.min(min, newValue); + if (!isCount) { + min = Math.min(min, newValue); + } max = Math.max(max, newValue); } } diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/pluck_style_meta.test.ts b/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/pluck_style_meta.test.ts new file mode 100644 index 0000000000000..c0e624d412bc3 --- /dev/null +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/pluck_style_meta.test.ts @@ -0,0 +1,102 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FIELD_ORIGIN } from '../../../../../common/constants'; +import { TileMetaFeature } from '../../../../../common/descriptor_types'; +import { pluckOrdinalStyleMeta } from './pluck_style_meta'; +import { IField } from '../../../fields/field'; +import { DynamicSizeProperty } from '../../../styles/vector/properties/dynamic_size_property'; + +describe('pluckOrdinalStyleMeta', () => { + test('should pluck range from metaFeatures', () => { + const mockField = { + isCount: () => { + return false; + }, + pluckRangeFromTileMetaFeature: (metaFeature: TileMetaFeature) => { + return { + max: metaFeature.properties['aggregations.avg_of_bytes.max'], + min: metaFeature.properties['aggregations.avg_of_bytes.min'], + }; + }, + } as unknown as IField; + const mockStyleProperty = { + getField: () => { + return mockField; + }, + isOrdinal: () => { + return true; + }, + getFieldOrigin: () => { + return FIELD_ORIGIN.SOURCE; + }, + } as unknown as DynamicSizeProperty; + const metaFeatures = [ + { + properties: { + 'aggregations.avg_of_bytes.max': 7565, + 'aggregations.avg_of_bytes.min': 1622, + }, + } as unknown as TileMetaFeature, + { + properties: { + 'aggregations.avg_of_bytes.max': 11869, + 'aggregations.avg_of_bytes.min': 659, + }, + } as unknown as TileMetaFeature, + ]; + expect(pluckOrdinalStyleMeta(mockStyleProperty, metaFeatures, undefined)).toEqual({ + max: 11869, + min: 659, + delta: 11210, + }); + }); + + test('should pluck range with min: 1 from metaFeatures for count field', () => { + const mockField = { + isCount: () => { + return true; + }, + pluckRangeFromTileMetaFeature: (metaFeature: TileMetaFeature) => { + return { + max: metaFeature.properties['aggregations._count.max'], + min: metaFeature.properties['aggregations._count.min'], + }; + }, + } as unknown as IField; + const mockStyleProperty = { + getField: () => { + return mockField; + }, + isOrdinal: () => { + return true; + }, + getFieldOrigin: () => { + return FIELD_ORIGIN.SOURCE; + }, + } as unknown as DynamicSizeProperty; + const metaFeatures = [ + { + properties: { + 'aggregations._count.max': 35, + 'aggregations._count.min': 3, + }, + } as unknown as TileMetaFeature, + { + properties: { + 'aggregations._count.max': 36, + 'aggregations._count.min': 5, + }, + } as unknown as TileMetaFeature, + ]; + expect(pluckOrdinalStyleMeta(mockStyleProperty, metaFeatures, undefined)).toEqual({ + max: 36, + min: 1, + delta: 35, + }); + }); +}); diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/pluck_style_meta.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/pluck_style_meta.ts similarity index 92% rename from x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/pluck_style_meta.tsx rename to x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/pluck_style_meta.ts index 1f9784fb65dc0..564500b59742b 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/pluck_style_meta.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/pluck_style_meta.ts @@ -70,7 +70,7 @@ function pluckCategoricalStyleMeta( return []; } -function pluckOrdinalStyleMeta( +export function pluckOrdinalStyleMeta( property: IDynamicStyleProperty, metaFeatures: TileMetaFeature[], joinPropertiesMap: PropertiesMap | undefined @@ -80,13 +80,16 @@ function pluckOrdinalStyleMeta( return null; } - let min = Infinity; + const isCount = field.isCount(); + let min = isCount ? 1 : Infinity; let max = -Infinity; if (property.getFieldOrigin() === FIELD_ORIGIN.SOURCE) { for (let i = 0; i < metaFeatures.length; i++) { const range = field.pluckRangeFromTileMetaFeature(metaFeatures[i]); if (range) { - min = Math.min(range.min, min); + if (!isCount) { + min = Math.min(range.min, min); + } max = Math.max(range.max, max); } } @@ -94,7 +97,9 @@ function pluckOrdinalStyleMeta( joinPropertiesMap.forEach((value: { [key: string]: unknown }) => { const propertyValue = value[field.getName()]; if (typeof propertyValue === 'number') { - min = Math.min(propertyValue as number, min); + if (!isCount) { + min = Math.min(propertyValue as number, min); + } max = Math.max(propertyValue as number, max); } });