为了向 AJAX 请求添加自定义标头,我使用了两个(现在是三个)技巧的组合。
first 提供了本地 Swift 代码和 JavaScript 之间的同步通信渠道。
second 覆盖了 XMLHttpRequest 的
send() 方法。
third 将这个覆盖注入到加载到我的 WKWebView 中的网页中。
所以,这个组合的工作方式如下:
不再使用
request.setValue("value", forHTTPHeaderField: "key"),而是:
在 ViewController 中:
func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt headerName: String, defaultText _: String?, initiatedByFrame _: WKFrameInfo, completionHandler: @escaping (String?) -> Void) {
if headerName == "key" {
completionHandler("value")
} else {
completionHandler(nil)
}
}}
在viewDidLoad方法中:
let script =
"XMLHttpRequest.prototype.realSend = XMLHttpRequest.prototype.send;"
"XMLHttpRequest.prototype.send = function (body) {"
"let value = window.prompt('key');"
"this.setRequestHeader('key', value);"
"this.realSend(body)"
"};"
webView.configuration.userContentController.addUserScript(WKUserScript(source: script, injectionTime: .atDocumentEnd, forMainFrameOnly: true))
这是测试HTML文件:
<html>
<head>
<script>
function loadAjax() {
const xmlhttp = new XMLHttpRequest()
xmlhttp.onload = function() {
document.getElementById("load").innerHTML = this.responseText
}
xmlhttp.open("GET", "/ajax")
xmlhttp.send()
}
</script>
</head>
<body>
<button onClick="loadAjax()">Change Content</button> <br />
<pre id="load">load…</pre>
</body>
</html>
调用
/ajax
会带来一个通用的回应,包括所有请求头。这样我就知道任务已经完成了。