1

I am using WKWebView in app & i am looking for getting all headers from wkwebview in finish loads method webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { Just like in UIWebView

func webViewDidFinishLoad(_ webView: UIWebView) {
        print("Finished loads---", webView.request?.allHTTPHeaderFields)
    }

How can we achieve that in WKWebView ?

Amit
  • 556
  • 1
  • 7
  • 24
  • So what's the issue? – El Tomato Jul 16 '21 at 04:58
  • I am not getting headers in `webView(_ webView: WKWebView, didFinish navigation: WKNavigation!` @ElTomato – Amit Jul 16 '21 at 05:01
  • @ElTomato in `webView(_ webView: WKWebView, didFinish navigation: WKNavigation!` the code `webView.request?.allHTTPHeaderFields` doesn't works. Could you please help. – Amit Jul 16 '21 at 05:18
  • I don't think you can with didFinish. – El Tomato Jul 16 '21 at 05:37
  • @ElTomato i have break down the problem here https://stackoverflow.com/questions/68403684/why-referer-appleapp-app-ios-header-not-displaying-in-wkwebview – Amit Jul 16 '21 at 05:38

2 Answers2

1

You need to set your view controller as the WKWebView Navigation Delegate WKNavigationDelegate and implement its decidePolicyFor method:

optional func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void)

Try like this:


func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
    let allHTTPHeaderFields = navigationAction.request.allHTTPHeaderFields ?? [:]
    for (key, value) in allHTTPHeaderFields {
        print("key:", key, "value:", value)
    }
    
    if navigationAction.navigationType == .linkActivated  {
        if let url = navigationAction.request.url,
            let host = url.host, !host.hasPrefix("www.google.com"),
            UIApplication.shared.canOpenURL(url) {
            UIApplication.shared.open(url)
            print(url)
            print("Redirected to browser. No need to open it locally")
            decisionHandler(.cancel)
        } else {
            print("Open it locally")
            decisionHandler(.allow)
        }
    } else {
        print("not a user click")
        decisionHandler(.allow)
    }
}
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
  • Doesn't the app crash if you don't set `decisionHandler(.allow)` or `decisionHandler(.cancel)`? – El Tomato Jul 16 '21 at 05:49
  • @LeoDabus @ElTomato Thanks But. if URL has multiple redirection then it doesn't captured in `decidePolicyFor navigationAction` It only shows very first URL – Amit Jul 16 '21 at 05:56
  • 1
    @Amit what do you want to do? It all depends how you are deciding which navigation you want to allow or not https://stackoverflow.com/a/36231713/2303865 – Leo Dabus Jul 16 '21 at 05:58
  • @LeoDabus. somehow we need to manage in `func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!)` which calls on every redirections so we can confirm that on every redirection headers are embedding correctly. :) This is i am looking for – Amit Jul 16 '21 at 06:02
  • @Amit not sure what are you asking. In your question you asked how to get the headers only when it finishes loading the web view. Is it what you are trying to achieve? – Leo Dabus Jul 16 '21 at 06:12
  • Yes @LeoDabus I Agree with your answer. But let say for example i have typed "Leo" in browser it will open search results now the on print statement Referer has changed `"Referer": "https://www.google.com/"` – Amit Jul 16 '21 at 06:22
  • @LeoDabus i have posted new question for referrer persist issue .https://stackoverflow.com/questions/68404439/persist-referer-header-in-ios-wkwebview – Amit Jul 16 '21 at 06:34
1

Use WKWebView's webView(_:decidePolicyFor:decisionHandler:).

import UIKit
import WebKit

class ViewController: UIViewController, WKNavigationDelegate {
    // MARK: - IBOutlet
    @IBOutlet weak var webView: WKWebView!
    
    
    // MARK: - Life cycle
    override func viewDidLoad() {
        super.viewDidLoad()
        webView.navigationDelegate = self
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        let urlStr = "https://www.google.com/"
        if let url = URL(string: urlStr) {
            let request = URLRequest(url: url)
            webView.load(request)
            //webView.allowsBackForwardNavigationGestures = false
            //webView.navigationDelegate = self
        }
    }
    
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        let request = navigationAction.request
        if let host = navigationAction.request.url?.host {
            if host == "www.google.com" {
                if let headers = request.allHTTPHeaderFields {
                    print("Google Headers: \(headers)")
                } else {
                    print("Nope, sir")
                }
            }
            else if host == "www.apple.com" {
                if let headers = request.allHTTPHeaderFields {
                    print("Apple Headers: \(headers)")
                } else {
                    print("Nope, sir")
                }
            }
        }
        decisionHandler(.allow)
    }
}

And I get the following.

["User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko)", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8"] Headers: ["Accept-Language": "en-us", "Upgrade-Insecure-Requests": "1", "Accept-Encoding": "gzip, deflate, br", "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko)", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8"]

El Tomato
  • 6,479
  • 6
  • 46
  • 75