UNPKG

fetch-plugin

Version:

fetch polyfill with TIMEOUT setting and other options, extend from whatwg-fetch

739 lines (633 loc) 21.8 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global._fetch = factory()); }(this, (function () { 'use strict'; function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } var support = { searchParams: 'URLSearchParams' in self, iterable: 'Symbol' in self && 'iterator' in Symbol, blob: 'FileReader' in self && 'Blob' in self && (function() { try { new Blob(); return true } catch (e) { return false } })(), formData: 'FormData' in self, arrayBuffer: 'ArrayBuffer' in self }; function isDataView(obj) { return obj && DataView.prototype.isPrototypeOf(obj) } if (support.arrayBuffer) { var viewClasses = [ '[object Int8Array]', '[object Uint8Array]', '[object Uint8ClampedArray]', '[object Int16Array]', '[object Uint16Array]', '[object Int32Array]', '[object Uint32Array]', '[object Float32Array]', '[object Float64Array]' ]; var isArrayBufferView = ArrayBuffer.isView || function(obj) { return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1 }; } function normalizeName(name) { if (typeof name !== 'string') { name = String(name); } if (/[^a-z0-9\-#$%&'*+.^_`|~]/i.test(name)) { throw new TypeError('Invalid character in header field name') } return name.toLowerCase() } function normalizeValue(value) { if (typeof value !== 'string') { value = String(value); } return value } // Build a destructive iterator for the value list function iteratorFor(items) { var iterator = { next: function() { var value = items.shift(); return {done: value === undefined, value: value} } }; if (support.iterable) { iterator[Symbol.iterator] = function() { return iterator }; } return iterator } function Headers$1(headers) { this.map = {}; if (headers instanceof Headers$1) { headers.forEach(function(value, name) { this.append(name, value); }, this); } else if (Array.isArray(headers)) { headers.forEach(function(header) { this.append(header[0], header[1]); }, this); } else if (headers) { Object.getOwnPropertyNames(headers).forEach(function(name) { this.append(name, headers[name]); }, this); } } Headers$1.prototype.append = function(name, value) { name = normalizeName(name); value = normalizeValue(value); var oldValue = this.map[name]; this.map[name] = oldValue ? oldValue + ', ' + value : value; }; Headers$1.prototype['delete'] = function(name) { delete this.map[normalizeName(name)]; }; Headers$1.prototype.get = function(name) { name = normalizeName(name); return this.has(name) ? this.map[name] : null }; Headers$1.prototype.has = function(name) { return this.map.hasOwnProperty(normalizeName(name)) }; Headers$1.prototype.set = function(name, value) { this.map[normalizeName(name)] = normalizeValue(value); }; Headers$1.prototype.forEach = function(callback, thisArg) { for (var name in this.map) { if (this.map.hasOwnProperty(name)) { callback.call(thisArg, this.map[name], name, this); } } }; Headers$1.prototype.keys = function() { var items = []; this.forEach(function(value, name) { items.push(name); }); return iteratorFor(items) }; Headers$1.prototype.values = function() { var items = []; this.forEach(function(value) { items.push(value); }); return iteratorFor(items) }; Headers$1.prototype.entries = function() { var items = []; this.forEach(function(value, name) { items.push([name, value]); }); return iteratorFor(items) }; if (support.iterable) { Headers$1.prototype[Symbol.iterator] = Headers$1.prototype.entries; } function consumed(body) { if (body.bodyUsed) { return Promise.reject(new TypeError('Already read')) } body.bodyUsed = true; } function fileReaderReady(reader) { return new Promise(function(resolve, reject) { reader.onload = function() { resolve(reader.result); }; reader.onerror = function() { reject(reader.error); }; }) } function readBlobAsArrayBuffer(blob) { var reader = new FileReader(); var promise = fileReaderReady(reader); reader.readAsArrayBuffer(blob); return promise } function readBlobAsText(blob) { var reader = new FileReader(); var promise = fileReaderReady(reader); reader.readAsText(blob); return promise } function readArrayBufferAsText(buf) { var view = new Uint8Array(buf); var chars = new Array(view.length); for (var i = 0; i < view.length; i++) { chars[i] = String.fromCharCode(view[i]); } return chars.join('') } function bufferClone(buf) { if (buf.slice) { return buf.slice(0) } else { var view = new Uint8Array(buf.byteLength); view.set(new Uint8Array(buf)); return view.buffer } } function Body() { this.bodyUsed = false; this._initBody = function(body) { this._bodyInit = body; if (!body) { this._bodyText = ''; } else if (typeof body === 'string') { this._bodyText = body; } else if (support.blob && Blob.prototype.isPrototypeOf(body)) { this._bodyBlob = body; } else if (support.formData && FormData.prototype.isPrototypeOf(body)) { this._bodyFormData = body; } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) { this._bodyText = body.toString(); } else if (support.arrayBuffer && support.blob && isDataView(body)) { this._bodyArrayBuffer = bufferClone(body.buffer); // IE 10-11 can't handle a DataView body. this._bodyInit = new Blob([this._bodyArrayBuffer]); } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) { this._bodyArrayBuffer = bufferClone(body); } else { this._bodyText = body = Object.prototype.toString.call(body); } if (!this.headers.get('content-type')) { if (typeof body === 'string') { this.headers.set('content-type', 'text/plain;charset=UTF-8'); } else if (this._bodyBlob && this._bodyBlob.type) { this.headers.set('content-type', this._bodyBlob.type); } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) { this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8'); } } }; if (support.blob) { this.blob = function() { var rejected = consumed(this); if (rejected) { return rejected } if (this._bodyBlob) { return Promise.resolve(this._bodyBlob) } else if (this._bodyArrayBuffer) { return Promise.resolve(new Blob([this._bodyArrayBuffer])) } else if (this._bodyFormData) { throw new Error('could not read FormData body as blob') } else { return Promise.resolve(new Blob([this._bodyText])) } }; this.arrayBuffer = function() { if (this._bodyArrayBuffer) { return consumed(this) || Promise.resolve(this._bodyArrayBuffer) } else { return this.blob().then(readBlobAsArrayBuffer) } }; } this.text = function() { var rejected = consumed(this); if (rejected) { return rejected } if (this._bodyBlob) { return readBlobAsText(this._bodyBlob) } else if (this._bodyArrayBuffer) { return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer)) } else if (this._bodyFormData) { throw new Error('could not read FormData body as text') } else { return Promise.resolve(this._bodyText) } }; if (support.formData) { this.formData = function() { return this.text().then(decode) }; } this.json = function() { return this.text().then(JSON.parse) }; return this } // HTTP methods whose capitalization should be normalized var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT']; function normalizeMethod(method) { var upcased = method.toUpperCase(); return methods.indexOf(upcased) > -1 ? upcased : method } function Request$1(input, options) { options = options || {}; var body = options.body; if (input instanceof Request$1) { if (input.bodyUsed) { throw new TypeError('Already read') } this.url = input.url; this.credentials = input.credentials; if (!options.headers) { this.headers = new Headers$1(input.headers); } this.method = input.method; this.mode = input.mode; this.signal = input.signal; if (!body && input._bodyInit != null) { body = input._bodyInit; input.bodyUsed = true; } } else { this.url = String(input); } this.credentials = options.credentials || this.credentials || 'same-origin'; if (options.headers || !this.headers) { this.headers = new Headers$1(options.headers); } this.method = normalizeMethod(options.method || this.method || 'GET'); this.mode = options.mode || this.mode || null; this.signal = options.signal || this.signal; this.referrer = null; if ((this.method === 'GET' || this.method === 'HEAD') && body) { throw new TypeError('Body not allowed for GET or HEAD requests') } this._initBody(body); } Request$1.prototype.clone = function() { return new Request$1(this, {body: this._bodyInit}) }; function decode(body) { var form = new FormData(); body .trim() .split('&') .forEach(function(bytes) { if (bytes) { var split = bytes.split('='); var name = split.shift().replace(/\+/g, ' '); var value = split.join('=').replace(/\+/g, ' '); form.append(decodeURIComponent(name), decodeURIComponent(value)); } }); return form } function parseHeaders(rawHeaders) { var headers = new Headers$1(); // Replace instances of \r\n and \n followed by at least one space or horizontal tab with a space // https://tools.ietf.org/html/rfc7230#section-3.2 var preProcessedHeaders = rawHeaders.replace(/\r?\n[\t ]+/g, ' '); preProcessedHeaders.split(/\r?\n/).forEach(function(line) { var parts = line.split(':'); var key = parts.shift().trim(); if (key) { var value = parts.join(':').trim(); headers.append(key, value); } }); return headers } Body.call(Request$1.prototype); function Response(bodyInit, options) { if (!options) { options = {}; } this.type = 'default'; this.status = options.status === undefined ? 200 : options.status; this.ok = this.status >= 200 && this.status < 300; this.statusText = 'statusText' in options ? options.statusText : 'OK'; this.headers = new Headers$1(options.headers); this.url = options.url || ''; this._initBody(bodyInit); } Body.call(Response.prototype); Response.prototype.clone = function() { return new Response(this._bodyInit, { status: this.status, statusText: this.statusText, headers: new Headers$1(this.headers), url: this.url }) }; Response.error = function() { var response = new Response(null, {status: 0, statusText: ''}); response.type = 'error'; return response }; var redirectStatuses = [301, 302, 303, 307, 308]; Response.redirect = function(url, status) { if (redirectStatuses.indexOf(status) === -1) { throw new RangeError('Invalid status code') } return new Response(null, {status: status, headers: {location: url}}) }; var DOMException = self.DOMException; try { new DOMException(); } catch (err) { DOMException = function(message, name) { this.message = message; this.name = name; var error = Error(message); this.stack = error.stack; }; DOMException.prototype = Object.create(Error.prototype); DOMException.prototype.constructor = DOMException; } function fetch$1(input, init) { return new Promise(function(resolve, reject) { var request = new Request$1(input, init); if (request.signal && request.signal.aborted) { return reject(new DOMException('Aborted', 'AbortError')) } var xhr = new XMLHttpRequest(); function abortXhr() { xhr.abort(); } xhr.onload = function() { var options = { status: xhr.status, statusText: xhr.statusText, headers: parseHeaders(xhr.getAllResponseHeaders() || '') }; options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL'); var body = 'response' in xhr ? xhr.response : xhr.responseText; resolve(new Response(body, options)); }; xhr.onerror = function() { reject(new TypeError('Network request failed')); }; xhr.ontimeout = function() { reject(new TypeError('Network request failed')); }; xhr.onabort = function() { reject(new DOMException('Aborted', 'AbortError')); }; xhr.open(request.method, request.url, true); if (request.credentials === 'include') { xhr.withCredentials = true; } else if (request.credentials === 'omit') { xhr.withCredentials = false; } if ('responseType' in xhr && support.blob) { xhr.responseType = 'blob'; } request.headers.forEach(function(value, name) { xhr.setRequestHeader(name, value); }); if (request.signal) { request.signal.addEventListener('abort', abortXhr); xhr.onreadystatechange = function() { // DONE (success or failure) if (xhr.readyState === 4) { request.signal.removeEventListener('abort', abortXhr); } }; } xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit); }) } fetch$1.polyfill = true; if (!self.fetch) { self.fetch = fetch$1; self.Headers = Headers$1; self.Request = Request$1; self.Response = Response; } var globalHeaders = { "Content-Type": "application/json" }; var globalOption = { headers: new Headers(globalHeaders), mode: "same-origin", credentials: "include", cache: "reload", redirect: "follow", timeout: 30000, fetchStart: function fetchStart(param) { return param; } }; var mergeOptions = function mergeOptions() { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } var myOptions = _extends.apply(void 0, [{}].concat(args)); var resultHealers = _extends({}, globalHeaders, myOptions.headers); var resultOptions = null; resultOptions = _extends({}, globalOption, myOptions); resultOptions.headers = new Headers(resultHealers); return { resultOptions: resultOptions, resultHealers: resultHealers }; }; var setOptions = function setOptions(options) { globalOption = mergeOptions(options).resultOptions; globalHeaders = mergeOptions(options).resultHealers; }; var parseJSON = function parseJSON(response) { var maxErrorRes = 500; return response.text().then(function (text) { try { return JSON.parse(text); } catch (err) { throw new Error("JSON Parse Error: ".concat(err, ", URL: ").concat(response.url, ", ").concat(text.slice(0, maxErrorRes))); } }); }; var checkStatus = function checkStatus(response) { if (response.status >= 200 && response.status < 300 || response.status == 304) { return response; } else { throw new Error("HTTP Status Code: ".concat(response.status, ", URL: ").concat(response.url)); } }; var setGetURL = function setGetURL(url) { var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; if (Object.prototype.toString.call(data) !== "[object Object]" || Object.keys(data).length === 0) { return url; } var list = []; for (var key in data) { list.push("".concat(encodeURIComponent(key), "=").concat(encodeURIComponent(data[key]))); } return url + (url.indexOf("?") === -1 ? "?" : "") + list.join("&"); }; var getJSON = function getJSON(url) { var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var option = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var fetchOption = mergeOptions({ method: "GET" }, option).resultOptions; var fetchURL = setGetURL(url, data); return _fetch(fetchURL, fetchOption).then(parseJSON).then(handleFetchPass, handleFetchError); }; var deleteJSON = function deleteJSON(url) { var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var option = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var fetchOption = mergeOptions({ method: "DELETE" }, option).resultOptions; var fetchURL = setGetURL(url, data); return _fetch(fetchURL, fetchOption).then(parseJSON).then(handleFetchPass, handleFetchError); }; var postJSON = function postJSON(url) { var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var option = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var fetchOption = mergeOptions({ method: "POST", body: JSON.stringify(data) }, option).resultOptions; var fetchURL = url; return _fetch(fetchURL, fetchOption).then(parseJSON).then(handleFetchPass, handleFetchError); }; var putJSON = function putJSON(url) { var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var option = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var fetchOption = mergeOptions({ method: "PUT", body: JSON.stringify(data) }, option).resultOptions; var fetchURL = url; return _fetch(fetchURL, fetchOption).then(parseJSON).then(handleFetchPass, handleFetchError); }; var handleFetchPass = function handleFetchPass(data) { typeof globalOption.fetchSuccess === "function" && globalOption.fetchSuccess(data); return data; }; var handleFetchError = function handleFetchError(error) { typeof globalOption.fetchError === "function" && globalOption.fetchError(error); error = error instanceof Error ? error : new Error(error); throw error; }; var getJSONP = function getJSONP(url) { var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var option = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var callbackValue = "jsonp" + +new Date(); var jsonpElement = document.createElement("script"); data[option.callbackName || "_callback"] = callbackValue; var fetchURL = setGetURL(url, data); var head = document.head || document.querySelector("head") || document.documentElement; jsonpElement.setAttribute("src", fetchURL); jsonpElement.setAttribute("charset", "utf-8"); jsonpElement.setAttribute("defer", true); jsonpElement.setAttribute("async", true); head.insertBefore(jsonpElement, head.firstChild); return new Promise(function (resolve, reject) { window[callbackValue] = function (payload) { resolve(payload); head.removeChild(jsonpElement); }; jsonpElement.onerror = function () { reject(); head.removeChild(jsonpElement); }; }); }; var _fetch = function _fetch(url, fetchOption) { return new Promise(function (resolve, reject) { var timer = 0; Promise.resolve(fetchOption.fetchStart({ url: url, fetchOption: fetchOption })).then(function (param) { if (param === false) { var error = new Error("".concat(param.url, " cancel")); error.fetchOption = param.fetchOption; reject(error); } var myRequest = new Request(param.url, param.fetchOption); timer = setTimeout(function () { var error = new Error("".concat(param.url, " timeout")); error.fetchOption = param.fetchOption; reject(error); }, param.fetchOption.timeout); return fetch(myRequest); }).then(function (response) { clearTimeout(timer); response.fetchOption = fetchOption; resolve(response); }, function (error) { clearTimeout(timer); error.url = url; error.fetchOption = fetchOption; reject(error); }); }).then(checkStatus); }; var main = { setOptions: setOptions, getJSONP: getJSONP, getJSON: getJSON, postJSON: postJSON, putJSON: putJSON, deleteJSON: deleteJSON }; return main; })));