Procházet zdrojové kódy

Merge pull request #1072 from devuarpd/Add-redirect-handler

Add redirect handler.
Wei Wang před 7 roky
rodič
revize
aaa7876a11

+ 10 - 0
Kingfisher.xcodeproj/project.pbxproj

@@ -233,6 +233,10 @@
 		D1E56447219B16330057AAE3 /* ImageDataProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1E56444219B16330057AAE3 /* ImageDataProvider.swift */; };
 		D1E56447219B16330057AAE3 /* ImageDataProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1E56444219B16330057AAE3 /* ImageDataProvider.swift */; };
 		D1E56448219B16330057AAE3 /* ImageDataProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1E56444219B16330057AAE3 /* ImageDataProvider.swift */; };
 		D1E56448219B16330057AAE3 /* ImageDataProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1E56444219B16330057AAE3 /* ImageDataProvider.swift */; };
 		D1ED2D401AD2D09F00CFC3EB /* Kingfisher.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D1ED2D351AD2D09F00CFC3EB /* Kingfisher.framework */; };
 		D1ED2D401AD2D09F00CFC3EB /* Kingfisher.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D1ED2D351AD2D09F00CFC3EB /* Kingfisher.framework */; };
+		D8B3692821C5CED6000F36F6 /* RedirectHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8FCF6A721C5A0E500F9ABC0 /* RedirectHandler.swift */; };
+		D8B3692921C5CED6000F36F6 /* RedirectHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8FCF6A721C5A0E500F9ABC0 /* RedirectHandler.swift */; };
+		D8B3692A21C5CED7000F36F6 /* RedirectHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8FCF6A721C5A0E500F9ABC0 /* RedirectHandler.swift */; };
+		D8FCF6A821C5A0E500F9ABC0 /* RedirectHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8FCF6A721C5A0E500F9ABC0 /* RedirectHandler.swift */; };
 		D9638BA61C7DC71F0046523D /* ImagePrefetcherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9638BA41C7DC71F0046523D /* ImagePrefetcherTests.swift */; };
 		D9638BA61C7DC71F0046523D /* ImagePrefetcherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9638BA41C7DC71F0046523D /* ImagePrefetcherTests.swift */; };
 		D9638BA71C7DCF560046523D /* ImagePrefetcherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9638BA41C7DC71F0046523D /* ImagePrefetcherTests.swift */; };
 		D9638BA71C7DCF560046523D /* ImagePrefetcherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9638BA41C7DC71F0046523D /* ImagePrefetcherTests.swift */; };
 		D9638BA81C7DCF570046523D /* ImagePrefetcherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9638BA41C7DC71F0046523D /* ImagePrefetcherTests.swift */; };
 		D9638BA81C7DCF570046523D /* ImagePrefetcherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9638BA41C7DC71F0046523D /* ImagePrefetcherTests.swift */; };
@@ -353,6 +357,7 @@
 		D1ED2D351AD2D09F00CFC3EB /* Kingfisher.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Kingfisher.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		D1ED2D351AD2D09F00CFC3EB /* Kingfisher.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Kingfisher.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		D1ED2D3F1AD2D09F00CFC3EB /* KingfisherTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = KingfisherTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
 		D1ED2D3F1AD2D09F00CFC3EB /* KingfisherTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = KingfisherTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
 		D7B91E45CD834BE64717E77F /* Pods-KingfisherTests-tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-KingfisherTests-tvOS.debug.xcconfig"; path = "Pods/Target Support Files/Pods-KingfisherTests-tvOS/Pods-KingfisherTests-tvOS.debug.xcconfig"; sourceTree = "<group>"; };
 		D7B91E45CD834BE64717E77F /* Pods-KingfisherTests-tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-KingfisherTests-tvOS.debug.xcconfig"; path = "Pods/Target Support Files/Pods-KingfisherTests-tvOS/Pods-KingfisherTests-tvOS.debug.xcconfig"; sourceTree = "<group>"; };
+		D8FCF6A721C5A0E500F9ABC0 /* RedirectHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RedirectHandler.swift; sourceTree = "<group>"; };
 		D9638BA41C7DC71F0046523D /* ImagePrefetcherTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImagePrefetcherTests.swift; sourceTree = "<group>"; };
 		D9638BA41C7DC71F0046523D /* ImagePrefetcherTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImagePrefetcherTests.swift; sourceTree = "<group>"; };
 		DE80CB18FBC9F9F23DC1FDCF /* Pods-KingfisherTests-macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-KingfisherTests-macOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-KingfisherTests-macOS/Pods-KingfisherTests-macOS.release.xcconfig"; sourceTree = "<group>"; };
 		DE80CB18FBC9F9F23DC1FDCF /* Pods-KingfisherTests-macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-KingfisherTests-macOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-KingfisherTests-macOS/Pods-KingfisherTests-macOS.release.xcconfig"; sourceTree = "<group>"; };
 		F72CE9CD1FCF17ED00CC522A /* ImageModifierTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageModifierTests.swift; sourceTree = "<group>"; };
 		F72CE9CD1FCF17ED00CC522A /* ImageModifierTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageModifierTests.swift; sourceTree = "<group>"; };
@@ -477,6 +482,7 @@
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
 				D12AB69D215D2BB50013BA68 /* RequestModifier.swift */,
 				D12AB69D215D2BB50013BA68 /* RequestModifier.swift */,
