mirror of
				https://github.com/zulip/zulip.git
				synced 2025-10-30 19:43:47 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			138 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			138 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| const pending_requests = [];
 | |
| 
 | |
| function add_pending_request(jqXHR) {
 | |
|     pending_requests.push(jqXHR);
 | |
|     if (pending_requests.length > 50) {
 | |
|         blueslip.warn('The length of pending_requests is over 50. Most likely ' +
 | |
|                       'they are not being correctly removed.');
 | |
|     }
 | |
| }
 | |
| 
 | |
| function remove_pending_request(jqXHR) {
 | |
|     const pending_request_index = pending_requests.indexOf(jqXHR);
 | |
|     if (pending_request_index !== -1) {
 | |
|         pending_requests.splice(pending_request_index, 1);
 | |
|     }
 | |
| }
 | |
| 
 | |
| function call(args, idempotent) {
 | |
|     if (reload_state.is_in_progress() && !args.ignore_reload) {
 | |
|         // If we're in the process of reloading, most HTTP requests
 | |
|         // are useless, with exceptions like cleaning up our event
 | |
|         // queue and blueslip (Which doesn't use channel.js).
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     // Wrap the error handlers to reload the page if we get a CSRF error
 | |
|     // (What probably happened is that the user logged out in another tab).
 | |
|     let orig_error = args.error;
 | |
|     if (orig_error === undefined) {
 | |
|         orig_error = function () {};
 | |
|     }
 | |
|     args.error = function wrapped_error(xhr, error_type, xhn) {
 | |
|         remove_pending_request(xhr);
 | |
| 
 | |
|         if (reload_state.is_in_progress()) {
 | |
|             // If we're in the process of reloading the browser,
 | |
|             // there's no point in running the success handler,
 | |
|             // because all of our state is about to be discarded
 | |
|             // anyway.
 | |
|             blueslip.log(`Ignoring ${args.type} ${args.url} error response while reloading`);
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         if (xhr.status === 403) {
 | |
|             try {
 | |
|                 if (JSON.parse(xhr.responseText).code === 'CSRF_FAILED') {
 | |
|                     reload.initiate({immediate: true,
 | |
|                                      save_pointer: true,
 | |
|                                      save_narrow: true,
 | |
|                                      save_compose: true});
 | |
|                 }
 | |
|             } catch (ex) {
 | |
|                 blueslip.error('Unexpected 403 response from server',
 | |
|                                {xhr: xhr.responseText,
 | |
|                                 args: args},
 | |
|                                ex.stack);
 | |
|             }
 | |
|         }
 | |
|         return orig_error(xhr, error_type, xhn);
 | |
|     };
 | |
|     let orig_success = args.success;
 | |
|     if (orig_success === undefined) {
 | |
|         orig_success = function () {};
 | |
|     }
 | |
|     args.success = function wrapped_success(data, textStatus, jqXHR) {
 | |
|         remove_pending_request(jqXHR);
 | |
| 
 | |
|         if (reload_state.is_in_progress()) {
 | |
|             // If we're in the process of reloading the browser,
 | |
|             // there's no point in running the success handler,
 | |
|             // because all of our state is about to be discarded
 | |
|             // anyway.
 | |
|             blueslip.log(`Ignoring ${args.type} ${args.url} response while reloading`);
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         if (!data && idempotent) {
 | |
|             // If idempotent, retry
 | |
|             blueslip.log("Retrying idempotent" + args);
 | |
|             setTimeout(function () {
 | |
|                 const jqXHR = $.ajax(args);
 | |
|                 add_pending_request(jqXHR);
 | |
|             }, 0);
 | |
|             return;
 | |
|         }
 | |
|         return orig_success(data, textStatus, jqXHR);
 | |
|     };
 | |
| 
 | |
|     const jqXHR = $.ajax(args);
 | |
|     add_pending_request(jqXHR);
 | |
|     return jqXHR;
 | |
| }
 | |
| 
 | |
| exports.get = function (options) {
 | |
|     const args = { type: "GET", dataType: "json", ...options };
 | |
|     return call(args, options.idempotent);
 | |
| };
 | |
| 
 | |
| exports.post = function (options) {
 | |
|     const args = { type: "POST", dataType: "json", ...options };
 | |
|     return call(args, options.idempotent);
 | |
| };
 | |
| 
 | |
| exports.put = function (options) {
 | |
|     const args = { type: "PUT", dataType: "json", ...options };
 | |
|     return call(args, options.idempotent);
 | |
| };
 | |
| 
 | |
| // Not called exports.delete because delete is a reserved word in JS
 | |
| exports.del = function (options) {
 | |
|     const args = { type: "DELETE", dataType: "json", ...options };
 | |
|     return call(args, options.idempotent);
 | |
| };
 | |
| 
 | |
| exports.patch = function (options) {
 | |
|     // Send a PATCH as a POST in order to work around QtWebkit
 | |
|     // (Linux/Windows desktop app) not supporting PATCH body.
 | |
|     if (options.processData === false) {
 | |
|         // If we're submitting a FormData object, we need to add the
 | |
|         // method this way
 | |
|         options.data.append("method", "PATCH");
 | |
|     } else {
 | |
|         options.data = { ...options.data, method: 'PATCH' };
 | |
|     }
 | |
|     return exports.post(options, options.idempotent);
 | |
| };
 | |
| 
 | |
| exports.xhr_error_message = function (message, xhr) {
 | |
|     if (xhr.status.toString().charAt(0) === "4") {
 | |
|         // Only display the error response for 4XX, where we've crafted
 | |
|         // a nice response.
 | |
|         message += ": " + JSON.parse(xhr.responseText).msg;
 | |
|     }
 | |
|     return message;
 | |
| };
 | |
| 
 | |
| window.channel = exports;
 |