123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- import Foundation
- import WebKit
- class WKCookieWebView : WKWebView {
- private let useRedirectCookieHandling: Bool
- init(frame: CGRect, configuration: WKWebViewConfiguration, useRedirectCookieHandling: Bool = false) {
- self.useRedirectCookieHandling = useRedirectCookieHandling
- super.init(frame: frame, configuration: configuration)
- }
-
- required init?(coder: NSCoder) {
- self.useRedirectCookieHandling = false
- super.init(coder: coder)
- }
- override func load(_ request: URLRequest) -> WKNavigation? {
-
- var request = request
- let language = NSLocale.preferredLanguages[0] as String
-
- request.setValue(CCUtility.getUserAgent(), forHTTPHeaderField: "User-Agent")
- request.addValue("true", forHTTPHeaderField: "OCS-APIRequest")
- request.addValue(language, forHTTPHeaderField: "Accept-Language")
- guard useRedirectCookieHandling else {
- return super.load(request)
- }
- requestWithCookieHandling(request, success: { (newRequest , response, data) in
- DispatchQueue.main.async {
- self.syncCookiesInJS()
- if let data = data, let response = response {
- let _ = self.webViewLoad(data: data, response: response)
- } else {
- self.syncCookies(newRequest, nil, { (cookieRequest) in
- let _ = super.load(cookieRequest)
- })
- }
- }
- }, failure: {
-
- DispatchQueue.main.async {
- self.syncCookies(request, nil, { (newRequest) in
- let _ = super.load(newRequest)
- })
- }
- })
- return nil
- }
- private func requestWithCookieHandling(_ request: URLRequest, success: @escaping (URLRequest, HTTPURLResponse?, Data?) -> Void, failure: @escaping () -> Void) {
- let sessionConfig = URLSessionConfiguration.default
- let session = URLSession(configuration: sessionConfig, delegate: self, delegateQueue: nil)
- let task = session.dataTask(with: request) { (data, response, error) in
- if let _ = error {
- failure()
- } else {
- if let response = response as? HTTPURLResponse {
- let code = response.statusCode
- if code == 200 {
-
- success(request, response, data)
- } else if code >= 300 && code < 400 {
-
- guard let location = response.allHeaderFields["Location"] as? String, let redirectURL = URL(string: location) else {
- failure()
- return
- }
- let request = URLRequest(url: redirectURL, cachePolicy: .reloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 5)
- success(request, nil, nil)
- } else {
- success(request, response, data)
- }
- }
- }
- }
- task.resume()
- }
- private func webViewLoad(data: Data, response: URLResponse) -> WKNavigation! {
- guard let url = response.url else {
- return nil
- }
- let encode = response.textEncodingName ?? "utf8"
- let mine = response.mimeType ?? "text/html"
- return self.load(data, mimeType: mine, characterEncodingName: encode, baseURL: url)
- }
- }
- extension WKCookieWebView {
-
- private func syncCookies(_ request: URLRequest, _ task: URLSessionTask? = nil, _ completion: @escaping (URLRequest) -> Void) {
- var request = request
- var cookiesArray = [HTTPCookie]()
- if let task = task {
- HTTPCookieStorage.shared.getCookiesFor(task, completionHandler: { (cookies) in
- if let cookies = cookies {
- cookiesArray.append(contentsOf: cookies)
- let cookieDict = HTTPCookie.requestHeaderFields(with: cookiesArray)
- if let cookieStr = cookieDict["Cookie"] {
- request.addValue(cookieStr, forHTTPHeaderField: "Cookie")
- }
- }
- completion(request)
- })
- } else if let url = request.url {
- if let cookies = HTTPCookieStorage.shared.cookies(for: url) {
- cookiesArray.append(contentsOf: cookies)
- }
- let cookieDict = HTTPCookie.requestHeaderFields(with: cookiesArray)
- if let cookieStr = cookieDict["Cookie"] {
- request.addValue(cookieStr, forHTTPHeaderField: "Cookie")
- }
- completion(request)
- }
- }
-
- private func syncCookiesInJS(for request: URLRequest? = nil) {
- if let url = request?.url,
- let cookies = HTTPCookieStorage.shared.cookies(for: url) {
- let script = jsCookiesString(for: cookies)
- let cookieScript = WKUserScript(source: script, injectionTime: .atDocumentStart, forMainFrameOnly: false)
- self.configuration.userContentController.addUserScript(cookieScript)
- } else if let cookies = HTTPCookieStorage.shared.cookies {
- let script = jsCookiesString(for: cookies)
- let cookieScript = WKUserScript(source: script, injectionTime: .atDocumentStart, forMainFrameOnly: false)
- self.configuration.userContentController.addUserScript(cookieScript)
- }
- }
- private func jsCookiesString(for cookies: [HTTPCookie]) -> String {
- var result = ""
- let dateFormatter = DateFormatter()
- dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
- dateFormatter.dateFormat = "EEE, d MMM yyyy HH:mm:ss zzz"
- for cookie in cookies {
- result += "document.cookie='\(cookie.name)=\(cookie.value); domain=\(cookie.domain); path=\(cookie.path); "
- if let date = cookie.expiresDate {
- result += "expires=\(dateFormatter.string(from: date)); "
- }
- if (cookie.isSecure) {
- result += "secure; "
- }
- result += "'; "
- }
- return result
- }
- }
- extension WKCookieWebView : URLSessionTaskDelegate {
- func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: @escaping (URLRequest?) -> Void) {
- syncCookies(request) { (newRequest) in
- completionHandler(newRequest)
- }
- }
- }
|