2009-03-10 32 views

Trả lời

0

Không chắc chắn nếu bạn có thể làm điều đó với greasemonkey, nhưng nếu bạn tạo một phần mở rộng thì bạn có thể sử dụng dịch vụ quan sát viên và người quan sát http-on-exam-response.

3

Làm thế nào về việc sửa đổi XMLHttpRequest.prototype.open hoặc gửi phương thức với các thay thế thiết lập callbacks của riêng chúng và gọi các phương thức gốc? Gọi lại có thể làm điều của nó và sau đó gọi lại mã ban đầu được chỉ định.

Nói cách khác:

XMLHttpRequest.prototype.realOpen = XMLHttpRequest.prototype.open; 

var myOpen = function(method, url, async, user, password) { 
    //do whatever mucking around you want here, e.g. 
    //changing the onload callback to your own version 


    //call original 
    this.realOpen (method, url, async, user, password); 
} 


//ensure all XMLHttpRequests use our custom open method 
XMLHttpRequest.prototype.open = myOpen ; 
1

Bạn có thể thay thế các đối tượng unsafeWindow.XMLHttpRequest trong tài liệu với một wrapper. Một mã nhỏ (không kiểm tra):

var oldFunction = unsafeWindow.XMLHttpRequest; 
unsafeWindow.XMLHttpRequest = function() { 
    alert("Hijacked! XHR was constructed."); 
    var xhr = oldFunction(); 
    return { 
    open: function(method, url, async, user, password) { 
     alert("Hijacked! xhr.open()."); 
     return xhr.open(method, url, async, user, password); 
    } 
    // TODO: include other xhr methods and properties 
    }; 
}; 

Nhưng điều này có một vấn đề nhỏ: script Greasemonkey thực hiện sau một tải trang, vì vậy trang có thể sử dụng hoặc lưu trữ các đối tượng XMLHttpRequest gốc trong đó là chuỗi tải, vì vậy yêu cầu được thực hiện trước khi tập lệnh của bạn thực hiện hoặc với đối tượng XMLHttpRequest thực sự sẽ không được theo dõi bởi tập lệnh của bạn. Không có cách nào mà tôi có thể thấy để làm việc xung quanh giới hạn này.

34

Câu trả lời được chấp nhận gần như chính xác, nhưng nó có thể sử dụng một sự cải thiện nhẹ:

(function(open) { 
    XMLHttpRequest.prototype.open = function() { 
     this.addEventListener("readystatechange", function() { 
      console.log(this.readyState); 
     }, false); 
     open.apply(this, arguments); 
    }; 
})(XMLHttpRequest.prototype.open); 

thích sử dụng áp dụng đối số + qua cuộc gọi vì sau đó bạn không có để biết rõ tất cả các đối số được đưa ra để mở có thể thay đổi!

0

Tested trong Chrome 55 và Firefox 50.1.0

Trong trường hợp của tôi, tôi muốn thay đổi responseText, mà trong Firefox là một thuộc tính chỉ đọc, vì vậy tôi đã phải quấn toàn bộ đối tượng XMLHttpRequest. Tôi đã không thực hiện toàn bộ API (cụ thể là responseType), nhưng nó đã đủ tốt để sử dụng cho tất cả các thư viện mà tôi có.

Cách sử dụng:

XHRProxy.addInterceptor(function(method, url, responseText, status) { 
     if (url.endsWith('.html') || url.endsWith('.htm')) { 
      return "<!-- HTML! -->" + responseText; 
     } 
    }); 

Code:

(function(window) { 

    var OriginalXHR = XMLHttpRequest; 

    var XHRProxy = function() { 
     this.xhr = new OriginalXHR(); 

     function delegate(prop) { 
      Object.defineProperty(this, prop, { 
       get: function() { 
        return this.xhr[prop]; 
       }, 
       set: function(value) { 
        this.xhr.timeout = value; 
       } 
      }); 
     } 
     delegate.call(this, 'timeout'); 
     delegate.call(this, 'responseType'); 
     delegate.call(this, 'withCredentials'); 
     delegate.call(this, 'onerror'); 
     delegate.call(this, 'onabort'); 
     delegate.call(this, 'onloadstart'); 
     delegate.call(this, 'onloadend'); 
     delegate.call(this, 'onprogress'); 
    }; 
    XHRProxy.prototype.open = function(method, url, async, username, password) { 
     var ctx = this; 

     function applyInterceptors(src) { 
      ctx.responseText = ctx.xhr.responseText; 
      for (var i=0; i < XHRProxy.interceptors.length; i++) { 
       var applied = XHRProxy.interceptors[i](method, url, ctx.responseText, ctx.xhr.status); 
       if (applied !== undefined) { 
        ctx.responseText = applied; 
       } 
      } 
     } 
     function setProps() { 
      ctx.readyState = ctx.xhr.readyState; 
      ctx.responseText = ctx.xhr.responseText; 
      ctx.responseURL = ctx.xhr.responseURL; 
      ctx.responseXML = ctx.xhr.responseXML; 
      ctx.status = ctx.xhr.status; 
      ctx.statusText = ctx.xhr.statusText; 
     } 

     this.xhr.open(method, url, async, username, password); 

     this.xhr.onload = function(evt) { 
      if (ctx.onload) { 
       setProps(); 

       if (ctx.xhr.readyState === 4) { 
        applyInterceptors(); 
       } 
       return ctx.onload(evt); 
      } 
     }; 
     this.xhr.onreadystatechange = function (evt) { 
      if (ctx.onreadystatechange) { 
       setProps(); 

       if (ctx.xhr.readyState === 4) { 
        applyInterceptors(); 
       } 
       return ctx.onreadystatechange(evt); 
      } 
     }; 
    }; 
    XHRProxy.prototype.addEventListener = function(event, fn) { 
     return this.xhr.addEventListener(event, fn); 
    }; 
    XHRProxy.prototype.send = function(data) { 
     return this.xhr.send(data); 
    }; 
    XHRProxy.prototype.abort = function() { 
     return this.xhr.abort(); 
    }; 
    XHRProxy.prototype.getAllResponseHeaders = function() { 
     return this.xhr.getAllResponseHeaders(); 
    }; 
    XHRProxy.prototype.getResponseHeader = function(header) { 
     return this.xhr.getResponseHeader(header); 
    }; 
    XHRProxy.prototype.setRequestHeader = function(header, value) { 
     return this.xhr.setRequestHeader(header, value); 
    }; 
    XHRProxy.prototype.overrideMimeType = function(mimetype) { 
     return this.xhr.overrideMimeType(mimetype); 
    }; 

    XHRProxy.interceptors = []; 
    XHRProxy.addInterceptor = function(fn) { 
     this.interceptors.push(fn); 
    }; 

    window.XMLHttpRequest = XHRProxy; 

})(window); 
Các vấn đề liên quan