web-dev-qa-db-ja.com

swiftでiOSのグローバルにリクエストにHTTPヘッダーを追加する方法

_func webView(webView: WKWebView!, decidePolicyForNavigationAction navigationAction: WKNavigationAction!, decisionHandler: ((WKNavigationActionPolicy) -> Void)!) {
     var request = NSMutableURLRequest(URL: navigationAction.request.URL)
     request.setValue("value", forHTTPHeaderField: "key")
     decisionHandler(.Allow)
}
_

上記のコードで、リクエストにヘッダーを追加します。 navigationAction.request.setValue("IOS", forKey: "DEVICE_APP")を実行しようとしましたが、機能しません。

どうぞ私を助けてください。

19
sandip

残念なことに、残念ながらWKWebViewを使用してこれを行うことはできません。

webView:decidePolicyForNavigationAction:decisionHandler: なぜなら navigationAction.requestは読み取り専用であり、変更できない変更不可能なNSURLRequestインスタンスです。

私が正しく理解している場合、WKWebViewは別のコンテンツおよびネットワークプロセスでサンドボックス化されて実行されます。少なくともiOSでは、ネットワークリクエストを傍受または変更する方法はありません。

UIWebViewに戻ると、これを行うことができます。

20
Stefan Arentz

これにはさまざまな方法がありますが、最も簡単な解決策は、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)
    }
}

次に、CustomWebViewクラスをWKWebViewであるかのように使用します。

EDIT NOTE:これは、@ Stefan Arentzによって指摘された最初のリクエストでのみ機能します。

[〜#〜]注[〜#〜]:一部のフィールドは上書きできず、変更されません。完全なテストは行っていませんが、User-Agentフィールドは、特定のハックを行わない限りオーバーライドできません( その回答についてはここをチェックしてください

8
Gabriel Cartier

Jonnyが示唆したように、Au Risの回答をNavigationActionではなくNavigationResponseを使用するように変更しました。また、これにより、同じ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!)
    }

}

4
Roben

いくつかの制限がありますが、それは可能です。デリゲート関数_webView:decidePolicyFornavigationResponse:decisionHandler:_で応答をインターセプトします。URLが変更された場合は、decisionHandler(.cancel)を渡してキャンセルし、カスタムヘッダーとインターセプトされたURLを設定するnew URLRequestでWebビューをリロードします。このようにして、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)
        }
    }
}
_
3
Au Ris
private var urlrequestCurrent: URLRequest?

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
    //print("WEB decidePolicyFor navigationAction: \(navigationAction)")
    if let currentrequest = self.urlrequestCurrent {
        //print("currentrequest: \(currentrequest), navigationAction.request: \(navigationAction.request)")
        if currentrequest == navigationAction.request {
            self.urlrequestCurrent = nil
            decisionHandler(.allow)
            return
        }
    }

    decisionHandler(.cancel)

    var customRequest = navigationAction.request
    customRequest.setValue("myvaluefffs", forHTTPHeaderField: "mykey")
    self.urlrequestCurrent = customRequest
    webView.load(customRequest)
}
0
Jonny