Created
December 7, 2016 17:16
-
-
Save soxjke/0dfa399be2b6f88dbbd328010ce1948b to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| extension APIService { | |
| // MARK: - AddressAPI | |
| func addressGetUserAddress() -> Signal<ResponseResult<Address>, NoError> { | |
| let converter:(Signal<ResponseResult<Address>, NoError>, Observer<ResponseResult<Address>, NoError>) = createSignal() | |
| let request = AdreessGetHomeAddressRequest(token: authorizationService.token) | |
| executeRequest(request).observeValues { (response) in | |
| let parsedResponse:ResponseResult<Address> = ResponseResult(response: response, mappingFunction: request.mapper) | |
| converter.1.send(value: parsedResponse) | |
| } | |
| return converter.0 | |
| } | |
| func addressGetSelectedAddress() -> Signal<ResponseResult<Address>, NoError> { | |
| let converter:(Signal<ResponseResult<Address>, NoError>, Observer<ResponseResult<Address>, NoError>) = createSignal() | |
| let request = AdreessGetSelectedAddressRequest(token: authorizationService.token) | |
| executeRequest(request).observeValues { (response) in | |
| let parsedResponse:ResponseResult<Address> = ResponseResult(response: response, mappingFunction: request.mapper) | |
| converter.1.send(value: parsedResponse) | |
| } | |
| return converter.0 | |
| } | |
| func addressRegisterUserAddress(_ address:Address) -> Signal<ResponseResult<Address>, NoError> { | |
| let converter:(Signal<ResponseResult<Address>, NoError>, Observer<ResponseResult<Address>, NoError>) = createSignal() | |
| let request = AdressRegisterHomeAddress(token: authorizationService.token, address: address) | |
| executeRequest(request).observeValues { (response) in | |
| let parsedResponse:ResponseResult<Address> = ResponseResult(response: response, mappingFunction: request.mapper) | |
| converter.1.send(value: parsedResponse) | |
| } | |
| return converter.0 | |
| } | |
| func addressRegisterNewAddress(_ address:Address) -> Signal<ResponseResult<Address>, NoError> { | |
| let converter:(Signal<ResponseResult<Address>, NoError>, Observer<ResponseResult<Address>, NoError>) = createSignal() | |
| let request = AdressRegisterSelectedAddress(token: authorizationService.token, address: address) | |
| executeRequest(request).observeValues { (response) in | |
| let parsedResponse:ResponseResult<Address> = ResponseResult(response: response, mappingFunction: request.mapper) | |
| converter.1.send(value: parsedResponse) | |
| } | |
| return converter.0 | |
| } | |
| } |
This file contains hidden or 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
| class AdressRegisterSelectedAddress: BaseRequest <Address> { | |
| var address:Address? | |
| override var HTTPMethod: RequestType { | |
| get { | |
| return .POST | |
| } | |
| } | |
| override var endPoint: String { | |
| get { | |
| return "/api/address/selected/register" | |
| } | |
| } | |
| override var bodyParameters:[String:AnyObject]? { | |
| get { | |
| let addressJSON = address?.toJSON() | |
| return addressJSON as [String : AnyObject]? | |
| } | |
| } | |
| // MARK: - LifeCycle | |
| convenience init(token: Token?, address:Address) { | |
| self.init(token: token) | |
| self.address = address | |
| } | |
| // MARK: - Private | |
| override func mapFunction(_ source:AnyObject?) -> Address? { | |
| var data:Address? = nil | |
| if let jsonDic = source as? [String:AnyObject] { | |
| data = Mapper<Address>().map(JSON:jsonDic) | |
| } | |
| return data | |
| } | |
| } |
This file contains hidden or 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
| class APIService { | |
| fileprivate static let baseURL:String = "" | |
| fileprivate let requestor:NetModule = NetModule(configuration: NetConfig(cacheSize: 250, pinnedHosts: [""]), baseURL: baseURL) | |
| fileprivate var analyzer:Analyzable? | |
| fileprivate var accessHandler:(()->())? | |
| fileprivate var invalidAccessSignal:(Signal<Bool, NoError>, Observer<Bool, NoError>)? | |
| var authorizationService: AuthentificationService = AuthentificationService(baseURL: baseURL) | |
| // MARK: - LifeCycle | |
| init() { } | |
| convenience init(accessHandler:@escaping (()->()), analyzer:Analyzable? = nil) { | |
| self.init() | |
| self.accessHandler = accessHandler | |
| self.analyzer = analyzer | |
| invalidAccessSignal = createSignal() | |
| let _ = invalidAccessSignal?.0.throttle(3.0, on: QueueScheduler.main).observeValues({ (invalid) in | |
| if invalid == true { | |
| self.accessHandler?() | |
| } | |
| }) | |
| } | |
| // MARK: - Public | |
| func executeRequest(_ executingRequest:Requestable) -> Signal<ProcessedResponse, NoError> { | |
| let signalProvider:(Signal<ProcessedResponse, NoError>, Observer<ProcessedResponse, NoError>) = createSignal() | |
| requestor.performRequest(executingRequest).observeValues { [weak self] (processedResponse) in | |
| self?.analyzer?.analyzeResponse(processedResponse) | |
| if processedResponse.needRefresh == true { | |
| let _ = self?.authorizationService.refresh().observeValues({ (token) in | |
| if let tokenString = token?.refreshToken { | |
| if tokenString.characters.count > 0 { | |
| var updatedRequest = executingRequest | |
| updatedRequest.token = token | |
| let _ = self?.requestor.performRequest(updatedRequest).observeValues({ (response) in | |
| signalProvider.1.send(value: processedResponse) | |
| }) | |
| } | |
| } else { | |
| self?.invalidAccessSignal?.1.send(value: true) | |
| } | |
| }) | |
| } else { | |
| signalProvider.1.send(value: processedResponse) | |
| } | |
| } | |
| return signalProvider.0 | |
| } | |
| // MARK: - Servisable | |
| func createSignal<T>() -> (signal:Signal<T, NoError>, signalObserver:Observer<T, NoError>) { | |
| let signal : Signal<T, NoError> | |
| let observer : Observer<T, NoError> | |
| (signal, observer) = Signal<T, NoError>.pipe() | |
| return (signal, observer) | |
| } | |
| } |
This file contains hidden or 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
| final class AuthentificationService : Authorizable { | |
| fileprivate var networkModule : NetworkRequestable = NetModule() | |
| fileprivate var refreshSignal : Signal<Token?, NoError>? = nil | |
| // MARK: - LifeCycle | |
| init() { } | |
| convenience init(baseURL:String) { | |
| self.init() | |
| networkModule = NetModule(baseURL: baseURL) | |
| } | |
| // MARK: - Public | |
| func authenticate(_ login: String, password: String) -> Signal<String?, NoError> { | |
| let authRequest = AuthorizationRequest(userName: login, password: password) | |
| return networkModule.performRequest(authRequest).map({ (response) -> String? in | |
| let parsedResponse = ResponseResult<Token>(response: response, mappingFunction: authRequest.mapper) | |
| let object = parsedResponse.convertedResponse?.accessToken | |
| self.storedToken = parsedResponse.convertedResponse | |
| return object | |
| }) | |
| } | |
| func refresh() -> Signal<Token?, NoError> { | |
| if refreshSignal == nil { | |
| let signal : Signal<Token?, NoError> | |
| let observer : Observer<Token?, NoError> | |
| (signal, observer) = Signal<Token?, NoError>.pipe() | |
| refreshSignal = signal | |
| let refreshAuthRequest = RefreshTokenRequest(refreshToken: self.refreshToken) | |
| networkModule.performRequest(refreshAuthRequest).observeValues({ (response) in | |
| let parsedResponse = ResponseResult<Token>(response: response, mappingFunction: refreshAuthRequest.mapper) | |
| self.storedToken = parsedResponse.convertedResponse | |
| observer.send(value: parsedResponse.convertedResponse) | |
| self.refreshSignal = nil | |
| }) | |
| } | |
| return refreshSignal! | |
| } | |
| } |
This file contains hidden or 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
| class BaseRequest <T>: Requestable { | |
| var mapper : ((AnyObject?) -> T?)? | |
| var token:Token? | |
| var HTTPMethod: RequestType { | |
| get { | |
| return .UNKNOWN | |
| } | |
| } | |
| var endPoint: String { | |
| get { | |
| return "/" | |
| } | |
| } | |
| var urlParameters:[String:AnyObject]? { | |
| get { | |
| return nil | |
| } | |
| } | |
| var bodyParameters:[String:AnyObject]? { | |
| get { | |
| return nil | |
| } | |
| } | |
| var headers:[String:String]? { | |
| get { | |
| return nil | |
| } | |
| } | |
| // MARK: - LifeCycle | |
| init() { | |
| mapper = mapFunction | |
| } | |
| required convenience init(token: Token?) { | |
| self.init() | |
| self.token = token | |
| } | |
| // MARK: - Public | |
| func requestWithBaseUrl(_ baseURL:String) -> URLRequest { | |
| var requestPath = endPoint | |
| if let urlParameters = urlParameters { | |
| requestPath = requestPath + urlParameters.requestString() | |
| } | |
| let completePath = String(format: "%@%@", baseURL, requestPath) | |
| guard let cleanPath = completePath.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) else { return URLRequest(url:URL(fileURLWithPath: "\\")) } | |
| if let url = URL(string: cleanPath) { | |
| let request = NSMutableURLRequest(url: url) | |
| request.httpMethod = HTTPMethod.rawValue | |
| if let bodyParameters = bodyParameters { | |
| if let data = Data.jsonDataFromDictionary(bodyParameters) { | |
| request.httpBody = data | |
| } | |
| } | |
| var headers:[String:String] = [:] | |
| if let additionalHeaders = self.headers { | |
| headers = headers + additionalHeaders | |
| } | |
| if let accessToken = token?.accessToken { | |
| headers = headers + ["Authorization": "Bearer " + accessToken] | |
| } | |
| request.allHTTPHeaderFields = headers | |
| return request as URLRequest | |
| } | |
| return URLRequest(url:URL(fileURLWithPath: "\\")) | |
| } | |
| // MARK: - Ovverride | |
| func mapFunction(_ source:AnyObject?) -> T? { | |
| return nil | |
| } | |
| } |
This file contains hidden or 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
| final class NetModule : NetworkRequestable { | |
| fileprivate var currentSession: URLSession? | |
| fileprivate var baseURL: String? | |
| fileprivate var sessionDelegate: NetSessionDelegate | |
| // MARK: - LifeCycle | |
| init() { sessionDelegate = NetSessionDelegate(configuration: nil) } | |
| convenience init(configuration:NetworkConfigurable? = nil, baseURL:String) { | |
| self.init() | |
| sessionDelegate = NetSessionDelegate(configuration: configuration) | |
| setup(configuration) | |
| self.baseURL = baseURL | |
| } | |
| // MARK: - Public | |
| func performRequest(_ request: Requestable) -> Signal<ProcessedResponse, NoError> { | |
| let signal = Signal<ProcessedResponse, NoError>( { [weak self] (observer) -> Disposable? in | |
| guard let baseURL = self?.baseURL, | |
| let currentSession = self?.currentSession else { | |
| return nil | |
| } | |
| let urlRequest = request.requestWithBaseUrl(baseURL) | |
| let timeLine = NetTimeLine() | |
| let task = currentSession.dataTask(with: urlRequest, completionHandler: { (data, response, error) in | |
| timeLine.complete() | |
| let response:NetResponse = NetResponse(request:request, responseData: data, response: response, error: error as NSError?, timeline:timeLine) | |
| let proceededResponse = ResponseConverter.convert(response) | |
| DispatchQueue.main.async { | |
| observer.send(value: proceededResponse) | |
| } | |
| }) | |
| task.resume() | |
| let disposable = ActionDisposable(action: { | |
| task.cancel() | |
| }) | |
| return disposable | |
| }) | |
| return signal | |
| } | |
| // MARK: - Private | |
| fileprivate func setup(_ configuration:NetworkConfigurable? = nil) { | |
| if let config = configuration { | |
| currentSession = URLSession(configuration: config.configuration, delegate: sessionDelegate, delegateQueue: OperationQueue()) | |
| } else { | |
| let configuration = NetConfig(cacheSize: 250) | |
| currentSession = URLSession(configuration: configuration.configuration, delegate: sessionDelegate, delegateQueue: OperationQueue()) | |
| } | |
| } | |
| } |
This file contains hidden or 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
| import UIKit | |
| enum RequestType:String { | |
| case UNKNOWN | |
| case POST | |
| case PUT | |
| case DELETE | |
| case GET | |
| } | |
| protocol Requestable { | |
| func requestWithBaseUrl(_ baseURL:String) -> URLRequest | |
| var token:Token? {get set} | |
| var HTTPMethod:RequestType {get} | |
| var endPoint:String {get} | |
| var urlParameters:[String:AnyObject]? {get} | |
| var bodyParameters:[String:AnyObject]? {get} | |
| var headers:[String:String]? {get} | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment