Идея заключается в том, чтобы собственный код IOS загружался в файл моста javascript до того, как в WKWebView загрузится веб-представление, содержащее потенциально сложный javascript и HTML.Этот мост javascript переопределяет методы open (), send (), fetch () и связанные с ними объекты XMLHttpRequst для маршрутизации всего трафика Http через собственный код IOS, а не напрямую через XHR.Если запрос является асинхронным, то создается Promise, и resolPromise () вызывается собственным кодом IOS, когда ответ готов к возвращению.
XMLHttpRequest.prototype.send = function(data) {
console.log("Overriden ajax ::XMLHttpRequest.prototype.send:", arguments);
console.log('uri',this.uri);
console.log("xhrObj::", this);
if(!this.uri) {
return this.realSend.apply(this, arguments);
}
// generate a unique id to reference the promise later from native function
var promiseId = generateUUID();
updateReadyState(this, 2);
delegateHttpToNativeWithPromise(promiseId, this, this.uri, this.httpMethod, data)
.then(function(responseWrapper) {
console.log('send resolve() - promise returned with responseWrapper', responseWrapper);
updateReadyState(responseWrapper.xhrObj, 3)
updateReadyState(responseWrapper.xhrObj, 4)
return responseWrapper.response;
}, function(xhrObj) {
console.log('send reject() - promise errorred with responseWrapper', responseWrapper);
updateReadyState(responseWrapper.xhrObj, 3)
updateReadyState(responseWrapper.xhrObj, 4)
return responseWrapper.response;
});
}
function delegateHttpToNativeWithPromise(promiseId, xhrObject, relativeIBAuthUri, methodType, payload) {
var promise = new Promise(function(resolve, reject) {
methodType = methodType || "get";
// save reference to promise in the global variable
promises[promiseId] = { resolve, reject, xhrObject };
try {
// call native function
if(window.webkit) {
window.webkit.messageHandlers.nativeNetwork.postMessage({
promiseId: promiseId,
apiUri: relativeIBAuthUri,
methodType: methodType,
requestHeaders : requestHeaders,
payload: payload});
}
requestHeaders = [];
}
catch(exception) {
console.error(exception)
// handle it somehow
}
});
return promise;
}
function resolvePromise(promiseId, status, headers, encodedResponse, error) {
var response = atob(encodedResponse);
if(promises[promiseId]) {
var xhrObj = promises[promiseId].xhrObject || null;
if(xhrObj != null) {
setReadOnlyProperty(xhrObj, "response", response);
setReadOnlyProperty(xhrObj, "responseText", response);
setReadOnlyProperty(xhrObj, "status", status);
setReadOnlyProperty(xhrObj, "statusText", "OK");
setReadOnlyProperty(xhrObj, "responseHeaders",headers);
}
if (error){
console.log('resolvePromise - error', error);
promises[promiseId].reject({response: response, xhrObj:xhrObj});
} else{
console.log('resolvePromise - success, resolving...');
promises[promiseId].resolve({response: response, xhrObj:xhrObj});
}
// remove reference to stored promise
delete promises[promiseId];
}
else {
console.log('promiseId not found in ', promises);
}
}
XMLHttpRequest.prototype.getResponseHeader = function(header) {
console.log('getResponseHeader', this);
if(!this.responseHeaders || this.responseHeaders == null) {
return null;
}
return this.responseHeaders[header];
}
XMLHttpRequest.prototype.getAllResponseHeaders = function() {
if(!this.responseHeaders || this.responseHeaders == null) {
return "";
}
var response = "";
for(header in this.responseHeaders) {
response += header+": "+this.responseHeaders[header]+"\r\n";
}
console.log('getAllResponseHeaders',response);
return response;
}
Можно ли успешно переопределить все эти методы?Мои первоначальные результаты указывают на НЕТ, потому что сложности нативных методов XHR не могут быть воспроизведены в Javascript.