NetworkStack is an networking library wrapping Alamofire, Rx, OAuth and replay mechanism in a reactive abstract API.
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.
Using CocoaPods is the recommended way :
- In your Podfile, add
use_frameworks!and podNetworkStackto your main and test targets. - Run
pod repo updateto make CocoaPods aware of the latest availableNetworkStackversions. - Simply add
pod 'NetworkStack'to yourPodfile.
pod 'NetworkStack'From the command line, run pod install
We have specific wiki. It will be helpful for you if you want to implement advanced or specific behaviour :
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.SessionManagerisAlamofire.SessionManager()by default - uploadManager:
Alamofire.SessionManagerisnilby default
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.
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
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>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)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
}We have some examples :
- 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
This code is distributed under the Apache 2 License.
