To add custom headers to AJAX requests, I use a combination of two three hacks. The first provides a synchronous communication channel between my native Swift code and javascript. The second overrides the XMLHttpRequest send() method. The third injects the override into the web page that is loaded into my WKWebView.
So, the combination works like this:
instead of request.setValue("value", forHTTPHeaderField: "key"):
in the ViewController:
func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt headerName: String, defaultText _: String?, initiatedByFrame _: WKFrameInfo, completionHandler: @escaping (String?) -> Void) {
if headerName == "key" {
completionHandler("value")
} else {
completionHandler(nil)
}
}}
in 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))
and this is the test HTML file:
<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>
Call to /ajax
brings a generic echo, including all request headers. This way I know that the task is fullfilled.