-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #81 in MML/infobip-mobile-messaging-ios from akado…
…chnikov-MM-2283-DynamicBaseUrl to master Squashed commit of the following: commit 113025057d21c33f361e73d8ce35b0a26bc198e6 Author: Andrey K <[email protected]> Date: Mon Nov 27 17:12:44 2017 +0100 refinements for a test commit 24edc8cff55106ecc01c1c4ec769b13bf4dcdc58 Author: Andrey K <[email protected]> Date: Mon Nov 27 17:10:58 2017 +0100 additional comments commit 0f5f8f91eba096830325a188c32ca2a43dba8716 Author: Andrey K <[email protected]> Date: Mon Nov 27 17:05:22 2017 +0100 refinements commit 5d8cfe04a6774a357ec250503aed747a6bf1fd02 Author: Andrey K <[email protected]> Date: Mon Nov 27 16:56:35 2017 +0100 now we will retry if host not found for any request (now, by default, retry limit is 1 for all requests and only allowed for "cannot find host" error if other rules not specified) commit eb3675e2d6afb1a9df26747a5f2b2f3a734044ef Author: Andrey K <[email protected]> Date: Mon Nov 27 16:23:08 2017 +0100 tests for retries when baseurl changing commit b223ac6620366c477540e2f107899e9d2ea87387 Author: Andrey K <[email protected]> Date: Mon Nov 27 09:46:57 2017 +0100 code refinements commit 17d3beca47fb3a2438302e7432bcb7d3b56d6854 Author: Andrey K <[email protected]> Date: Fri Nov 24 18:24:12 2017 +0300 shared dynamic base url storage commit b2d9cba0e7ce88984eacfb4ddb31bbfb243a389d Author: Andrey K <[email protected]> Date: Fri Nov 24 13:17:54 2017 +0300 error handling commit c98d242330b28b3d51463b98939d8b9d3f2b4d1a Author: Andrey K <[email protected]> Date: Fri Nov 24 12:13:30 2017 +0300 tests commit 5fddd25fbd61dd3444cb84e4d73928583e47fdc1 Author: Andrey K <[email protected]> Date: Thu Nov 23 18:01:48 2017 +0300 extension supports dynamic base url commit 08590535bc80c0cd283a8623841aa40915cbc420 Author: Andrey K <[email protected]> Date: Thu Nov 23 15:14:53 2017 +0300 initial implementation
- Loading branch information
Andrey Kadochnikov
authored and
Andrey Kadochnikov
committed
Nov 29, 2017
1 parent
9ebf775
commit f6e59e0
Showing
33 changed files
with
417 additions
and
200 deletions.
There are no files selected for viewing
125 changes: 125 additions & 0 deletions
125
Classes/Core/HTTP/DynamicBaseUrlHTTPSessionManager.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
// | ||
// DynamicBaseUrlHTTPSessionManager.swift | ||
// MobileMessaging | ||
// | ||
// Created by Andrey Kadochnikov on 23/11/2017. | ||
// | ||
|
||
import Foundation | ||
|
||
struct DynamicBaseUrlConsts { | ||
static let newBaseUrlHeader = "newbaseurl" | ||
static let storedDynamicBaseUrlKey = "com.mobile-messaging.dynamic-base-url" | ||
} | ||
|
||
protocol DynamicBaseUrlStorage { | ||
func get() -> URL? | ||
|
||
func cleanUp() | ||
|
||
func set(_ url: URL) | ||
} | ||
|
||
extension UserDefaults: DynamicBaseUrlStorage { | ||
func get() -> URL? { | ||
return object(forKey: DynamicBaseUrlConsts.storedDynamicBaseUrlKey) as? URL | ||
} | ||
|
||
func cleanUp() { | ||
removeObject(forKey: DynamicBaseUrlConsts.storedDynamicBaseUrlKey) | ||
synchronize() | ||
} | ||
|
||
func set(_ url: URL) { | ||
set(url, forKey: DynamicBaseUrlConsts.storedDynamicBaseUrlKey) | ||
synchronize() | ||
} | ||
} | ||
|
||
class DynamicBaseUrlHTTPSessionManager { | ||
let applicationCode: String | ||
var dynamicBaseUrl: URL? | ||
let originalBaseUrl: URL? | ||
let configuration: URLSessionConfiguration? | ||
let appGroupId: String? | ||
var storage: DynamicBaseUrlStorage | ||
|
||
init(applicationCode: String, baseURL url: URL?, sessionConfiguration configuration: URLSessionConfiguration?, appGroupId: String?) { | ||
self.applicationCode = applicationCode | ||
self.configuration = configuration | ||
self.originalBaseUrl = url | ||
self.appGroupId = appGroupId | ||
if let appGroupId = appGroupId, let sharedUserDefaults = UserDefaults(suiteName: appGroupId) { | ||
self.storage = sharedUserDefaults | ||
} else { | ||
self.storage = UserDefaults.standard | ||
} | ||
self.dynamicBaseUrl = getStoredDynamicBaseUrl() ?? url | ||
} | ||
|
||
private func storeDynamicBaseUrl(_ url: URL?) { | ||
if let url = url { | ||
storage.set(url) | ||
} else { | ||
storage.cleanUp() | ||
} | ||
} | ||
|
||
private func getStoredDynamicBaseUrl() -> URL? { | ||
return storage.get() | ||
} | ||
|
||
func sendRequest<R: RequestData>(_ request: R, completion: @escaping (Result<R.ResponseType>) -> Void) { | ||
let sessionManager = makeSessionManager(for: request) | ||
|
||
let successBlock = { (task: URLSessionDataTask, obj: Any?) -> Void in | ||
self.handleDynamicBaseUrl(response: task.response, error: nil) | ||
if let obj = obj as? R.ResponseType { | ||
completion(Result.Success(obj)) | ||
} else { | ||
let error = NSError(domain: AFURLResponseSerializationErrorDomain, code: NSURLErrorCannotDecodeContentData, userInfo:[NSLocalizedFailureReasonErrorKey : "Request succeeded with no return value or return value wasn't a ResponseType value."]) | ||
completion(Result.Failure(error)) | ||
} | ||
} | ||
|
||
let failureBlock = { (task: URLSessionDataTask?, error: Error) -> Void in | ||
self.handleDynamicBaseUrl(response: task?.response, error: error as NSError?) | ||
completion(Result<R.ResponseType>.Failure(error as NSError?)) | ||
} | ||
|
||
performRequest(request, sessionManager: sessionManager, successBlock: successBlock, failureBlock: failureBlock) | ||
} | ||
|
||
func makeSessionManager<R: RequestData>(for request: R) -> MM_AFHTTPSessionManager { | ||
let sessionManager = MM_AFHTTPSessionManager(baseURL: dynamicBaseUrl, sessionConfiguration: configuration) | ||
sessionManager.responseSerializer = ResponseSerializer<R.ResponseType>() | ||
sessionManager.requestSerializer = RequestSerializer(applicationCode: applicationCode, jsonBody: request.body, headers: request.headers) | ||
return sessionManager | ||
} | ||
|
||
func performRequest<R: RequestData>(_ request: R, sessionManager: MM_AFHTTPSessionManager, successBlock: @escaping (URLSessionDataTask, Any?) -> Void, failureBlock: @escaping (URLSessionDataTask?, Error) -> Void) { | ||
|
||
MMLogDebug("Sending request \(type(of: self))\nparameters: \(String(describing: request.parameters))\nbody: \(String(describing: request.body))\nto \(dynamicBaseUrl?.absoluteString ?? "empty-host" + request.path.rawValue)") | ||
|
||
switch request.method { | ||
case .POST: | ||
sessionManager.post(request.path.rawValue, parameters: request.parameters, progress: nil, success: successBlock, failure: failureBlock) | ||
case .PUT: | ||
sessionManager.put(request.path.rawValue, parameters: request.parameters, success: successBlock, failure: failureBlock) | ||
case .GET: | ||
sessionManager.get(request.path.rawValue, parameters: request.parameters, progress: nil, success: successBlock, failure: failureBlock) | ||
} | ||
} | ||
|
||
func handleDynamicBaseUrl(response: URLResponse?, error: NSError?) { | ||
if let error = error, error.mm_isCannotFindHost { | ||
storeDynamicBaseUrl(nil) | ||
dynamicBaseUrl = originalBaseUrl | ||
} else { | ||
if let httpResponse = response as? HTTPURLResponse, let newBaseUrlString = httpResponse.allHeaderFields[DynamicBaseUrlConsts.newBaseUrlHeader] as? String, let newDynamicBaseUrl = URL(string: newBaseUrlString) { | ||
storeDynamicBaseUrl(newDynamicBaseUrl) | ||
dynamicBaseUrl = newDynamicBaseUrl | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 7 additions & 7 deletions
14
Classes/Core/HTTP/RemoteAPIManager.swift → Classes/Core/HTTP/RemoteAPIProvider.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.