+				D8FCF6A721C5A0E500F9ABC0 /* RedirectHandler.swift */,
 				D12AB69F215D2BB50013BA68 /* ImageDownloader.swift */,
 				D12AB69F215D2BB50013BA68 /* ImageDownloader.swift */,
 				4BD821612189FC0C0084CC21 /* SessionDelegate.swift */,
 				4BD821612189FC0C0084CC21 /* SessionDelegate.swift */,
 				4BD821662189FD330084CC21 /* SessionDataTask.swift */,
 				4BD821662189FD330084CC21 /* SessionDataTask.swift */,
@@ -1068,6 +1074,7 @@
 				D1A37BE5215D359F009B39B7 /* ImageFormat.swift in Sources */,
 				D1A37BE5215D359F009B39B7 /* ImageFormat.swift in Sources */,
 				D1A37BCE215D2DBA009B39B7 /* KingfisherOptionsInfo.swift in Sources */,
 				D1A37BCE215D2DBA009B39B7 /* KingfisherOptionsInfo.swift in Sources */,
 				D1A37BCF215D2DBA009B39B7 /* Image.swift in Sources */,
 				D1A37BCF215D2DBA009B39B7 /* Image.swift in Sources */,
+				D8B3692921C5CED6000F36F6 /* RedirectHandler.swift in Sources */,
 				D1A37BD0215D2DBA009B39B7 /* ImageTransition.swift in Sources */,
 				D1A37BD0215D2DBA009B39B7 /* ImageTransition.swift in Sources */,
 				4B10480F216F157000300C61 /* ImageDataProcessor.swift in Sources */,
 				4B10480F216F157000300C61 /* ImageDataProcessor.swift in Sources */,
 				D1A37BD1215D2DBA009B39B7 /* ImageProcessor.swift in Sources */,
 				D1A37BD1215D2DBA009B39B7 /* ImageProcessor.swift in Sources */,
@@ -1183,6 +1190,7 @@
 				4BD821632189FC0C0084CC21 /* SessionDelegate.swift in Sources */,
 				4BD821632189FC0C0084CC21 /* SessionDelegate.swift in Sources */,
 				D12AB6E1215D2BB50013BA68 /* Filter.swift in Sources */,
 				D12AB6E1215D2BB50013BA68 /* Filter.swift in Sources */,
 				D12AB6C5215D2BB50013BA68 /* Resource.swift in Sources */,
 				D12AB6C5215D2BB50013BA68 /* Resource.swift in Sources */,
+				D8B3692A21C5CED7000F36F6 /* RedirectHandler.swift in Sources */,
 				D1A37BDF215D34E8009B39B7 /* ImageDrawing.swift in Sources */,
 				D1A37BDF215D34E8009B39B7 /* ImageDrawing.swift in Sources */,
 				4BD821682189FD330084CC21 /* SessionDataTask.swift in Sources */,
 				4BD821682189FD330084CC21 /* SessionDataTask.swift in Sources */,
 				D12AB709215D2BB50013BA68 /* KingfisherError.swift in Sources */,
 				D12AB709215D2BB50013BA68 /* KingfisherError.swift in Sources */,
