如何在swift中为iOS全局请求添加HTTP头

san*_*dip 16 http request-headers ios swift wkwebview

func webView(webView: WKWebView!, decidePolicyForNavigationAction navigationAction: WKNavigationAction!, decisionHandler: ((WKNavigationActionPolicy) -> Void)!) {
     var request = NSMutableURLRequest(URL: navigationAction.request.URL)
     request.setValue("value", forHTTPHeaderField: "key")
     decisionHandler(.Allow)
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,我想为请求添加一个标头.我试过,navigationAction.request.setValue("IOS", forKey: "DEVICE_APP")但它不起作用.

请以任何方式帮助我.

Ste*_*ntz 19

很遗憾AFAIK你不能这样做WKWebView.

它肯定不起作用,webView:decidePolicyForNavigationAction:decisionHandler:因为它navigationAction.request是只读的和不可变的NSURLRequest实例,你无法改变.

如果我理解正确,请WKWebView在单独的内容和网络流程中运行沙箱,至少在iOS上,无法拦截或更改其网络请求.

如果你退一步,你可以这样做UIWebView.

  • 为什么选择downvote?相信我,我已经调查了很多.这是不可能的. (3认同)

Gab*_*ier 8

有很多不同的方法,我发现最简单的解决方案是子类WKWebView并覆盖loadRequest方法.像这样的东西:

class CustomWebView: WKWebView {
    override func loadRequest(request: NSURLRequest) -> WKNavigation? {
        guard let mutableRequest = request.mutableCopy() as? NSMutableURLRequest else {
            return super.loadRequest(request)
        }
        mutableRequest.setValue("custom value", forHTTPHeaderField: "custom field")
        return super.loadRequest(mutableRequest)
    }
}
Run Code Online (Sandbox Code Playgroud)

然后简单地使用CustomWebView类,就像它是WKWebView一样.

编辑注意:这只适用于@Stefan Arentz指出的第一个请求.

注意:某些字段无法覆盖且不会更改.我没有做过彻底的测试,但我知道User-Agent除非你做一个特定的黑客攻击,否则不能覆盖该字段(请点击此处查看答案)

  • 这实际上并不能解决此处提出的问题。因为这仅适用于初始的“顶级”请求。自定义标头不是粘性的,不会用于子资源加载或例如XHR。 (2认同)

Au *_*Ris 5

有一些限制,但是您可以做到。截获委托函数中的响应webView:decidePolicyFornavigationResponse:decisionHandler:,如果url更改,则通过传递decisionHandler(.cancel)并用新的webview重新加载,以URLRequest设置自定义标头和截获的url来取消响应。这样,每次更改网址(例如,用户点击链接),您便会取消该请求并使用自定义标头创建一个新请求。

import UIKit
import WebKit
class ViewController: UIViewController, WKNavigationDelegate  {
    var webView: WKWebView?
    var loadUrl = URL(string: "https://www.google.com/")!

    override func viewDidLoad() {
        super.viewDidLoad()

        webView = WKWebView(frame: CGRect.zero)
        webView!.navigationDelegate = self
        view.addSubview(webView!)
        webView!.translatesAutoresizingMaskIntoConstraints = false
        webView!.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
        webView!.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true
        webView!.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true
        webView!.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0).isActive = true

        // Load first request with initial url
        loadWebPage(url: loadUrl)
    }

    func loadWebPage(url: URL)  {
        var customRequest = URLRequest(url: url)
        customRequest.setValue("some value", forHTTPHeaderField: "custom header key")
        webView!.load(customRequest)
    }

    // MARK: - WKNavigationDelegate

    func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
        guard let url = (navigationResponse.response as! HTTPURLResponse).url else {
            decisionHandler(.cancel)
            return
        }

        // If url changes, cancel current request which has no custom headers appended and load a new request with that url with custom headers
        if url != loadUrl {
            loadUrl = url
            decisionHandler(.cancel)
            loadWebPage(url: url)
        } else {
            decisionHandler(.allow)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Rob*_*ben 5

我已经修改了Au Ris答案,以NavigationAction代替NavigationResponsejonny建议使用。此外,这可以解决以下情况:随后将调用相同的URL,而您不必再跟踪当前的URL。这仅适用于GET请求,但如果需要,肯定可以适用于其他请求类型。

import UIKit
import WebKit
class ViewController: UIViewController, WKNavigationDelegate  {
    var webView: WKWebView?

    override func viewDidLoad() {
        super.viewDidLoad()
        webView = WKWebView(frame: CGRect.zero)
        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!)
    }
Run Code Online (Sandbox Code Playgroud)

}