You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					223 lines
				
				7.2 KiB
			
		
		
			
		
	
	
					223 lines
				
				7.2 KiB
			| 
											3 years ago
										 | 'use strict'; | ||
|  | 
 | ||
|  | var utils = require('./../utils'); | ||
|  | var settle = require('./../core/settle'); | ||
|  | var cookies = require('./../helpers/cookies'); | ||
|  | var buildURL = require('./../helpers/buildURL'); | ||
|  | var buildFullPath = require('../core/buildFullPath'); | ||
|  | var parseHeaders = require('./../helpers/parseHeaders'); | ||
|  | var isURLSameOrigin = require('./../helpers/isURLSameOrigin'); | ||
|  | var transitionalDefaults = require('../defaults/transitional'); | ||
|  | var AxiosError = require('../core/AxiosError'); | ||
|  | var CanceledError = require('../cancel/CanceledError'); | ||
|  | var parseProtocol = require('../helpers/parseProtocol'); | ||
|  | 
 | ||
|  | 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 (config.signal) { | ||
|  |         config.signal.removeEventListener('abort', onCanceled); | ||
|  |       } | ||
|  |     } | ||
|  | 
 | ||
|  |     if (utils.isFormData(requestData) && utils.isStandardBrowserEnv()) { | ||
|  |       delete requestHeaders['Content-Type']; // Let the browser set it
 | ||
|  |     } | ||
|  | 
 | ||
|  |     var request = new XMLHttpRequest(); | ||
|  | 
 | ||
|  |     // HTTP basic authentication
 | ||
|  |     if (config.auth) { | ||
|  |       var username = config.auth.username || ''; | ||
|  |       var password = config.auth.password ? unescape(encodeURIComponent(config.auth.password)) : ''; | ||
|  |       requestHeaders.Authorization = 'Basic ' + btoa(username + ':' + password); | ||
|  |     } | ||
|  | 
 | ||
|  |     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; | ||
|  | 
 | ||
|  |     function onloadend() { | ||
|  |       if (!request) { | ||
|  |         return; | ||
|  |       } | ||
|  |       // Prepare the response
 | ||
|  |       var responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null; | ||
|  |       var responseData = !responseType || responseType === 'text' ||  responseType === 'json' ? | ||
|  |         request.responseText : request.response; | ||
|  |       var response = { | ||
|  |         data: responseData, | ||
|  |         status: request.status, | ||
|  |         statusText: request.statusText, | ||
|  |         headers: responseHeaders, | ||
|  |         config: config, | ||
|  |         request: request | ||
|  |       }; | ||
|  | 
 | ||
|  |       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() { | ||
|  |       if (!request) { | ||
|  |         return; | ||
|  |       } | ||
|  | 
 | ||
|  |       reject(new AxiosError('Request aborted', AxiosError.ECONNABORTED, config, request)); | ||
|  | 
 | ||
|  |       // Clean up request
 | ||
|  |       request = null; | ||
|  |     }; | ||
|  | 
 | ||
|  |     // Handle low level network errors
 | ||
|  |     request.onerror = function handleError() { | ||
|  |       // Real errors are hidden from us by the browser
 | ||
|  |       // onerror should only fire if it's a network error
 | ||
|  |       reject(new AxiosError('Network Error', AxiosError.ERR_NETWORK, config, request, request)); | ||
|  | 
 | ||
|  |       // Clean up request
 | ||
|  |       request = null; | ||
|  |     }; | ||
|  | 
 | ||
|  |     // Handle timeout
 | ||
|  |     request.ontimeout = function handleTimeout() { | ||
|  |       var timeoutErrorMessage = config.timeout ? 'timeout of ' + config.timeout + 'ms exceeded' : 'timeout exceeded'; | ||
|  |       var transitional = config.transitional || transitionalDefaults; | ||
|  |       if (config.timeoutErrorMessage) { | ||
|  |         timeoutErrorMessage = config.timeoutErrorMessage; | ||
|  |       } | ||
|  |       reject(new AxiosError( | ||
|  |         timeoutErrorMessage, | ||
|  |         transitional.clarifyTimeoutError ? AxiosError.ETIMEDOUT : AxiosError.ECONNABORTED, | ||
|  |         config, | ||
|  |         request)); | ||
|  | 
 | ||
|  |       // Clean up request
 | ||
|  |       request = null; | ||
|  |     }; | ||
|  | 
 | ||
|  |     // Add xsrf header
 | ||
|  |     // This is only done if running in a standard browser environment.
 | ||
|  |     // Specifically not if we're in a web worker, or react-native.
 | ||
|  |     if (utils.isStandardBrowserEnv()) { | ||
|  |       // Add xsrf header
 | ||
|  |       var xsrfValue = (config.withCredentials || isURLSameOrigin(fullPath)) && config.xsrfCookieName ? | ||
|  |         cookies.read(config.xsrfCookieName) : | ||
|  |         undefined; | ||
|  | 
 | ||
|  |       if (xsrfValue) { | ||
|  |         requestHeaders[config.xsrfHeaderName] = xsrfValue; | ||
|  |       } | ||
|  |     } | ||
|  | 
 | ||
|  |     // Add headers to the request
 | ||
|  |     if ('setRequestHeader' in request) { | ||
|  |       utils.forEach(requestHeaders, function setRequestHeader(val, key) { | ||
|  |         if (typeof requestData === 'undefined' && key.toLowerCase() === 'content-type') { | ||
|  |           // Remove Content-Type if data is undefined
 | ||
|  |           delete requestHeaders[key]; | ||
|  |         } else { | ||
|  |           // Otherwise add header to the request
 | ||
|  |           request.setRequestHeader(key, val); | ||
|  |         } | ||
|  |       }); | ||
|  |     } | ||
|  | 
 | ||
|  |     // Add withCredentials to request if needed
 | ||
|  |     if (!utils.isUndefined(config.withCredentials)) { | ||
|  |       request.withCredentials = !!config.withCredentials; | ||
|  |     } | ||
|  | 
 | ||
|  |     // Add responseType to request if needed
 | ||
|  |     if (responseType && responseType !== 'json') { | ||
|  |       request.responseType = config.responseType; | ||
|  |     } | ||
|  | 
 | ||
|  |     // Handle progress if needed
 | ||
|  |     if (typeof config.onDownloadProgress === 'function') { | ||
|  |       request.addEventListener('progress', config.onDownloadProgress); | ||
|  |     } | ||
|  | 
 | ||
|  |     // Not all browsers support upload events
 | ||
|  |     if (typeof config.onUploadProgress === 'function' && request.upload) { | ||
|  |       request.upload.addEventListener('progress', config.onUploadProgress); | ||
|  |     } | ||
|  | 
 | ||
|  |     if (config.cancelToken || config.signal) { | ||
|  |       // Handle cancellation
 | ||
|  |       // eslint-disable-next-line func-names
 | ||
|  |       onCanceled = function(cancel) { | ||
|  |         if (!request) { | ||
|  |           return; | ||
|  |         } | ||
|  |         reject(!cancel || (cancel && cancel.type) ? new CanceledError() : cancel); | ||
|  |         request.abort(); | ||
|  |         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); | ||
|  |   }); | ||
|  | }; |