@@ -1203,6 +1211,7 @@
 				D1A37BF5215D3850009B39B7 /* SizeExtensions.swift in Sources */,
 				D1A37BF5215D3850009B39B7 /* SizeExtensions.swift in Sources */,
 				D12AB71B215D2BB50013BA68 /* CacheSerializer.swift in Sources */,
 				D12AB71B215D2BB50013BA68 /* CacheSerializer.swift in Sources */,
 				4B46CC6C21744AC500D90C4A /* DiskStorage.swift in Sources */,
 				4B46CC6C21744AC500D90C4A /* DiskStorage.swift in Sources */,
+				D8B3692821C5CED6000F36F6 /* RedirectHandler.swift in Sources */,
 				D12AB6DB215D2BB50013BA68 /* ImageTransition.swift in Sources */,
 				D12AB6DB215D2BB50013BA68 /* ImageTransition.swift in Sources */,
 				4BD821652189FC0C0084CC21 /* SessionDelegate.swift in Sources */,
 				4BD821652189FC0C0084CC21 /* SessionDelegate.swift in Sources */,
 				D1BA78202174D07800C69D7B /* CallbackQueue.swift in Sources */,
 				D1BA78202174D07800C69D7B /* CallbackQueue.swift in Sources */,
@@ -1278,6 +1287,7 @@
 				4BD821622189FC0C0084CC21 /* SessionDelegate.swift in Sources */,
 				4BD821622189FC0C0084CC21 /* SessionDelegate.swift in Sources */,
 				D12AB6E0215D2BB50013BA68 /* Filter.swift in Sources */,
 				D12AB6E0215D2BB50013BA68 /* Filter.swift in Sources */,
 				D12AB6C4215D2BB50013BA68 /* Resource.swift in Sources */,
 				D12AB6C4215D2BB50013BA68 /* Resource.swift in Sources */,
+				D8FCF6A821C5A0E500F9ABC0 /* RedirectHandler.swift in Sources */,
 				D1A37BDE215D34E8009B39B7 /* ImageDrawing.swift in Sources */,
 				D1A37BDE215D34E8009B39B7 /* ImageDrawing.swift in Sources */,
 				4BD821672189FD330084CC21 /* SessionDataTask.swift in Sources */,
 				4BD821672189FD330084CC21 /* SessionDataTask.swift in Sources */,
 				D12AB708215D2BB50013BA68 /* KingfisherError.swift in Sources */,
 				D12AB708215D2BB50013BA68 /* KingfisherError.swift in Sources */,

+ 9 - 0
Sources/General/KingfisherOptionsInfo.swift

