How to add HTTP headers in request globally for iOS in swift How to add HTTP headers in request globally for iOS in swift ios ios

How to add HTTP headers in request globally for iOS in swift

AFAIK sadly you cannot do this with WKWebView.

It most certainly does not work in webView:decidePolicyForNavigationAction:decisionHandler: because the navigationAction.request is read-only and a non-mutable NSURLRequest instance that you cannot change.

If I understand correctly, WKWebView runs sandboxed in a separate content and network process and, at least on iOS, there is no way to intercept or change it's network requests.

You can do this if you step back to UIWebView.

There are many different ways to do that, I found that the easiest solution was to subclass WKWebView and override the loadRequest method. Something like this:

class CustomWebView: WKWebView {    override func load(_ request: URLRequest) -> WKNavigation? {        guard let mutableRequest: NSMutableURLRequest = request as? NSMutableURLRequest else {            return super.load(request)        }        mutableRequest.setValue("custom value", forHTTPHeaderField: "custom field")        return super.load(mutableRequest as URLRequest)    }}

Then simply use the CustomWebView class as if it was a WKWebView.

EDIT NOTE: This will only work on the first request as pointed out by @Stefan Arentz.

NOTE: Some fields cannot be overridden and will not be changed. I haven't done a thorough testing but I know that the User-Agent field cannot be overridden unless you do a specific hack (check here for an answer to that)

I have modified Au Ris answer to use NavigationAction instead of NavigationResponse, as jonny suggested. Also, this fixes situations where the same url is called subsequently and you don't have to keep track of the current url anymore. This only works for GET requests but can surely be adapted for other request types if neccessary.

import UIKitimport WebKitclass ViewController: UIViewController, WKNavigationDelegate  {    var webView: WKWebView?    override func viewDidLoad() {        super.viewDidLoad()        webView = WKWebView(frame:        webView!.navigationDelegate = self        view.addSubview(webView!)        // [...] set constraints and stuff        // Load first request with initial url        loadWebPage(url: "https://my.url")    }    func loadWebPage(url: URL)  {        var customRequest = URLRequest(url: url)        customRequest.setValue("true", forHTTPHeaderField: "x-custom-header")        webView!.load(customRequest)    }    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping    (WKNavigationActionPolicy) -> Void) {        if navigationAction.request.httpMethod != "GET" || navigationAction.request.value(forHTTPHeaderField: "x-custom-header") != nil {            // not a GET or already a custom request - continue            decisionHandler(.allow)            return        }        decisionHandler(.cancel)        loadWebPage(url: navigationAction.request.url!)    }