forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			103 lines
		
	
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			103 lines
		
	
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| // Strictly follow RFC 3986 when encoding URI components.
 | |
| // Accepts a unescaped string and returns the URI encoded string for use in
 | |
| // an HTTP request.
 | |
| export function percentEncode(aString) {
 | |
|   return encodeURIComponent(aString)
 | |
|     .replace(/[!'()]/g, escape)
 | |
|     .replace(/\*/g, "%2A");
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * aOptions can have a variety of fields:
 | |
|  *  headers, an array of headers
 | |
|  *  postData, this can be:
 | |
|  *    a string: send it as is
 | |
|  *    an array of parameters: encode as form values
 | |
|  *    null/undefined: no POST data.
 | |
|  *  method, GET, POST or PUT (this is set automatically if postData exists).
 | |
|  *  onLoad, a function handle to call when the load is complete, it takes two
 | |
|  *          parameters: the responseText and the XHR object.
 | |
|  *  onError, a function handle to call when an error occcurs, it takes three
 | |
|  *          parameters: the error, the responseText and the XHR object.
 | |
|  *  logger, an object that implements the debug and log methods (e.g. Log.sys.mjs).
 | |
|  *
 | |
|  * Headers or post data are given as an array of arrays, for each each inner
 | |
|  * array the first value is the key and the second is the value, e.g.
 | |
|  *  [["key1", "value1"], ["key2", "value2"]].
 | |
|  */
 | |
| export function httpRequest(aUrl, aOptions) {
 | |
|   let xhr = new XMLHttpRequest();
 | |
|   xhr.mozBackgroundRequest = true; // no error dialogs
 | |
|   xhr.open(aOptions.method || (aOptions.postData ? "POST" : "GET"), aUrl);
 | |
|   xhr.channel.loadFlags =
 | |
|     Ci.nsIChannel.LOAD_ANONYMOUS | // don't send cookies
 | |
|     Ci.nsIChannel.LOAD_BYPASS_CACHE |
 | |
|     Ci.nsIChannel.INHIBIT_CACHING;
 | |
|   xhr.onerror = function(aProgressEvent) {
 | |
|     if (aOptions.onError) {
 | |
|       // adapted from toolkit/mozapps/extensions/nsBlocklistService.js
 | |
|       let request = aProgressEvent.target;
 | |
|       let status;
 | |
|       try {
 | |
|         // may throw (local file or timeout)
 | |
|         status = request.status;
 | |
|       } catch (e) {
 | |
|         request = request.channel.QueryInterface(Ci.nsIRequest);
 | |
|         status = request.status;
 | |
|       }
 | |
|       // When status is 0 we don't have a valid channel.
 | |
|       let statusText = status ? request.statusText : "offline";
 | |
|       aOptions.onError(statusText, null, this);
 | |
|     }
 | |
|   };
 | |
|   xhr.onload = function(aRequest) {
 | |
|     try {
 | |
|       let target = aRequest.target;
 | |
|       if (aOptions.logger) {
 | |
|         aOptions.logger.debug("Received response: " + target.responseText);
 | |
|       }
 | |
|       if (target.status < 200 || target.status >= 300) {
 | |
|         let errorText = target.responseText;
 | |
|         if (!errorText || /<(ht|\?x)ml\b/i.test(errorText)) {
 | |
|           errorText = target.statusText;
 | |
|         }
 | |
|         throw new Error(target.status + " - " + errorText);
 | |
|       }
 | |
|       if (aOptions.onLoad) {
 | |
|         aOptions.onLoad(target.responseText, this);
 | |
|       }
 | |
|     } catch (e) {
 | |
|       if (aOptions.onError) {
 | |
|         aOptions.onError(e, aRequest.target.responseText, this);
 | |
|       }
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   if (aOptions.headers) {
 | |
|     aOptions.headers.forEach(function(header) {
 | |
|       xhr.setRequestHeader(header[0], header[1]);
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   // Handle adding postData as defined above.
 | |
|   let POSTData = aOptions.postData || null;
 | |
|   if (POSTData && Array.isArray(POSTData)) {
 | |
|     xhr.setRequestHeader(
 | |
|       "Content-Type",
 | |
|       "application/x-www-form-urlencoded; charset=utf-8"
 | |
|     );
 | |
|     POSTData = POSTData.map(p => p[0] + "=" + percentEncode(p[1])).join("&");
 | |
|   }
 | |
| 
 | |
|   if (aOptions.logger) {
 | |
|     aOptions.logger.log(
 | |
|       "sending request to " + aUrl + " (POSTData = " + POSTData + ")"
 | |
|     );
 | |
|   }
 | |
|   xhr.send(POSTData);
 | |
|   return xhr;
 | |
| }
 | 
