Это абсолютно возможно.
Этот пояс показывает, как просто получить его копию: https://gist.github.com/Noitidart/d0b08629ee2804538ad9 - вы можете скопировать и вставить это в блокнот, нажать пробег и увидеть его в действии.
Обратите внимание на линии 44, он устанавливает this.responseBody = this.receivedChunks.join('');
Так в основном вы бы установить this.responseBody
все, что вы хотите
Heres код с сутью:
var {classes: Cc, interfaces: Ci, results: Cr, Constructor: CC, utils: Cu} = Components;
Cu.import('resource://gre/modules/Services.jsm');
var BinaryInputStream = CC('@mozilla.org/binaryinputstream;1', 'nsIBinaryInputStream', 'setInputStream');
var BinaryOutputStream = CC('@mozilla.org/binaryoutputstream;1', 'nsIBinaryOutputStream', 'setOutputStream');
var StorageStream = CC('@mozilla.org/storagestream;1', 'nsIStorageStream', 'init');
function TracingListener() {
this.receivedChunks = []; // array for incoming data. holds chunks as they come, onStopRequest we join these junks to get the full source
this.responseBody; // we'll set this to the
this.responseStatusCode;
this.deferredDone = {
promise: null,
resolve: null,
reject: null
};
this.deferredDone.promise = new Promise(function(resolve, reject) {
this.resolve = resolve;
this.reject = reject;
}.bind(this.deferredDone));
Object.freeze(this.deferredDone);
this.promiseDone = this.deferredDone.promise;
}
TracingListener.prototype = {
onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) {
var iStream = new BinaryInputStream(aInputStream) // binaryaInputStream
var sStream = new StorageStream(8192, aCount); // storageStream // not sure why its 8192 but thats how eveyrone is doing it, we should ask why
var oStream = new BinaryOutputStream(sStream.getOutputStream(0)); // binaryOutputStream
// Copy received data as they come.
var data = iStream.readBytes(aCount);
this.receivedChunks.push(data);
oStream.writeBytes(data, aCount);
this.originalListener.onDataAvailable(aRequest, aContext, sStream.newInputStream(0), aOffset, aCount);
},
onStartRequest: function(aRequest, aContext) {
this.originalListener.onStartRequest(aRequest, aContext);
},
onStopRequest: function(aRequest, aContext, aStatusCode) {
this.responseBody = this.receivedChunks.join('');
delete this.receivedChunks;
this.responseStatus = aStatusCode;
this.originalListener.onStopRequest(aRequest, aContext, aStatusCode);
this.deferredDone.resolve();
},
QueryInterface: function(aIID) {
if (aIID.equals(Ci.nsIStreamListener) || aIID.equals(Ci.nsISupports)) {
return this;
}
throw Cr.NS_NOINTERFACE;
}
};
var httpResponseObserver = {
observe: function(aSubject, aTopic, aData) {
var newListener = new TracingListener();
aSubject.QueryInterface(Ci.nsITraceableChannel);
newListener.originalListener = aSubject.setNewListener(newListener);
/////// END - DO NOT EDIT
newListener.promiseDone.then(
function() {
// no error happened
console.log('yay response done:', newListener.responseBody);
},
function(aReason) {
// promise was rejected, right now i didnt set up rejection, but i should listen to on abort or bade status code then reject maybe
}
).catch(
function(aCatch) {
console.error('something went wrong, a typo by dev probably:', aCatch);
}
);
}
};
Services.obs.addObserver(httpResponseObserver, 'http-on-examine-response', false);
// Services.obs.removeObserver(httpResponseObserver, 'http-on-examine-response'); // call this when you dont want to listen anymore
Это уже то, что я делаю (см. https://github.com/BruceBerry/addon-proxy/blob/master/proxy.js), и есть множество примеров этого. В отличие от обычного случая, когда вы хотите изменить реальный ответ с сервера, здесь я хочу вернуть полностью фальшивый ответ, так что применяются # 1 и # 2: с кодом, по которому вы отправляете запрос в сети без причины, вы ждут ответа на возврат данных, даже если данные уже доступны локально, и, самое главное, вы не можете изменить код состояния ответа, тип контента и другие значения. – BruceBerry
@BruceBerry Я уверен, что он не отправляет другой запрос. Он делает копию запроса. Если вы хотите подделать код статуса ответа, я не уверен, как это сделать. То, что я думаю, что вам следует делать, - это что-то вроде того, когда вы переходите на страницу с страницей загрузки проблем, вы видите, как они перенаправляют ее на другую страницу, но URL-адрес не изменяется? Посмотрите, как они это делают и разделяют. Я знаю, что новый URL-адрес отображается в 'nsiWebNavigation' like -' win.QueryInterface (Ci.nsIInterfaceRequestor) .getInterface (Ci.nsIWebNavigation) .document.documentURI; ' – Noitidart
Я посмотрю, спасибо. Мое требование состоит не в том, чтобы избежать второго запроса (как вы сказали, это не так), но и для того, чтобы избежать первого! Как только канал узнает, что этот запрос может фактически обслуживаться локально, он не должен отправлять какие-либо данные по сети и ждать ответа. – BruceBerry