@@ -133,6 +133,13 @@ public enum KingfisherOptionsInfoItem {
     /// The original request will be sent without any modification by default.
     /// The original request will be sent without any modification by default.
     case requestModifier(ImageDownloadRequestModifier)
     case requestModifier(ImageDownloadRequestModifier)
     
     
+    /// The `ImageDownloadRedirectHandler` contained will be used to change the request before redirection.
+    /// This is the posibility you can modify the image download request during redirect. You can modify the request for
+    /// some customizing purpose, such as adding auth token to the header, do basic HTTP auth or something like url
+    /// mapping.
+    /// The original redirection request will be sent without any modification by default.
+    case redirectHandler(ImageDownloadRedirectHandler)
+    
     /// Processor for processing when the downloading finishes, a processor will convert the downloaded data to an image
     /// Processor for processing when the downloading finishes, a processor will convert the downloaded data to an image
     /// and/or apply some filter on it. If a cache is connected to the downloader (it happens when you are using
     /// and/or apply some filter on it. If a cache is connected to the downloader (it happens when you are using
     /// KingfisherManager or any of the view extension methods), the converted image will also be sent to cache as well.
     /// KingfisherManager or any of the view extension methods), the converted image will also be sent to cache as well.
@@ -231,6 +238,7 @@ public struct KingfisherParsedOptionsInfo {
     public var callbackQueue: CallbackQueue = .mainCurrentOrAsync
     public var callbackQueue: CallbackQueue = .mainCurrentOrAsync
     public var scaleFactor: CGFloat = 1.0
     public var scaleFactor: CGFloat = 1.0
     public var requestModifier: ImageDownloadRequestModifier = NoModifier.default
     public var requestModifier: ImageDownloadRequestModifier = NoModifier.default
+    public var redirectHandler: ImageDownloadRedirectHandler = NoHandler.default
     public var processor: ImageProcessor = DefaultImageProcessor.default
     public var processor: ImageProcessor = DefaultImageProcessor.default
     public var imageModifier: ImageModifier = DefaultImageModifier.default
     public var imageModifier: ImageModifier = DefaultImageModifier.default
     public var cacheSerializer: CacheSerializer = DefaultCacheSerializer.default
     public var cacheSerializer: CacheSerializer = DefaultCacheSerializer.default
@@ -264,6 +272,7 @@ public struct KingfisherParsedOptionsInfo {
             case .callbackQueue(let value): callbackQueue = value
             case .callbackQueue(let value): callbackQueue = value
             case .scaleFactor(let value): scaleFactor = value
             case .scaleFactor(let value): scaleFactor = value
             case .requestModifier(let value): requestModifier = value
             case .requestModifier(let value): requestModifier = value
+            case .redirectHandler(let value): redirectHandler = value
             case .processor(let value): processor = value
             case .processor(let value): processor = value
             case .imageModifier(let value): imageModifier = value
             case .imageModifier(let value): imageModifier = value
             case .cacheSerializer(let value): cacheSerializer = value
             case .cacheSerializer(let value): cacheSerializer = value

+ 76 - 0
Sources/Networking/RedirectHandler.swift

@@ -0,0 +1,76 @@
+//
+//  RedirectHandler.swift
+//  Kingfisher
+//
+//  Created by Roman Maidanovych on 2018/12/10.
+//
+//  Copyright (c) 2018 Wei Wang <onevcat@gmail.com>
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+import Foundation
+
+/// Represents and wraps a method for modifying request during an image download request redirection.
+public protocol ImageDownloadRedirectHandler {
+    
+    /// The `ImageDownloadRedirectHandler` contained will be used to change the request before redirection.
+    /// This is the posibility you can modify the image download request during redirection. You can modify the request for
+    /// some customizing purpose, such as adding auth token to the header, do basic HTTP auth or something like url
+    /// mapping.
+    ///
+    /// Usually, you pass an `ImageDownloadRedirectHandler` as the associated value of
+    /// `KingfisherOptionsInfoItem.redirectHandler` and use it as the `options` parameter in related methods.
+    ///
+    /// If you do nothing with the input `request` and return it as is, a downloading process will redirect with it.
+    ///
+    /// - Parameter task: current SessionDataTask.
+    ///             response: response received during redirection.
+    ///             newRequest: request for redirection which can be modified.
+    ///             completionHandler: closure for modifying request
+    ///
+    func handleHTTPRedirection(for task: SessionDataTask, response: HTTPURLResponse, newRequest: URLRequest, completionHandler: @escaping (URLRequest?) -> Void)
+}
+
+struct NoHandler: ImageDownloadRedirectHandler {
+    static let `default` = NoHandler()
+    private init() {}
+    
+    func handleHTTPRedirection(for task: SessionDataTask, response: HTTPURLResponse, newRequest: URLRequest, completionHandler: @escaping (URLRequest?) -> Void) {
+        completionHandler(newRequest)
+    }
+}
+
+/// A wrapper for creating an `ImageDownloadRedirectHandler` easier.
+/// This type conforms to `ImageDownloadRedirectHandler` and wraps an image modify block.
+public struct AnyHandler: ImageDownloadRedirectHandler {
+    
+    let block: (SessionDataTask, HTTPURLResponse, URLRequest, (URLRequest?) -> Void) -> Void
+
+    public func handleHTTPRedirection(for task: SessionDataTask, response: HTTPURLResponse, newRequest: URLRequest, completionHandler: @escaping (URLRequest?) -> Void) {
+        block(task, response, newRequest, completionHandler)
+    }
+    
+    /// Creates a value of `ImageDownloadRedirectHandler` which runs `modify` block.
+    ///
+    /// - Parameter modify: The request modifying block runs when a request modifying task comes.
+    ///
+    public init(handle: @escaping (SessionDataTask, HTTPURLResponse, URLRequest, (URLRequest?) -> Void) -> Void) {
+        block = handle
+    }
+}

+ 12 - 0
Sources/Networking/SessionDelegate.swift

@@ -220,6 +220,18 @@ extension SessionDelegate: URLSessionDataDelegate {
     {
     {
         onReceiveSessionTaskChallenge.call((session, task, challenge, completionHandler))
         onReceiveSessionTaskChallenge.call((session, task, challenge, completionHandler))
     }
     }
+    
+    func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: @escaping (URLRequest?) -> Void)
+    {
+        guard let url = response.url,
+            let sessionDataTask = self.task(for: url),
+            let options = Array(sessionDataTask.callbacks).last?.options else {
+                completionHandler(request)
+                return
+        }
+        
+        options.redirectHandler.handleHTTPRedirection(for: sessionDataTask, response: response, newRequest: request, completionHandler: completionHandler)
+    }
 
 
     private func onCompleted(task: URLSessionTask, result: Result<(Data, URLResponse?), KingfisherError>) {
     private func onCompleted(task: URLSessionTask, result: Result<(Data, URLResponse?), KingfisherError>) {
         guard let sessionTask = self.task(for: task) else {
         guard let sessionTask = self.task(for: task) else {

+ 9 - 0
Tests/KingfisherTests/KingfisherOptionsInfoTests.swift

@@ -60,6 +60,7 @@ class KingfisherOptionsInfoTests: XCTestCase {
         
         
         let queue = DispatchQueue.global(qos: .default)
         let queue = DispatchQueue.global(qos: .default)
         let testModifier = TestModifier()
         let testModifier = TestModifier()
+        let testRedirectHandler = TestRedirectHandler()
         let processor = RoundCornerImageProcessor(cornerRadius: 20)
         let processor = RoundCornerImageProcessor(cornerRadius: 20)
         let serializer = FormatIndicatedCacheSerializer.png
         let serializer = FormatIndicatedCacheSerializer.png
         let modifier = DefaultImageModifier.default
         let modifier = DefaultImageModifier.default
@@ -81,6 +82,7 @@ class KingfisherOptionsInfoTests: XCTestCase {
             KingfisherOptionsInfoItem.scaleFactor(2.0),
             KingfisherOptionsInfoItem.scaleFactor(2.0),
             .preloadAllAnimationData,
             .preloadAllAnimationData,
             .requestModifier(testModifier),
             .requestModifier(testModifier),
+            .redirectHandler(testRedirectHandler),
             .processor(processor),
             .processor(processor),
             .cacheSerializer(serializer),
             .cacheSerializer(serializer),
             .imageModifier(modifier),
             .imageModifier(modifier),
@@ -115,6 +117,7 @@ class KingfisherOptionsInfoTests: XCTestCase {
         XCTAssertEqual(options.scaleFactor, 2.0)
         XCTAssertEqual(options.scaleFactor, 2.0)
         XCTAssertTrue(options.preloadAllAnimationData)
         XCTAssertTrue(options.preloadAllAnimationData)
         XCTAssertTrue(options.requestModifier is TestModifier)
         XCTAssertTrue(options.requestModifier is TestModifier)
+        XCTAssertTrue(options.redirectHandler is TestRedirectHandler)
         XCTAssertEqual(options.processor.identifier, processor.identifier)
         XCTAssertEqual(options.processor.identifier, processor.identifier)
         XCTAssertTrue(options.cacheSerializer is FormatIndicatedCacheSerializer)
         XCTAssertTrue(options.cacheSerializer is FormatIndicatedCacheSerializer)
         XCTAssertTrue(options.imageModifier is DefaultImageModifier)
         XCTAssertTrue(options.imageModifier is DefaultImageModifier)
@@ -137,3 +140,9 @@ class TestModifier: ImageDownloadRequestModifier {
         return nil
         return nil
     }
     }
 }
 }
+
+class TestRedirectHandler: ImageDownloadRedirectHandler {
+    func handleHTTPRedirection(for task: SessionDataTask, response: HTTPURLResponse, newRequest: URLRequest, completionHandler: @escaping (URLRequest?) -> Void) {
+        completionHandler(newRequest)
+    }
+}