Skip to content

Commit

Permalink
Merge pull request onevcat#1072 from devuarpd/Add-redirect-handler
Browse files Browse the repository at this point in the history
Add redirect handler.
  • Loading branch information
onevcat authored Dec 17, 2018
2 parents 3e1d881 + fe3c8e3 commit aaa7876
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 0 deletions.
10 changes: 10 additions & 0 deletions Kingfisher.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,10 @@
D1E56447219B16330057AAE3 /* 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 */; };
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 */; };
D9638BA71C7DCF560046523D /* ImagePrefetcherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9638BA41C7DC71F0046523D /* ImagePrefetcherTests.swift */; };
D9638BA81C7DCF570046523D /* ImagePrefetcherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9638BA41C7DC71F0046523D /* ImagePrefetcherTests.swift */; };
Expand Down Expand Up @@ -353,6 +357,7 @@
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; };
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>"; };
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>"; };
Expand Down Expand Up @@ -477,6 +482,7 @@
isa = PBXGroup;
children = (
D12AB69D215D2BB50013BA68 /* RequestModifier.swift */,
D8FCF6A721C5A0E500F9ABC0 /* RedirectHandler.swift */,
D12AB69F215D2BB50013BA68 /* ImageDownloader.swift */,
4BD821612189FC0C0084CC21 /* SessionDelegate.swift */,
4BD821662189FD330084CC21 /* SessionDataTask.swift */,
Expand Down Expand Up @@ -1068,6 +1074,7 @@
D1A37BE5215D359F009B39B7 /* ImageFormat.swift in Sources */,
D1A37BCE215D2DBA009B39B7 /* KingfisherOptionsInfo.swift in Sources */,
D1A37BCF215D2DBA009B39B7 /* Image.swift in Sources */,
D8B3692921C5CED6000F36F6 /* RedirectHandler.swift in Sources */,
D1A37BD0215D2DBA009B39B7 /* ImageTransition.swift in Sources */,
4B10480F216F157000300C61 /* ImageDataProcessor.swift in Sources */,
D1A37BD1215D2DBA009B39B7 /* ImageProcessor.swift in Sources */,
Expand Down Expand Up @@ -1183,6 +1190,7 @@
4BD821632189FC0C0084CC21 /* SessionDelegate.swift in Sources */,
D12AB6E1215D2BB50013BA68 /* Filter.swift in Sources */,
D12AB6C5215D2BB50013BA68 /* Resource.swift in Sources */,
D8B3692A21C5CED7000F36F6 /* RedirectHandler.swift in Sources */,
D1A37BDF215D34E8009B39B7 /* ImageDrawing.swift in Sources */,
4BD821682189FD330084CC21 /* SessionDataTask.swift in Sources */,
D12AB709215D2BB50013BA68 /* KingfisherError.swift in Sources */,
Expand All @@ -1203,6 +1211,7 @@
D1A37BF5215D3850009B39B7 /* SizeExtensions.swift in Sources */,
D12AB71B215D2BB50013BA68 /* CacheSerializer.swift in Sources */,
4B46CC6C21744AC500D90C4A /* DiskStorage.swift in Sources */,
D8B3692821C5CED6000F36F6 /* RedirectHandler.swift in Sources */,
D12AB6DB215D2BB50013BA68 /* ImageTransition.swift in Sources */,
4BD821652189FC0C0084CC21 /* SessionDelegate.swift in Sources */,
D1BA78202174D07800C69D7B /* CallbackQueue.swift in Sources */,
Expand Down Expand Up @@ -1278,6 +1287,7 @@
4BD821622189FC0C0084CC21 /* SessionDelegate.swift in Sources */,
D12AB6E0215D2BB50013BA68 /* Filter.swift in Sources */,
D12AB6C4215D2BB50013BA68 /* Resource.swift in Sources */,
D8FCF6A821C5A0E500F9ABC0 /* RedirectHandler.swift in Sources */,
D1A37BDE215D34E8009B39B7 /* ImageDrawing.swift in Sources */,
4BD821672189FD330084CC21 /* SessionDataTask.swift in Sources */,
D12AB708215D2BB50013BA68 /* KingfisherError.swift in Sources */,
Expand Down
9 changes: 9 additions & 0 deletions Sources/General/KingfisherOptionsInfo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,13 @@ public enum KingfisherOptionsInfoItem {
/// The original request will be sent without any modification by default.
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
/// 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.
Expand Down Expand Up @@ -231,6 +238,7 @@ public struct KingfisherParsedOptionsInfo {
public var callbackQueue: CallbackQueue = .mainCurrentOrAsync
public var scaleFactor: CGFloat = 1.0
public var requestModifier: ImageDownloadRequestModifier = NoModifier.default
public var redirectHandler: ImageDownloadRedirectHandler = NoHandler.default
public var processor: ImageProcessor = DefaultImageProcessor.default
public var imageModifier: ImageModifier = DefaultImageModifier.default
public var cacheSerializer: CacheSerializer = DefaultCacheSerializer.default
Expand Down Expand Up @@ -264,6 +272,7 @@ public struct KingfisherParsedOptionsInfo {
case .callbackQueue(let value): callbackQueue = value
case .scaleFactor(let value): scaleFactor = value
case .requestModifier(let value): requestModifier = value
case .redirectHandler(let value): redirectHandler = value
case .processor(let value): processor = value
case .imageModifier(let value): imageModifier = value
case .cacheSerializer(let value): cacheSerializer = value
Expand Down
76 changes: 76 additions & 0 deletions Sources/Networking/RedirectHandler.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//
// RedirectHandler.swift
// Kingfisher
//
// Created by Roman Maidanovych on 2018/12/10.
//
// Copyright (c) 2018 Wei Wang <[email protected]>
//
// 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 changes: 12 additions & 0 deletions Sources/Networking/SessionDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,18 @@ extension SessionDelegate: URLSessionDataDelegate {
{
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>) {
guard let sessionTask = self.task(for: task) else {
Expand Down
9 changes: 9 additions & 0 deletions Tests/KingfisherTests/KingfisherOptionsInfoTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class KingfisherOptionsInfoTests: XCTestCase {

let queue = DispatchQueue.global(qos: .default)
let testModifier = TestModifier()
let testRedirectHandler = TestRedirectHandler()
let processor = RoundCornerImageProcessor(cornerRadius: 20)
let serializer = FormatIndicatedCacheSerializer.png
let modifier = DefaultImageModifier.default
Expand All @@ -81,6 +82,7 @@ class KingfisherOptionsInfoTests: XCTestCase {
KingfisherOptionsInfoItem.scaleFactor(2.0),
.preloadAllAnimationData,
.requestModifier(testModifier),
.redirectHandler(testRedirectHandler),
.processor(processor),
.cacheSerializer(serializer),
.imageModifier(modifier),
Expand Down Expand Up @@ -115,6 +117,7 @@ class KingfisherOptionsInfoTests: XCTestCase {
XCTAssertEqual(options.scaleFactor, 2.0)
XCTAssertTrue(options.preloadAllAnimationData)
XCTAssertTrue(options.requestModifier is TestModifier)
XCTAssertTrue(options.redirectHandler is TestRedirectHandler)
XCTAssertEqual(options.processor.identifier, processor.identifier)
XCTAssertTrue(options.cacheSerializer is FormatIndicatedCacheSerializer)
XCTAssertTrue(options.imageModifier is DefaultImageModifier)
Expand All @@ -137,3 +140,9 @@ class TestModifier: ImageDownloadRequestModifier {
return nil
}
}

class TestRedirectHandler: ImageDownloadRedirectHandler {
func handleHTTPRedirection(for task: SessionDataTask, response: HTTPURLResponse, newRequest: URLRequest, completionHandler: @escaping (URLRequest?) -> Void) {
completionHandler(newRequest)
}
}

0 comments on commit aaa7876

Please sign in to comment.