/NetworkStack

Network layer wrapping Alamofire, Rx, OAuth and replay mechanism in a reactive abstract API

Primary LanguageSwiftApache License 2.0Apache-2.0

NetworkStack

Language: Swift 4 CocoaPods compatible CocoaPods Twitter CocoaPods

NetworkStack is an networking library wrapping Alamofire, Rx, OAuth and replay mechanism in a reactive abstract API.

Features

This library features the following:

  • Wraps your network calls into a RxSwift-compatible API, returning Observable<T> values rather than using completion blocks
  • Handles the OAuth authentication workflow, allowing you to specify the credentials (which are stored in the Keychain) and let the library use them to enrich your authenticated requests for you
  • Handles auto-retry in case of 401 authentication errors:
    • letting you execute the refreshToken request, then replay the request automatically
    • letting you present arbitrary login screen when credentials must be asked to the user in case the refreshToken isn't valid or available
  • Simplifies the API so that your WebService client has a simple (and Alamofire-agnostic) API to call when it needs to send requests, without worrying about the internals.

Installation

CocoaPods

Using CocoaPods is the recommended way :

  • In your Podfile, add use_frameworks! and pod NetworkStack to your main and test targets.
  • Run pod repo update to make CocoaPods aware of the latest available NetworkStack versions.
  • Simply add pod 'NetworkStack' to your Podfile.
pod 'NetworkStack'

From the command line, run pod install

Documentation & Usage Examples

We have specific wiki. It will be helpful for you if you want to implement advanced or specific behaviour :



Simple Usage

Setup

let baseStringURL = "http://networkstack.fr/api/v1"
let keychainService: KeychainService = KeychainService(serviceType: "com.networkstack.keychain")
let networkStack = NetworkStack(baseURL: baseStringURL, keychainService: keychainService)

You can customize your request in many way. Feel free to create your SessionManager to change behaviour of requesting inside NetworkStack. NetworkStack has two properties that you can set :

  • requestManager: Alamofire.SessionManager is Alamofire.SessionManager() by default
  • uploadManager: Alamofire.SessionManager is nil by default

Routes as Routable protocol

NetworkStack has Routable protocol to create path for endpoints of your requests.

public struct Route: Routable {
  public let path: String
  init(path: String) { self.path = path }
}

extension Route: CustomStringConvertible {
  public var description: String { return path }
}

extension Route {
  public static func authent() -> Route { return Route(path: "/authent") }
}

This is an implementation example but you are free to use it like you want.

Request parameters

This is the core of requests creation. Request parameters can take :

RequestParameters :

  • method: Alamofire.HTTPMethod
  • route: Routable
  • needsAuthorization: Bool = false
  • parameters: Alamofire.Parameters? = nil
  • parametersEncoding: Alamofire.ParameterEncoding = JSONEncoding.default
  • headers: Alamofire.HTTPHeaders? = nil
let requestParameters = RequestParameters(method: .get,
                                          route: Route.authent(),
                                          parameters: nil, // [String: Any] type
                                          needsAuthorization: false,
                                          parametersEncoding: URLEncoding.httpBody,
                                          headers: nil) // [String: String] type

*For Upload : UploadRequestParameters :

  • method: Alamofire.HTTPMethod = .post
  • route: Routable
  • needsAuthorization: Bool = true
  • uploadFiles: [UploadRequestParametersFile]
  • parameters: Alamofire.Parameters? = nil
  • headers: Alamofire.HTTPHeaders? = nil

Requests

In public interface you can find this few methods that help you to send requests.

func sendRequestWithDataResponse(requestParameters: RequestParameters) -> Observable<(HTTPURLResponse, Data)>

func sendRequestWithJSONResponse(requestParameters: RequestParameters) -> Observable<(HTTPURLResponse, Any)>

// For Uploads
func sendUploadRequestWithDataResponse(uploadRequestParameters: UploadRequestParameters) -> Observable<(HTTPURLResponse, Data)>

func sendUploadRequestWithDataResponse(uploadRequestParameters: UploadRequestParameters) -> Observable<(HTTPURLResponse, Any)>

func sendBackgroundUploadRequest(uploadRequestParameters: UploadRequestParameters) -> Observable<URLSessionTask>

Send request and response

networkStack.sendRequestWithJSONResponse(requestParameters: requestParameters)
  .subscribe({ (event: Event<(HTTPURLResponse, Any)>) in
    switch event {
    case .next(let json):
      // do something with the json response or statusCode
      break
    case .error(let error):
      // do something with NetworkStackError
      break
    case .completed:
      // do something when observable completed
      break
    }
  }).addDisposableTo(self.disposeBag)

Errors

Network stack provides several errors that you can handles in your app.

public enum NetworkStackError: Error {
  /// No internet, roaming off, data not allowed, call active, …
  case noInternet(error: Error)
  /// DNS Lookup failed, Host unreachable, …
  case serverUnreachable(error: Error)
  /// Invalid request, Fail to parse JSON, Unable to decode payload…
  case badServerResponse(error: Error)
  /// Response in 4xx-5xx range
  case http(httpURLResponse: HTTPURLResponse, data: Data?)
  /// Fail to parse response
  case parseError
  /// Other, unclassified error
  case otherError(error: Error)
  /// Request building has failed
  case requestBuildFail
  /// Upload manager has not been setup
  case uploadManagerIsNotSet
  /// Unknown
  case unknown
}

More examples & Help Topics

We have some examples :

Feedback

  • If you found a bug , open an issue
  • If you have a feature request , open an issue
  • If you want to contribute , submit a pull request

License

This code is distributed under the Apache 2 License.