iOS - not able to add http header of URLRequest - ios

I am trying to add http header to URLRequest, which I am loading in WKWebView.
I tried this code:
var urlRequest = URLRequest(url: URL(string: "url")!)
urlRequest.addValue("value", forHTTPHeaderField: "key")
self.viewerWebKit.load(urlRequest)
and also this:
var urlRequest = URLRequest(url: URL(string: "url")!)
urlRequest.setValue("value", forHTTPHeaderField: "key")
self.viewerWebKit.load(urlRequest)
But when I am printing http headers with this code:
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: #escaping (WKNavigationResponsePolicy) -> Void) {
let headers = (navigationResponse.response as! HTTPURLResponse).allHeaderFields
for (key,value) in headers {
print("key \(key) value \(value)")
}
decisionHandler(.allow)
}
nothing is added or set. What am I doing wrong?

optional func webView(_ webView: WKWebView,
decidePolicyFor navigationAction: WKNavigationAction,
decisionHandler: #escaping (WKNavigationActionPolicy) -> Void)
Use this delegate function. You can find headers of request in navigationAction.request.

URLRequest immutable so if you want to add header in that request you need to make it mutable.use this extension to add header.
extension URLRequest {
internal mutating func addHeaders() {
let mutableRequest = ((self as NSURLRequest).mutableCopy() as? NSMutableURLRequest)!
mutableRequest.setValue("your header", forHTTPHeaderField: "key")
self = mutableRequest as URLRequest
}
}
}
Use where you want to set Header:
request.addHeaders()

Related

WKWebview Authentication using token is not working - Swift

I want to open authorised url in WKWebview my application. I have tried all possible solution from stackoverflow and google but none of them working for me.
if let url = myURL {
var request = URLRequest(url: url)
request.addValue("3d66fc991e82415398a8e92d8856da3e", forHTTPHeaderField: "Authorization")
webView.load(request)
}
I have also added this delegate.
public func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: #escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
let creds = URLCredential(user:"user1", password:"1234", persistence: URLCredential.Persistence.permanent)
completionHandler(URLSession.AuthChallengeDisposition.useCredential, creds)
}

URL is not opening in WKWebView in swift

I have a requirement to open the URL in WKWebView and login to the portal. As user logged in successfully after that I have to perform download operation from WKWebView, Everything is working fine but it's opening in external safari browser but as per requirement it should open in WKWebView
Outlet for WKWebView
#IBOutlet var webView: WKWebView!
Function to call URL in WKWebVIew
func loadURLInWebView() {
let url = URL(string: "https://www-qa.yyy.com/content/dash/en/public/login.html")
let urlRequest = URLRequest(url: url!)
if let webView = webView {
webView.load(urlRequest)
}
}
after adding decidePolicyFor delegate it's opening url in safari but it should open in WKWebView. I am not able to find the issue.
public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: #escaping (WKNavigationActionPolicy) -> Void) {
let url = navigationAction.request.url
guard url != nil else {
print(url!)
decisionHandler(.allow)
return
}
if url!.description.lowercased().starts(with: "http://") ||
url!.description.lowercased().starts(with: "https://") {
decisionHandler(.cancel)
UIApplication.shared.open(url!, options: [:], completionHandler: nil)
} else {
decisionHandler(.allow)
}
}
you are handling guard statement in the wrong way. In guard else, the condition will be called when the URL is nil.
If you do print(URL!) in else your app will crash. moreover when URL is nill, you should call cancel Handler.
public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: #escaping (WKNavigationActionPolicy) -> Void) {
guard let url = navigationAction.request.url else { // else will be called when url is nil
decisionHandler(.cancel)
return
}
if url.description.lowercased().starts(with: "http://") ||
url.description.lowercased().starts(with: "https://") {
decisionHandler(.allow)
} else {
decisionHandler(.cancel)
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
}

Stop navigation WKWebview

This is my situation:
I have a view controller within a WKWebView. This webview starts with a page "A". In this page there are some links (href) and I want that for some of these links must open in the external browser.
For this reason I set the WKWebView delegate:
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: #escaping (WKNavigationActionPolicy) -> Void) {
if let url = webView.url?.absoluteString
{
if(self.isExternalURL(url))
{
let urlT = URL(string: url)!
decisionHandler(.cancel)
UIApplication.shared.open(urlT, options: [:], completionHandler: nil)
}
else
{
decisionHandler(.allow)
}
}
else
{
decisionHandler(.allow)
}
}
private func isExternalURL(url:String) -> Bool
{
//......check link
}
My problem is that if I select an external link the external browser opens, but the webview does not remain on page A, but it also loads the external link while I would like it to remain on page A.
I dont know why
You should use navigationAction.request.url instead of webView.url
webView.url - Already loaded url
navigationAction.request.url - New url to load
Change
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: #escaping (WKNavigationActionPolicy) -> Void) {
if let url = navigationAction.request.url?.absoluteString
{
if self.isExternalURL(url)
{
decisionHandler(.cancel)
UIApplication.shared.open(navigationAction.request.url, options: [:], completionHandler: nil)
}
else
{
decisionHandler(.allow)
}
}
else
{
decisionHandler(.allow)
}
}
You can try to use webView(webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!)
func webView(webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
if let url = navigationAction.request.url?.absoluteString
{
if self.isExternalURL(url)
{
webView.stopLoading()
UIApplication.shared.open(navigationAction.request.url, options: [:], completionHandler: nil)
}
}
}

WKWeb View does finish loading of page in swift iOS?

I have created a WKWebView. It loads the url of MSB ie. My school bucks. It loads almost all url for payment. But at one url didFinishLoad is not getting called. I have added all the delegates for the web view.but certainly it is not working. The whole process works fine in the web browser of iPhone.
Below is the code I have added below code for that
let preferences = WKPreferences()
preferences.javaScriptEnabled = true
let configuration = WKWebViewConfiguration()
configuration.preferences = preferences
self.webView = WKWebView(frame: frame, configuration: configuration)
self.view.addSubview(webView)
self.webView.navigationDelegate = self
self.webView.uiDelegate = self
Delegates Methods for the navigation
// MARK: - WKWebView Delegation
extension PaymentWebViewController:WKNavigationDelegate {
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
DILog.print(items: "didFinish")
self.hideLoader()
if let strUrl = webView.url?.absoluteString {
self.readRedirectUrl(stringUrl: strUrl)
}
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
DILog.print(items: "faluere")
self.hideLoader()
}
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
DILog.print(items: "didStatrt")
self.showLoader()
if let strUrl = webView.url?.absoluteString {
DILog.print(items: "URL IS \(strUrl)")
}
}
func webView(_ webView: WKWebView,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: #escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
{
if(challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust)
{ DILog.print(items: "Auth Channlenge1")
let cred = URLCredential(trust: challenge.protectionSpace.serverTrust!)
completionHandler(.useCredential, cred)
}
else
{ DILog.print(items: "Auth Channlenge2")
completionHandler(.performDefaultHandling, nil)
}
}
func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {
DILog.print(items: "webViewWebContentProcessDidTerminate")
}
func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
DILog.print(items: "didCommit")
}
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: #escaping (WKNavigationActionPolicy) -> Void) {
DILog.print(items: "decidePolicyFor Action")
decisionHandler(WKNavigationActionPolicy.allow)
}
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: #escaping (WKNavigationResponsePolicy) -> Void) {
DILog.print(items: "decidePolicyFor response ")
decisionHandler(.allow)
}
}
You need to add exception (SecTrustSetExceptions) for that particular url. As there is some conflict with its signing identity and your WKWebView.
I was also facing same issue in my app and successfully solved by using below snippet.
try this:
extension PaymentWebViewController: WKNavigationDelegate {
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: #escaping (WKNavigationActionPolicy) -> Void) {
decisionHandler(.allow)
}
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: #escaping (WKNavigationResponsePolicy) -> Void) {
decisionHandler(.allow)
}
func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: #escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
let serverTrust = challenge.protectionSpace.serverTrust
let exceptions = SecTrustCopyExceptions(serverTrust!)
SecTrustSetExceptions(serverTrust!, exceptions)
completionHandler(.useCredential, URLCredential(trust: serverTrust!))
}
}
Hope you've already setup this in your info.plist:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoadsInWebContent</key>
<true/>
</dict>

How do you allow the WKWebView to accept redirect url

Having some trouble redirecting a user to a link from a WKWebView.
User is essentially meant to be authenticating on a website using WKWebView, the website checks the authentication which in turn redirects the user back to our app.
My initial thought is that there is some sort of restriction to allow the user to exit the app during the redirecting process. Which is why I implemented WKNavigationDelegate and saw that when we try authenticating the code below didReceive challenge runs through the second if case - which I only assume that its a good thing. Though the app does not get redirected.
Below is the code I have.
import UIKit
import WebKit
class WebViewViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {
var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.isHidden = false
tabBarController?.tabBar.isHidden = true
webView.navigationDelegate = self
if let url = URL(string: "SomeUrl") {
let request = URLRequest(url: url)
webView.load(request)
}
}
override func loadView() {
let webConfiguration = WKWebViewConfiguration()
webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.uiDelegate = self
view = webView
}
override func viewWillAppear(_ animated: Bool) {
self.navigationController?.navigationBar.isHidden = false
}
override func viewWillDisappear(_ animated: Bool) {
self.tabBarController?.tabBar.isHidden = false
}
func webViewDidFinishLoad(_ webView: UIWebView) {
if let URL = webView.request?.url {
OAuthHelper.oAuthManager.processOAuthStep1Response(url: URL)
}
}
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
}
func webView(_ webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!) {
}
func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: #escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
if challenge.previousFailureCount > 0 {
completionHandler(Foundation.URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge, nil)
} else if let serverTrust = challenge.protectionSpace.serverTrust {
completionHandler(Foundation.URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust: serverTrust))
} else {
print("unknown state. error: \(challenge.error)")
// do something w/ completionHandler here
}
}
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: #escaping (WKNavigationActionPolicy) -> Void) {
if (navigationAction.navigationType == .linkActivated){
decisionHandler(.cancel)
} else {
decisionHandler(.allow)
}
}
}
I did not fully understand the problem. If the question is that if you want the user to redirect from Webview to Native App, then you do have different options. I will be providing the options. Let me know if this is you are looking at.
Use WKURLSchemeHandler to handle the custom URLs. Read my article about this. https://medium.com/#kumarreddy_b/custom-scheme-handling-in-uiwebview-wkwebview-bbeb2f3f6cc1. https://github.com/BKRApps/KRWebView
you will be getting the urls in func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: #escaping (WKNavigationActionPolicy) -> Void), here you can intercept the URL and then use your URL scheme to get into the native app. Use OpenUrl to do this. But this is deprecated.

Resources